]> spindle.queued.net Git - midori/commitdiff
Implement MD5 and SHA1 Link Fingerprint support
authorChristian Dywan <christian@twotoasts.de>
Sat, 12 Mar 2011 20:02:48 +0000 (21:02 +0100)
committerChristian Dywan <christian@twotoasts.de>
Sat, 12 Mar 2011 20:10:01 +0000 (21:10 +0100)
If a URL has an embedded link fingerprint the checksum
and algorithm is shown in the download prompt. After a
file has been saved to disk a warning icon will be shown
if the checksum doesn't match and clicking the icon will
explain that the file is erroneous and not open it.

See http://mdhashtool.mozdev.org/lfinfo.html

midori/midori-view.c
toolbars/midori-transferbar.c

index 665823d01a0ef5d241e0ff2933970453675d9730..b2522826a236e304c3180be7400823bc8b16a26b 100644 (file)
@@ -2857,6 +2857,13 @@ webkit_web_view_mime_type_decision_cb (GtkWidget*               web_view,
     GtkWidget* dialog;
     gchar* content_type;
     gchar* description;
+    gchar* file_type;
+    #if WEBKIT_CHECK_VERSION (1, 1, 14)
+    WebKitWebDataSource* datasource;
+    WebKitNetworkRequest* original_request;
+    #endif
+    const gchar* original_uri;
+    gchar** fingerprint;
     #if GTK_CHECK_VERSION (2, 14, 0)
     GIcon* icon;
     GtkWidget* image;
@@ -2916,12 +2923,38 @@ webkit_web_view_mime_type_decision_cb (GtkWidget*               web_view,
     #endif
     g_free (content_type);
     if (g_strrstr (description, mime_type))
-        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-        _("File Type: '%s'"), mime_type);
+        file_type = g_strdup_printf (_("File Type: '%s'"), mime_type);
     else
-       gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-       _("File Type: %s ('%s')"), description, mime_type);
+        file_type = g_strdup_printf (_("File Type: %s ('%s')"), description, mime_type);
     g_free (description);
