diff --git a/src/ghtml-gtkhtml.c b/src/ghtml-gtkhtml.c index 74753ba..40aeb71 100644 --- a/src/ghtml-gtkhtml.c +++ b/src/ghtml-gtkhtml.c @@ -14,15 +14,13 @@ * Suite 330, Boston, MA 02111-1307 USA */ /* TODO: * - fix URL generation for relative path - * - update the URL of the main window * - implement selection * - more meaningful status updates * - implement cookies (beware same-origin policy) * - implement referer - * - implement POST * - implement history * - implement anchors - * - do we need to use html_stream_cancel? + * - probably need to implement html_stream_cancel * - need to take care of CSRF? eg remotely load local files */ @@ -82,19 +80,23 @@ struct _GHtmlConn /* http */ GConnHttp * http; + GConnHttpMethod http_method; + gchar * http_post; }; /* prototypes */ static GHtmlConn * _ghtmlconn_new(GHtml * ghtml, HtmlStream * stream, - gchar const * url); + gchar const * url, gchar const * post); static void _ghtmlconn_delete(GHtmlConn * ghtmlconn); static int _ghtml_set_base(GHtml * ghtml, char const * url); -static int _ghtml_document_load(GHtml * ghtml, gchar const * url); +static int _ghtml_document_load(GHtml * ghtml, gchar const * url, + gchar const * post); static gchar * _ghtml_make_url(gchar const * base, gchar const * url); +static void _ghtml_stop(GHtml * ghtml); static int _ghtml_stream_load(GHtml * ghtml, HtmlStream * stream, - gchar const * url); + gchar const * url, gchar const * post); /* callbacks */ static void _on_link_clicked(HtmlDocument * document, const gchar * url); @@ -233,7 +235,7 @@ void ghtml_load_url(GtkWidget * widget, char const * url) ghtml = g_object_get_data(G_OBJECT(widget), "ghtml"); if((link = _ghtml_make_url(NULL, url)) != NULL) url = link; - if(_ghtml_document_load(ghtml, url) != 0) + if(_ghtml_document_load(ghtml, url, NULL) != 0) { g_free(link); return; @@ -253,7 +255,8 @@ void ghtml_refresh(GtkWidget * widget) ghtml = g_object_get_data(G_OBJECT(widget), "ghtml"); if(ghtml->html_url == NULL) return; - _ghtml_document_load(ghtml, ghtml->html_url); + /* FIXME keep and warn about POST data */ + _ghtml_document_load(ghtml, ghtml->html_url, NULL); } @@ -279,9 +282,12 @@ void ghtml_select_all(GtkWidget * widget) /* ghtml_stop */ -void ghtml_stop(GtkWidget * ghtml) +void ghtml_stop(GtkWidget * widget) { - /* FIXME implement */ + GHtml * ghtml; + + ghtml = g_object_get_data(G_OBJECT(widget), "ghtml"); + _ghtml_stop(ghtml); } @@ -328,7 +334,7 @@ void ghtml_zoom_reset(GtkWidget * widget) /* private */ /* functions */ static GHtmlConn * _ghtmlconn_new(GHtml * ghtml, HtmlStream * stream, - gchar const * url) + gchar const * url, gchar const * post) { GHtmlConn ** p; GHtmlConn * c; @@ -361,7 +367,10 @@ static GHtmlConn * _ghtmlconn_new(GHtml * ghtml, HtmlStream * stream, c->file_size = 0; c->file_read = 0; c->http = NULL; - if(c->url == NULL) + c->http_method = (post == NULL) ? GNET_CONN_HTTP_METHOD_GET + : GNET_CONN_HTTP_METHOD_POST; + c->http_post = (post != NULL) ? g_strdup(post) : NULL; + if(c->url == NULL || (post != NULL && c->http_post == NULL)) { _ghtmlconn_delete(c); return NULL; @@ -412,6 +421,7 @@ static void _ghtmlconn_delete_file(GHtmlConn * ghtmlconn) static void _ghtmlconn_delete_http(GHtmlConn * ghtmlconn) { gnet_conn_http_delete(ghtmlconn->http); + g_free(ghtmlconn->http_post); } @@ -431,11 +441,15 @@ static int _ghtml_set_base(GHtml * ghtml, char const * url) /* ghtml_document_load */ -static int _ghtml_document_load(GHtml * ghtml, gchar const * url) +static int _ghtml_document_load(GHtml * ghtml, gchar const * url, + gchar const * post) { + _ghtml_stop(ghtml); + surfer_set_location(ghtml->surfer, url); + surfer_set_title(ghtml->surfer, NULL); html_document_open_stream(ghtml->html_document, "text/html"); return _ghtml_stream_load(ghtml, ghtml->html_document->current_stream, - url); + url, post); } @@ -476,6 +490,20 @@ static gchar * _ghtml_make_url(gchar const * base, gchar const * url) } +/* ghtml_stop */ +static void _ghtml_stop(GHtml * ghtml) +{ + size_t i; + + for(i = 0; i < ghtml->conns_cnt; i++) + if(ghtml->conns[i] != NULL) + _ghtmlconn_delete(ghtml->conns[i]); + free(ghtml->conns); + ghtml->conns = NULL; + ghtml->conns_cnt = 0; +} + + /* ghtml_stream_load */ static gboolean _stream_load_idle(gpointer data); static gboolean _stream_load_idle_directory(GHtmlConn * conn); @@ -494,11 +522,11 @@ static void _http_resolved(GConnHttpEventResolved * event, GHtmlConn * conn); static void _http_timeout(GHtmlConn * conn); static int _ghtml_stream_load(GHtml * ghtml, HtmlStream * stream, - gchar const * url) + gchar const * url, gchar const * post) { GHtmlConn * conn; - if((conn = _ghtmlconn_new(ghtml, stream, url)) == NULL) + if((conn = _ghtmlconn_new(ghtml, stream, url, post)) == NULL) return -1; g_idle_add(_stream_load_idle, conn); return 0; @@ -566,7 +594,7 @@ static gboolean _stream_load_idle_directory(GHtmlConn * conn) html_stream_write(conn->stream, tail, sizeof(tail) - 1); closedir(dir); surfer_set_progress(conn->ghtml->surfer, -1.0); - surfer_set_status(conn->ghtml->surfer, "Ready"); + surfer_set_status(conn->ghtml->surfer, NULL); _ghtmlconn_delete(conn); return FALSE; } @@ -627,7 +655,7 @@ static gboolean _stream_load_watch_file(GIOChannel * source, if(len == 0) /* no more data */ { surfer_set_progress(conn->ghtml->surfer, 1.0); - surfer_set_status(conn->ghtml->surfer, "Ready"); + surfer_set_status(conn->ghtml->surfer, NULL); _ghtmlconn_delete(conn); return FALSE; } @@ -649,8 +677,9 @@ static gboolean _stream_load_idle_http(GHtmlConn * conn) conn->http = gnet_conn_http_new(); gnet_conn_http_set_uri(conn->http, conn->url); gnet_conn_http_set_user_agent(conn->http, "DeforaOS " PACKAGE); - gnet_conn_http_set_method(conn->http, GNET_CONN_HTTP_METHOD_GET, NULL, - 0); + gnet_conn_http_set_method(conn->http, conn->http_method, + conn->http_post, (conn->http_post != NULL) + ? strlen(conn->http_post) : 0); gnet_conn_http_run_async(conn->http, _stream_load_watch_http, conn); return FALSE; } @@ -709,7 +738,7 @@ static void _http_data_complete(GConnHttpEventData * event, GHtmlConn * conn) html_stream_write(conn->stream, buf, size); surfer_set_progress(conn->ghtml->surfer, 1.0); } - surfer_set_status(conn->ghtml->surfer, "Ready"); + surfer_set_status(conn->ghtml->surfer, NULL); _ghtmlconn_delete(conn); } @@ -744,7 +773,7 @@ static void _http_error(GConnHttpEventError * event, GHtmlConn * conn) snprintf(buf, sizeof(buf), "%s %u", "Error", event->code); surfer_error(conn->ghtml->surfer, buf, 0); surfer_set_progress(conn->ghtml->surfer, -1.0); - surfer_set_status(conn->ghtml->surfer, "Ready"); + surfer_set_status(conn->ghtml->surfer, NULL); _ghtmlconn_delete(conn); } @@ -767,7 +796,7 @@ static void _http_resolved(GConnHttpEventResolved * event, GHtmlConn * conn) if(event->ia == NULL) { surfer_set_progress(conn->ghtml->surfer, -1.0); - surfer_set_status(conn->ghtml->surfer, "Ready"); + surfer_set_status(conn->ghtml->surfer, NULL); surfer_error(conn->ghtml->surfer, "Unknown host", 0); _ghtmlconn_delete(conn); } @@ -785,7 +814,7 @@ static void _http_timeout(GHtmlConn * conn) { surfer_error(conn->ghtml->surfer, "Timed out", 0); surfer_set_progress(conn->ghtml->surfer, -1.0); - surfer_set_status(conn->ghtml->surfer, "Ready"); + surfer_set_status(conn->ghtml->surfer, NULL); _ghtmlconn_delete(conn); } @@ -803,7 +832,7 @@ static void _on_link_clicked(HtmlDocument * document, const gchar * url) fprintf(stderr, "DEBUG: %s(\"%s\") base=\"%s\" => \"%s\"\n", __func__, url, ghtml->html_base, link); #endif - _ghtml_document_load(ghtml, link); + _ghtml_document_load(ghtml, link, NULL); g_free(link); } @@ -821,7 +850,7 @@ static void _on_request_url(HtmlDocument * document, const gchar * url, fprintf(stderr, "DEBUG: %s(\"%s\") base=\"%s\" => \"%s\"\n", __func__, url, ghtml->html_base, link); #endif - _ghtml_stream_load(ghtml, stream, link); + _ghtml_stream_load(ghtml, stream, link, NULL); g_free(link); } @@ -829,12 +858,16 @@ static void _on_request_url(HtmlDocument * document, const gchar * url, static void _on_set_base(HtmlDocument * document, const gchar * url) { GHtml * ghtml; + gchar * u; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, url); #endif ghtml = g_object_get_data(G_OBJECT(document), "ghtml"); - _ghtml_set_base(ghtml, url); + /* FIXME may fail */ + u = _ghtml_make_url(ghtml->html_base, url); + _ghtml_set_base(ghtml, u); + g_free(u); } @@ -842,23 +875,31 @@ static void _on_submit(HtmlDocument * document, const gchar * url, const gchar * method, const gchar * encoding) { GHtml * ghtml; + gchar * u; + gchar * v; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\", \"%s\", \"%s\")\n", __func__, url, method, encoding); #endif ghtml = g_object_get_data(G_OBJECT(document), "ghtml"); - if(strcmp(method, "GET") == 0) - _ghtml_document_load(ghtml, url); - else if(strcmp(method, "POST") == 0) - /* FIXME really use POST */ - _ghtml_document_load(ghtml, url); - else + if((u = _ghtml_make_url(ghtml->html_base, url)) == NULL) + return; /* FIXME report error */ + if(strcasecmp(method, "GET") == 0) { - /* FIXME implement */ - surfer_error(ghtml->surfer, "Unsupported method", 0); - return; + v = (encoding != NULL) ? g_strdup_printf("%s?%s", u, encoding) + : g_strdup(u); + if(v == NULL) + ; /* FIXME report error */ + else + _ghtml_document_load(ghtml, v, NULL); + g_free(v); } + else if(strcasecmp(method, "POST") == 0) + _ghtml_document_load(ghtml, u, encoding); + else + surfer_error(ghtml->surfer, "Unsupported method", 0); + g_free(u); } @@ -884,7 +925,7 @@ static void _on_url(HtmlView * view, const gchar * url) ghtml = g_object_get_data(G_OBJECT(view), "ghtml"); if(url == NULL) { - surfer_set_status(ghtml->surfer, "Ready"); + surfer_set_status(ghtml->surfer, NULL); return; } if((link = _ghtml_make_url(ghtml->html_base, url)) != NULL)