about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--xxxterm.c108
1 files changed, 75 insertions, 33 deletions
diff --git a/xxxterm.c b/xxxterm.c
index 32e25e4..51628f8 100644
--- a/xxxterm.c
+++ b/xxxterm.c
@@ -243,6 +243,7 @@ struct karg {
 /* defines */
 #define XT_NAME			("XXXTerm")
 #define XT_DIR			(".xxxterm")
+#define XT_CACHE_DIR		("cache")
 #define XT_CERT_DIR		("certs/")
 #define XT_SESSIONS_DIR		("sessions/")
 #define XT_CONF_FILE		("xxxterm.conf")
@@ -751,6 +752,7 @@ char			*fl_session_key;	/* favorites list */
 
 char			work_dir[PATH_MAX];
 char			certs_dir[PATH_MAX];
+char			cache_dir[PATH_MAX];
 char			sessions_dir[PATH_MAX];
 char			cookie_file[PATH_MAX];
 SoupURI			*proxy_uri = NULL;
@@ -4450,42 +4452,55 @@ done:
 }
 
 void
-favicon_download_status_changed_cb(WebKitDownload *download, GParamSpec *spec,
-    struct tab *t)
+load_favicon(struct tab *t)
 {
-	WebKitDownloadStatus status = webkit_download_get_status (download);
+	gchar *name_hash;
 	gint width, height;
 	char *file;
 	GdkPixbuf *pixbuf, *scaled;
 
-	switch (status) {
-	case WEBKIT_DOWNLOAD_STATUS_FINISHED:
-		asprintf(&file, "%s/%s/tab-%d.ico", pwd->pw_dir, XT_DIR,
-		   t->tab_id);
-		pixbuf = gdk_pixbuf_new_from_file(file, NULL);
-		g_object_get(pixbuf,
-			"width", &width,
-			"height", &height,
-			(char *)NULL);
-		DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon size %dx%d\n",
-		    __func__, t->tab_id, width, height);
-
-		if (width > 16 || height > 16) {
-			scaled = gdk_pixbuf_scale_simple(pixbuf, 16, 16,
-			    GDK_INTERP_BILINEAR);
-			g_object_unref(pixbuf);
-		} else {
-			scaled = pixbuf;
-		}
+	name_hash = g_compute_checksum_for_string(G_CHECKSUM_SHA256,
+	    t->icon_uri, -1);
+	asprintf(&file, "%s/%s.ico", cache_dir, name_hash);
+	g_free(name_hash);
+	pixbuf = gdk_pixbuf_new_from_file(file, NULL);
+	free(file);
+	if (!pixbuf) {
+		update_favicon(t);
+		return;
+	}
+	g_object_get(pixbuf,
+		"width", &width,
+		"height", &height,
+		(char *)NULL);
+	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon size %dx%d\n",
+	    __func__, t->tab_id, width, height);
+
+	if (width > 16 || height > 16) {
+		scaled = gdk_pixbuf_scale_simple(pixbuf, 16, 16,
+		    GDK_INTERP_BILINEAR);
+		g_object_unref(pixbuf);
+	} else {
+		scaled = pixbuf;
+	}
 
-		if (t->icon_pixbuf) {
-			g_object_unref(t->icon_pixbuf);
-		}
-		t->icon_pixbuf = scaled;
+	if (t->icon_pixbuf) {
+		g_object_unref(t->icon_pixbuf);
+	}
+	t->icon_pixbuf = scaled;
 
-		unlink(file);
-		free(file);
-		update_favicon(t);
+	update_favicon(t);
+}
+
+void
+favicon_download_status_changed_cb(WebKitDownload *download, GParamSpec *spec,
+    struct tab *t)
+{
+	WebKitDownloadStatus status = webkit_download_get_status (download);
+
+	switch (status) {
+	case WEBKIT_DOWNLOAD_STATUS_FINISHED:
+		load_favicon(t);
 		/* fallthrough */
 	case WEBKIT_DOWNLOAD_STATUS_ERROR:
 	case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
@@ -4501,7 +4516,9 @@ notify_icon_loaded_cb(WebKitWebView *wv, char *uri, struct tab *t)
 {
 	WebKitNetworkRequest	*request;
 	WebKitDownload		*download;
-	char			*dest_uri;
+	gchar			*name_hash;
+	char			*dest_uri, *file;
+	struct stat		sb;
 
 	if (uri == NULL || t == NULL)
 		errx(1, "%s: invalid pointers", __func__);
@@ -4511,7 +4528,6 @@ notify_icon_loaded_cb(WebKitWebView *wv, char *uri, struct tab *t)
 		}
 		free(t->icon_uri);
 	}
-
 	asprintf(&t->icon_uri, "%s", uri);
 	DNPRINTF(XT_D_DOWNLOAD, "%s: tab %d icon uri %s "
 	    "(dl!)\n", __func__, t->tab_id, uri);
@@ -4525,8 +4541,17 @@ notify_icon_loaded_cb(WebKitWebView *wv, char *uri, struct tab *t)
 	download = webkit_download_new(request);
 	g_object_unref(request);
 
-	asprintf(&dest_uri, "file://%s/%s/tab-%d.ico", pwd->pw_dir, XT_DIR,
-	    t->tab_id);
+	name_hash = g_compute_checksum_for_string(G_CHECKSUM_SHA256, uri, -1);
+	asprintf(&file, "%s/%s.ico", cache_dir, name_hash);
+	fflush(stderr);
+	g_free(name_hash);
+	if (!stat(file, &sb)) {
+		free(file);
+		load_favicon(t);
+		return TRUE;
+	}
+	asprintf(&dest_uri, "file://%s", file);
+	free(file);
 
 	webkit_download_set_destination_uri(download, dest_uri);
 	free(dest_uri);
@@ -6373,6 +6398,23 @@ main(int argc, char *argv[])
 			err(1, "chmod");
 	}
 
+	/* icon cache dir */
+	snprintf(cache_dir, sizeof cache_dir, "%s/%s/%s",
+	    pwd->pw_dir, XT_DIR, XT_CACHE_DIR);
+	if (stat(cache_dir, &sb)) {
+		if (mkdir(cache_dir, S_IRWXU) == -1)
+			err(1, "mkdir cache_dir");
+		if (stat(cache_dir, &sb))
+			err(1, "stat cache_dir");
+	}
+	if (S_ISDIR(sb.st_mode) == 0)
+		errx(1, "%s not a dir", cache_dir);
+	if (((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) != S_IRWXU) {
+		warnx("fixing invalid permissions on %s", cache_dir);
+		if (chmod(cache_dir, S_IRWXU) == -1)
+			err(1, "chmod");
+	}
+
 	/* certs dir */
 	snprintf(certs_dir, sizeof certs_dir, "%s/%s/%s",
 	    pwd->pw_dir, XT_DIR, XT_CERT_DIR);