X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=surf.c;h=0fae80bf2c2a27903fdacd6f7f61dac577597489;hb=c81fbbaf43535781cbc86904c361a57823b6de50;hp=42dbf2116d990155dba3a86c5726478baa708545;hpb=68813b3a4640dcfcbe002a1ff5803f04b9c50c06;p=surf.git diff --git a/surf.c b/surf.c index 42dbf21..0fae80b 100644 --- a/surf.c +++ b/surf.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "arg.h" @@ -35,6 +37,15 @@ char *argv0; #define COOKIEJAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COOKIEJAR_TYPE, CookieJar)) enum { AtomFind, AtomGo, AtomUri, AtomLast }; +enum { + ClkDoc = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT, + ClkLink = WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK, + ClkImg = WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE, + ClkMedia = WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA, + ClkSel = WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION, + ClkEdit = WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE, + ClkAny = ClkDoc | ClkLink | ClkImg | ClkMedia | ClkSel | ClkEdit, +}; typedef union Arg Arg; union Arg { @@ -61,6 +72,14 @@ typedef struct { const Arg arg; } Key; +typedef struct { + unsigned int click; + unsigned int mask; + guint button; + void (*func)(Client *c, const Arg *arg); + const Arg arg; +} Button; + typedef struct { SoupCookieJarText parent_instance; int lock; @@ -96,9 +115,9 @@ static void addaccelgroup(Client *c); static void beforerequest(WebKitWebView *w, WebKitWebFrame *f, WebKitWebResource *r, WebKitNetworkRequest *req, WebKitNetworkResponse *resp, Client *c); +static char *buildfile(const char *path); static char *buildpath(const char *path); -static gboolean buttonrelease(WebKitWebView *web, GdkEventButton *e, - GList *gl); +static gboolean buttonrelease(WebKitWebView *web, GdkEventButton *e, Client *c); static void cleanup(void); static void clipboard(Client *c, const Arg *arg); @@ -168,6 +187,8 @@ static void print(Client *c, const Arg *arg); static GdkFilterReturn processx(GdkXEvent *xevent, GdkEvent *event, gpointer d); static void progresschange(WebKitWebView *view, GParamSpec *pspec, Client *c); +static void linkopen(Client *c, const Arg *arg); +static void linkopenembed(Client *c, const Arg *arg); static void reload(Client *c, const Arg *arg); static void scroll_h(Client *c, const Arg *arg); static void scroll_v(Client *c, const Arg *arg); @@ -179,6 +200,7 @@ static void source(Client *c, const Arg *arg); static void spawn(Client *c, const Arg *arg); static void stop(Client *c, const Arg *arg); static void titlechange(WebKitWebView *view, GParamSpec *pspec, Client *c); +static void titlechangeleave(void *a, void *b, Client *c); static void toggle(Client *c, const Arg *arg); static void togglecookiepolicy(Client *c, const Arg *arg); static void togglegeolocation(Client *c, const Arg *arg); @@ -213,6 +235,7 @@ beforerequest(WebKitWebView *w, WebKitWebFrame *f, WebKitWebResource *r, WebKitNetworkRequest *req, WebKitNetworkResponse *resp, Client *c) { const gchar *uri = webkit_network_request_get_uri(req); + int i, isascii = 1; if(g_str_has_suffix(uri, "/favicon.ico")) webkit_network_request_set_uri(req, "about:blank"); @@ -222,58 +245,93 @@ beforerequest(WebKitWebView *w, WebKitWebFrame *f, WebKitWebResource *r, && !g_str_has_prefix(uri, "about:") \ && !g_str_has_prefix(uri, "file://") \ && !g_str_has_prefix(uri, "data:") \ + && !g_str_has_prefix(uri, "blob:") \ && strlen(uri) > 0) { - handleplumb(c, w, uri); + + for(i = 0; i < strlen(uri); i++) { + if(!g_ascii_isprint(uri[i])) { + isascii = 0; + break; + } + } + if(isascii) + handleplumb(c, w, uri); } } static char * -buildpath(const char *path) { - char *apath, *p; +buildfile(const char *path) { + char *dname, *bname, *bpath, *fpath; FILE *f; - /* creating directory */ - if(path[0] == '/') { - apath = g_strdup(path); - } else if(path[0] == '~') { - if(path[1] == '/') { - apath = g_strconcat(g_get_home_dir(), &path[1], NULL); + dname = g_path_get_dirname(path); + bname = g_path_get_basename(path); + + bpath = buildpath(dname); + g_free(dname); + + fpath = g_build_filename(bpath, bname, NULL); + g_free(bname); + + if(!(f = fopen(fpath, "a"))) + die("Could not open file: %s\n", fpath); + + g_chmod(fpath, 0600); /* always */ + fclose(f); + + return fpath; +} + +static char * +buildpath(const char *path) { + struct passwd *pw; + char *apath, *name, *p, *fpath; + + if(path[0] == '~') { + if(path[1] == '/' || path[1] == '\0') { + p = (char *)&path[1]; + pw = getpwuid(getuid()); } else { - apath = g_strconcat(g_get_home_dir(), "/", - &path[1], NULL); + if((p = strchr(path, '/'))) + name = g_strndup(&path[1], --p - path); + else + name = g_strdup(&path[1]); + + if(!(pw = getpwnam(name))) { + die("Can't get user %s home directory: %s.\n", + name, path); + } + g_free(name); } + apath = g_build_filename(pw->pw_dir, p, NULL); } else { - apath = g_strconcat(g_get_current_dir(), "/", path, NULL); + apath = g_strdup(path); } - if((p = strrchr(apath, '/'))) { - *p = '\0'; - 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"))) { - g_chmod(apath, 0600); /* always */ - fclose(f); - } + /* creating directory */ + if(g_mkdir_with_parents(apath, 0700) < 0) + die("Could not access directory: %s\n", apath); + + fpath = realpath(apath, NULL); + g_free(apath); - return apath; + return fpath; } static gboolean -buttonrelease(WebKitWebView *web, GdkEventButton *e, GList *gl) { +buttonrelease(WebKitWebView *web, GdkEventButton *e, Client *c) { WebKitHitTestResultContext context; WebKitHitTestResult *result = webkit_web_view_get_hit_test_result(web, e); Arg arg; + unsigned int i; g_object_get(result, "context", &context, NULL); - if(context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) { - if(e->button == 2 || - (e->button == 1 && CLEANMASK(e->state) == CLEANMASK(MODKEY))) { - g_object_get(result, "link-uri", &arg.v, NULL); - newwindow(NULL, &arg, e->state & GDK_CONTROL_MASK); + g_object_get(result, "link-uri", &arg.v, NULL); + for(i = 0; i < LENGTH(buttons); i++) { + if(context & buttons[i].click && e->button == buttons[i].button && + CLEANMASK(e->state) == CLEANMASK(buttons[i].mask) && buttons[i].func) { + buttons[i].func(c, buttons[i].click == ClkLink && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); return true; } } @@ -282,7 +340,7 @@ buttonrelease(WebKitWebView *web, GdkEventButton *e, GList *gl) { static void cleanup(void) { - if (diskcache) { + if(diskcache) { soup_cache_flush(diskcache); soup_cache_dump(diskcache); } @@ -563,6 +621,9 @@ static gchar * getstyle(const char *uri) { int i; + if(stylefile != NULL) + return g_strconcat("file://", stylefile, NULL); + for(i = 0; i < LENGTH(styles); i++) { if(styles[i].regex && !regexec(&(styles[i].re), uri, 0, NULL, 0)) { @@ -694,7 +755,7 @@ loadstatuschange(WebKitWebView *view, GParamSpec *pspec, Client *c) { } setatom(c, AtomUri, uri); - if(stylefile == NULL && enablestyles) { + if(enablestyles) { g_object_set(G_OBJECT(set), "user-stylesheet-uri", getstyle(uri), NULL); } @@ -702,7 +763,7 @@ loadstatuschange(WebKitWebView *view, GParamSpec *pspec, Client *c) { case WEBKIT_LOAD_FINISHED: c->progress = 100; updatetitle(c); - if (diskcache) { + if(diskcache) { soup_cache_flush(diskcache); soup_cache_dump(diskcache); } @@ -760,7 +821,7 @@ newclient(void) { GdkGeometry hints = { 1, 1 }; GdkScreen *screen; gdouble dpi; - char *uri = NULL, *ua; + char *ua; if(!(c = calloc(1, sizeof(Client)))) die("Cannot malloc!\n"); @@ -792,6 +853,9 @@ newclient(void) { g_signal_connect(G_OBJECT(c->win), "destroy", G_CALLBACK(destroywin), c); + g_signal_connect(G_OBJECT(c->win), + "leave_notify_event", + G_CALLBACK(titlechangeleave), c); if(!kioskmode) addaccelgroup(c); @@ -890,9 +954,9 @@ newclient(void) { if(!(ua = getenv("SURF_USERAGENT"))) ua = useragent; g_object_set(G_OBJECT(settings), "user-agent", ua, NULL); - if (stylefile != NULL) { - uri = g_strconcat("file://", stylefile, NULL); - g_object_set(G_OBJECT(settings), "user-stylesheet-uri", uri, NULL); + if (enablestyles) { + g_object_set(G_OBJECT(settings), "user-stylesheet-uri", + getstyle("about:blank"), NULL); } g_object_set(G_OBJECT(settings), "auto-load-images", loadimages, NULL); @@ -948,9 +1012,6 @@ newclient(void) { fullscreen(c, NULL); } - if(stylefile != NULL) - g_free(uri); - setatom(c, AtomFind, ""); setatom(c, AtomUri, "about:blank"); if(hidebackground) @@ -1104,6 +1165,16 @@ progresschange(WebKitWebView *view, GParamSpec *pspec, Client *c) { updatetitle(c); } +static void +linkopen(Client *c, const Arg *arg) { + newwindow(NULL, arg, 1); +} + +static void +linkopenembed(Client *c, const Arg *arg) { + newwindow(NULL, arg, 0); +} + static void reload(Client *c, const Arg *arg) { gboolean nocache = *(gboolean *)arg; @@ -1178,11 +1249,11 @@ setup(void) { atoms[AtomUri] = XInternAtom(dpy, "_SURF_URI", False); /* dirs and files */ - cookiefile = buildpath(cookiefile); - scriptfile = buildpath(scriptfile); + cookiefile = buildfile(cookiefile); + scriptfile = buildfile(scriptfile); cachefolder = buildpath(cachefolder); styledir = buildpath(styledir); - if(stylefile == NULL && enablestyles) { + if(stylefile == NULL) { for(i = 0; i < LENGTH(styles); i++) { if(regcomp(&(styles[i].re), styles[i].regex, REG_EXTENDED)) { @@ -1191,12 +1262,12 @@ setup(void) { styles[i].regex); styles[i].regex = NULL; } - styles[i].style = buildpath( + styles[i].style = buildfile( g_strconcat(styledir, styles[i].style, NULL)); } } else { - stylefile = buildpath(stylefile); + stylefile = buildfile(stylefile); } /* request handler */ @@ -1227,8 +1298,12 @@ setup(void) { /* proxy */ if((proxy = getenv("http_proxy")) && strcmp(proxy, "")) { - new_proxy = g_strrstr(proxy, "http://") ? g_strdup(proxy) : - g_strdup_printf("http://%s", proxy); + new_proxy = g_strrstr(proxy, "http://") + || g_strrstr(proxy, "socks://") + || g_strrstr(proxy, "socks4://") + || g_strrstr(proxy, "socks5://") + ? g_strdup(proxy) + : g_strdup_printf("http://%s", proxy); puri = soup_uri_new(new_proxy); g_object_set(G_OBJECT(s), "proxy-uri", puri, NULL); soup_uri_free(puri); @@ -1288,6 +1363,12 @@ titlechange(WebKitWebView *view, GParamSpec *pspec, Client *c) { } } +static void +titlechangeleave(void *a, void *b, Client *c) { + c->linkhover = NULL; + updatetitle(c); +} + static void toggle(Client *c, const Arg *arg) { WebKitWebSettings *settings; @@ -1376,13 +1457,8 @@ togglestyle(Client *c, const Arg *arg) { WebKitWebSettings *settings = webkit_web_view_get_settings(c->view); char *uri; - g_object_get(G_OBJECT(settings), "user-stylesheet-uri", &uri, NULL); - if(stylefile == NULL && enablestyles) { - uri = (uri && uri[0])? g_strdup("") : getstyle(geturi(c)); - } else { - uri = uri[0]? g_strdup("") : g_strconcat("file://", - stylefile, NULL); - } + enablestyles = !enablestyles; + uri = enablestyles ? getstyle(geturi(c)) : g_strdup(""); g_object_set(G_OBJECT(settings), "user-stylesheet-uri", uri, NULL); updatetitle(c); @@ -1391,7 +1467,6 @@ togglestyle(Client *c, const Arg *arg) { static void gettogglestat(Client *c){ gboolean value; - char *uri; int p = 0; WebKitWebSettings *settings = webkit_web_view_get_settings(c->view); @@ -1414,8 +1489,7 @@ gettogglestat(Client *c){ g_object_get(G_OBJECT(settings), "enable-plugins", &value, NULL); togglestat[p++] = value? 'V': 'v'; - g_object_get(G_OBJECT(settings), "user-stylesheet-uri", &uri, NULL); - togglestat[p++] = (uri && uri[0]) ? 'M': 'm'; + togglestat[p++] = enablestyles ? 'M': 'm'; togglestat[p] = '\0'; }