+
+    /* Link Fingerprint */
+    #if WEBKIT_CHECK_VERSION (1, 1, 14)
+    /* We look at the original URI because redirection would lose the fragment */
+    datasource = webkit_web_frame_get_provisional_data_source (web_frame);
+    original_request = webkit_web_data_source_get_initial_request (datasource);
+    original_uri = webkit_network_request_get_uri (original_request);
+    #else
+    original_uri = webkit_network_request_get_uri (request);
+    #endif
+    fingerprint = g_strsplit (original_uri, "#!md5!", 2);
+    if (fingerprint && fingerprint[0] && fingerprint[1])
+        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+            "%s\n%s %s", file_type, _("MD5-Checksum:"), fingerprint[1]);
+    else
+    {
+        g_strfreev (fingerprint);
+        fingerprint = g_strsplit (original_uri, "#!sha1!", 2);
+        if (fingerprint && fingerprint[0] && fingerprint[1])
+            gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                "%s\n%s %s", file_type, _("SHA1-Checksum:"), fingerprint[1]);
+        else
+            gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                "%s", file_type);
+    }
+    g_strfreev (fingerprint);
+    g_free (file_type);
+
     gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
     /* i18n: A file open dialog title, ie. "Open http://fila.com/manual.tgz" */
     title = g_strdup_printf (_("Open %s"),
@@ -2989,6 +3022,16 @@ webkit_web_view_download_requested_cb (GtkWidget*      web_view,
                                        MidoriView*     view)
 {
     gboolean handled;
+    #if WEBKIT_CHECK_VERSION (1, 1, 14)
+    /* Propagate original URI to make it available when the download finishes */
+    WebKitWebFrame* web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
+    WebKitWebDataSource* datasource = webkit_web_frame_get_provisional_data_source (web_frame);
+    WebKitNetworkRequest* original_request = webkit_web_data_source_get_initial_request (datasource);
+    const gchar* original_uri = webkit_network_request_get_uri (original_request);
+    WebKitNetworkRequest* request = webkit_download_get_network_request (download);
+    g_object_set_data_full (G_OBJECT (request), "midori-original-uri",
+                            g_strdup (original_uri), g_free);
+    #endif
     g_object_set_data (G_OBJECT (download), "open-download",
         g_object_get_data (G_OBJECT (view), "open-download"));
     g_object_set_data (G_OBJECT (download), "save-as-download",
index 0a8fec46151eff75620cbde8da73635c6214d0f2..6b1de4c0092d05264d6a3ed2fa717326e67a707f 100644 (file)
@@ -137,6 +137,11 @@ midori_transferbar_download_notify_status_cb (WebKitDownload* download,
         case WEBKIT_DOWNLOAD_STATUS_FINISHED:
         {
             MidoriBrowser* browser = midori_browser_get_for_widget (button);
+            #if WEBKIT_CHECK_VERSION (1, 1, 14)
+            WebKitNetworkRequest* request;
+            #endif
+            const gchar* original_uri;
+            gchar** fingerprint;
 
             icon = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
             gtk_button_set_image (GTK_BUTTON (button), icon);
@@ -155,6 +160,53 @@ midori_transferbar_download_notify_status_cb (WebKitDownload* download,
                                        _("Transfer completed"), msg);
                 g_free (msg);
             }
+
+            /* Link Fingerprint */
+            #if WEBKIT_CHECK_VERSION (1, 1, 14)
+            request = webkit_download_get_network_request (download);
+            original_uri = g_object_get_data (G_OBJECT (request), "midori-original-uri");
+            #else
+            original_uri = webkit_download_get_uri (download);
+            #endif
+            fingerprint = g_strsplit (original_uri, "#!md5!", 2);
+            if (fingerprint && fingerprint[0] && fingerprint[1])
+            {
+                gchar* filename = g_filename_from_uri (
+                    webkit_download_get_destination_uri (download), NULL, NULL);
+                gchar* contents;
+                gsize length;
+                gboolean y = g_file_get_contents (filename, &contents, &length, NULL);
+                gchar* checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5,
+                    (guchar*)contents, length);
+                g_free (filename);
+                g_free (contents);
+                if (!y || !g_str_equal (fingerprint[1], checksum))
+                    gtk_image_set_from_stock (GTK_IMAGE (icon),
+                        GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
+                g_free (checksum);
+            }
+            else
+            {
+                gchar* filename = g_filename_from_uri (
+                    webkit_download_get_destination_uri (download), NULL, NULL);
+                g_strfreev (fingerprint);
+                fingerprint = g_strsplit (original_uri, "#!sha1!", 2);
+                if (fingerprint && fingerprint[0] && fingerprint[1])
+                {
+                    gchar* contents;
+                    gsize length;
+                    gboolean y = g_file_get_contents (filename, &contents, &length, NULL);
+                    gchar* checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1,
+                        (guchar*)contents, length);
+                    g_free (contents);
+                    if (!y || !g_str_equal (fingerprint[1], checksum))
+                        gtk_image_set_from_stock (GTK_IMAGE (icon),
+                            GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
+                    g_free (checksum);
+                }
+                g_free (filename);
+            }
+            g_strfreev (fingerprint);
             break;
         }
         case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
@@ -181,7 +233,19 @@ midori_transferbar_download_button_clicked_cb (GtkWidget*    button,
         case WEBKIT_DOWNLOAD_STATUS_FINISHED:
         {
             const gchar* uri = webkit_download_get_destination_uri (download);
-            if (sokoke_show_uri (gtk_widget_get_screen (button),
+            GtkWidget* icon = gtk_button_get_image (GTK_BUTTON (button));
+            gchar* stock_id;
+            gtk_image_get_stock (GTK_IMAGE (icon), &stock_id, NULL);
+            if (g_str_equal (stock_id, GTK_STOCK_DIALOG_WARNING))
+            {
+                sokoke_message_dialog (GTK_MESSAGE_WARNING,
+                    _("The downloaded file is erroneous."),
+                    _("The checksum provided with the link did not match. " \
+                      "This means the file is probably incomplete or was " \
+                      "modified afterwards."),
+                    TRUE);
+            }
+            else if (sokoke_show_uri (gtk_widget_get_screen (button),
                 uri, gtk_get_current_event_time (), NULL))
                 gtk_widget_destroy (button);
             break;