X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=surf.c;h=9a621e61618151956a8ee5fc239bb8dc38cc665b;hb=3083ef4031aaf48926497397295b0db639a6a9c1;hp=1a1aae45aa7ef8feefc6fde8d3f4841ff075f64d;hpb=36129338cfd64fd9aee8862060cddfd186d8b486;p=surf.git diff --git a/surf.c b/surf.c index 1a1aae4..9a621e6 100644 --- a/surf.c +++ b/surf.c @@ -21,9 +21,8 @@ #include #define LENGTH(x) (sizeof x / sizeof x[0]) -#define CLEANMASK(mask) (mask & ~(GDK_MOD2_MASK)) -enum { AtomFind, AtomGo, AtomUri, AtomHiLight, AtomLast }; +enum { AtomFind, AtomGo, AtomUri, AtomLast }; typedef union Arg Arg; union Arg { @@ -38,6 +37,7 @@ typedef struct Client { char *title, *linkhover; const char *uri, *needle; gint progress; + gboolean sslfailed; struct Client *next; gboolean zoomed; } Client; @@ -81,6 +81,7 @@ static const char *getatom(Client *c, int a); static const char *getcookies(SoupURI *uri); static char *geturi(Client *c); void gotheaders(SoupMessage *msg, gpointer user_data); +static gboolean initdownload(WebKitWebView *v, WebKitDownload *o, Client *c); static gboolean keypress(GtkWidget *w, GdkEventKey *ev, Client *c); static void linkhover(WebKitWebView *v, const char* t, const char* l, Client *c); static void loadstatuschange(WebKitWebView *view, GParamSpec *pspec, Client *c); @@ -95,13 +96,16 @@ static GdkFilterReturn processx(GdkXEvent *xevent, GdkEvent *event, gpointer d); static void progresschange(WebKitWebView *view, GParamSpec *pspec, Client *c); static void reload(Client *c, const Arg *arg); static void resize(GtkWidget *w, GtkAllocation *a, Client *c); -static void scroll(Client *c, const Arg *arg); +static void scroll_h(Client *c, const Arg *arg); +static void scroll_v(Client *c, const Arg *arg); +static void scroll(GtkAdjustment *a, const Arg *arg); static void setatom(Client *c, int a, const char *v); static void setcookie(SoupCookie *c); static void setup(void); static void sigchld(int unused); static void source(Client *c, const Arg *arg); static void spawn(Client *c, const Arg *arg); +static void eval(Client *c, const Arg *arg); static void stop(Client *c, const Arg *arg); static void titlechange(WebKitWebView *v, WebKitWebFrame* frame, const char* title, Client *c); static void update(Client *c); @@ -125,12 +129,15 @@ buildpath(const char *path) { apath = g_strconcat(g_get_home_dir(), "/", path, NULL); if((p = strrchr(apath, '/'))) { *p = '\0'; - g_mkdir_with_parents(apath, 0755); + g_mkdir_with_parents(apath, 0700); + g_chmod(apath, 0700); /* in case it existed */ *p = '/'; } /* creating file (gives error when apath ends with "/") */ - if((f = fopen(apath, "a"))) + if((f = fopen(apath, "a"))) { + g_chmod(apath, 0600); /* always */ fclose(f); + } return apath; } @@ -143,16 +150,25 @@ cleanup(void) { g_free(stylefile); } +void +evalscript(WebKitWebFrame *frame, JSContextRef js, char *script, char* scriptname) { + JSStringRef jsscript, jsscriptname; + JSValueRef exception = NULL; + + jsscript = JSStringCreateWithUTF8CString(script); + jsscriptname = JSStringCreateWithUTF8CString(scriptname); + JSEvaluateScript(js, jsscript, JSContextGetGlobalObject(js), jsscriptname, 0, &exception); + JSStringRelease(jsscript); + JSStringRelease(jsscriptname); +} + void runscript(WebKitWebFrame *frame, JSContextRef js) { - JSStringRef jsscript; char *script; - JSValueRef exception = NULL; GError *error; - + if(g_file_get_contents(scriptfile, &script, NULL, &error)) { - jsscript = JSStringCreateWithUTF8CString(script); - JSEvaluateScript(js, jsscript, JSContextGetGlobalObject(js), NULL, 0, &exception); + evalscript(frame, webkit_web_frame_get_global_context(frame), script, scriptfile); } } @@ -187,10 +203,7 @@ createwindow(WebKitWebView *v, WebKitWebFrame *f, Client *c) { gboolean decidedownload(WebKitWebView *v, WebKitWebFrame *f, WebKitNetworkRequest *r, gchar *m, WebKitWebPolicyDecision *p, Client *c) { if(!webkit_web_view_can_show_mime_type(v, m)) { - webkit_web_policy_decision_ignore(p); - webkit_web_view_load_html_string(c->view, - "Can't display content.", - webkit_network_request_get_uri(r)); + webkit_web_policy_decision_download(p); return TRUE; } return FALSE; @@ -213,6 +226,7 @@ void destroyclient(Client *c) { Client *p; + webkit_web_view_stop_loading(c->view); gtk_widget_destroy(c->indicator); gtk_widget_destroy(GTK_WIDGET(c->view)); gtk_widget_destroy(c->scroll); @@ -252,8 +266,11 @@ drawindicator(Client *c) { w = c->indicator; width = c->progress * w->allocation.width / 100; gc = gdk_gc_new(w->window); - gdk_color_parse(strstr(uri, "https://") == uri ? - progress_trust : progress, &fg); + if(strstr(uri, "https://") == uri) + gdk_color_parse(c->sslfailed ? + progress_untrust : progress_trust, &fg); + else + gdk_color_parse(progress, &fg); gdk_gc_set_rgb_fg_color(gc, &fg); gdk_draw_rectangle(w->window, w->style->bg_gc[GTK_WIDGET_STATE(w)], @@ -328,6 +345,16 @@ gotheaders(SoupMessage *msg, gpointer v) { soup_cookies_free(l); } +gboolean +initdownload(WebKitWebView *view, WebKitDownload *o, Client *c) { + Arg arg; + + updatewinid(c); + arg = (Arg)DOWNLOAD((char *)webkit_download_get_uri(o)); + spawn(c, &arg); + return FALSE; +} + gboolean keypress(GtkWidget* w, GdkEventKey *ev, Client *c) { guint i; @@ -336,7 +363,7 @@ keypress(GtkWidget* w, GdkEventKey *ev, Client *c) { updatewinid(c); for(i = 0; i < LENGTH(keys); i++) { if(gdk_keyval_to_lower(ev->keyval) == keys[i].keyval - && CLEANMASK(ev->state) == keys[i].mod + && (ev->state & keys[i].mod) == keys[i].mod && keys[i].func) { keys[i].func(c, &(keys[i].arg)); processed = TRUE; @@ -359,9 +386,24 @@ linkhover(WebKitWebView *v, const char* t, const char* l, Client *c) { void loadstatuschange(WebKitWebView *view, GParamSpec *pspec, Client *c) { + WebKitWebFrame *frame; + WebKitWebDataSource *src; + WebKitNetworkRequest *request; + SoupMessage *msg; + char *uri; + switch(webkit_web_view_get_load_status (c->view)) { case WEBKIT_LOAD_COMMITTED: - setatom(c, AtomUri, geturi(c)); + uri = geturi(c); + if(strstr(uri, "https://") == uri) { + frame = webkit_web_view_get_main_frame(c->view); + src = webkit_web_frame_get_data_source(frame); + request = webkit_web_data_source_get_request(src); + msg = webkit_network_request_get_message(request); + c->sslfailed = soup_message_get_flags(msg) + ^ SOUP_MESSAGE_CERTIFICATE_TRUSTED; + } + setatom(c, AtomUri, uri); break; case WEBKIT_LOAD_FINISHED: c->progress = 0; @@ -424,7 +466,7 @@ newclient(void) { * window class (WM_CLASS) is capped, while the resource is in * lowercase. Both these values come as a pair. */ - gtk_window_set_wmclass(GTK_WINDOW(c->win), "surf", "surf"); + gtk_window_set_wmclass(GTK_WINDOW(c->win), "surf", "Surf"); /* TA: 20091214: And set the role here as well -- so that * sessions can pick this up. @@ -454,6 +496,7 @@ newclient(void) { g_signal_connect(G_OBJECT(c->view), "window-object-cleared", G_CALLBACK(windowobjectcleared), c); g_signal_connect(G_OBJECT(c->view), "notify::load-status", G_CALLBACK(loadstatuschange), c); g_signal_connect(G_OBJECT(c->view), "notify::progress", G_CALLBACK(progresschange), c); + g_signal_connect(G_OBJECT(c->view), "download-requested", G_CALLBACK(initdownload), c); /* Indicator */ c->indicator = gtk_drawing_area_new(); @@ -491,11 +534,13 @@ newclient(void) { g_object_set(G_OBJECT(settings), "auto-load-images", loadimage, NULL); g_object_set(G_OBJECT(settings), "enable-plugins", plugin, NULL); g_object_set(G_OBJECT(settings), "enable-scripts", script, NULL); + g_object_set(G_OBJECT(settings), "enable-spatial-navigation", SPATIAL_BROWSING, NULL); + g_free(uri); setatom(c, AtomFind, ""); setatom(c, AtomUri, "about:blank"); - if(NOBACKGROUND) + if(HIDE_BACKGROUND) webkit_web_view_set_transparent(c->view, TRUE); c->title = NULL; @@ -505,6 +550,9 @@ newclient(void) { gdk_display_sync(gtk_widget_get_display(c->win)); printf("%u\n", (guint)GDK_WINDOW_XID(GTK_WIDGET(c->win)->window)); fflush(NULL); + if (fclose(stdout) != 0) { + die("Error closing stdout"); + } } return c; } @@ -616,16 +664,32 @@ resize(GtkWidget *w, GtkAllocation *a, Client *c) { } void -scroll(Client *c, const Arg *arg) { - gdouble v; - GtkAdjustment *a; +scroll_h(Client *c, const Arg *arg) { + scroll(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(c->scroll)), arg); +} - a = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(c->scroll)); - v = gtk_adjustment_get_value(a); - v += gtk_adjustment_get_step_increment(a) * arg->i; - v = MAX(v, 0.0); - v = MIN(v, gtk_adjustment_get_upper(a) - gtk_adjustment_get_page_size(a)); - gtk_adjustment_set_value(a, v); +void +scroll_v(Client *c, const Arg *arg) { + scroll(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(c->scroll)), arg); +} + +void +scroll(GtkAdjustment *a, const Arg *arg) { + gdouble v; + + v = gtk_adjustment_get_value(a); + switch (arg->i){ + case +10000: + case -10000: + v += gtk_adjustment_get_page_increment(a) * (arg->i / 10000); break; + case +20000: + case -20000: + default: + v += gtk_adjustment_get_step_increment(a) * arg->i; + } + v = MAX(v, 0.0); + v = MIN(v, gtk_adjustment_get_upper(a) - gtk_adjustment_get_page_size(a)); + gtk_adjustment_set_value(a, v); } void @@ -675,7 +739,6 @@ setup(void) { atoms[AtomFind] = XInternAtom(dpy, "_SURF_FIND", False); atoms[AtomGo] = XInternAtom(dpy, "_SURF_GO", False); atoms[AtomUri] = XInternAtom(dpy, "_SURF_URI", False); - atoms[AtomHiLight] = XInternAtom(dpy, "_SURF_HILIGHT", False); /* dirs and files */ cookiefile = buildpath(cookiefile); @@ -688,6 +751,10 @@ setup(void) { soup_session_remove_feature_by_type(s, soup_cookie_jar_get_type()); g_signal_connect_after(G_OBJECT(s), "request-started", G_CALLBACK(newrequest), NULL); + /* ssl */ + g_object_set(G_OBJECT(s), "ssl-ca-file", cafile, NULL); + g_object_set(G_OBJECT(s), "ssl-strict", strictssl, NULL); + /* proxy */ if((proxy = getenv("http_proxy")) && strcmp(proxy, "")) { new_proxy = g_strrstr(proxy, "http://") ? g_strdup(proxy) : @@ -729,6 +796,12 @@ spawn(Client *c, const Arg *arg) { } } +void +eval(Client *c, const Arg *arg) { + WebKitWebFrame *frame = webkit_web_view_get_main_frame(c->view); + evalscript(frame, webkit_web_frame_get_global_context(frame), ((char **)arg->v)[0], ""); +} + void stop(Client *c, const Arg *arg) { webkit_web_view_stop_loading(c->view); @@ -744,10 +817,10 @@ void update(Client *c) { char *t; - if(c->progress != 100) - t = g_strdup_printf("[%i%%] %s", c->progress, c->title); - else if(c->linkhover) + if(c->linkhover) t = g_strdup(c->linkhover); + else if(c->progress != 100) + t = g_strdup_printf("[%i%%] %s", c->progress, c->title); else t = g_strdup(c->title); drawindicator(c); @@ -818,7 +891,7 @@ main(int argc, char *argv[]) { showxid = TRUE; break; case 'v': - die("surf-"VERSION", © 2009 surf engineers, see LICENSE for details\n"); + die("surf-"VERSION", ©2009-2012 surf engineers, see LICENSE for details\n"); default: usage(); }