From 9ca127102025df8f4096d820d1e6a9b25fc83f07 Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Sat, 12 Mar 2011 21:02:48 +0100 Subject: [PATCH] Implement MD5 and SHA1 Link Fingerprint support 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 | 51 ++++++++++++++++++++++++--- toolbars/midori-transferbar.c | 66 ++++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 5 deletions(-) diff --git a/midori/midori-view.c b/midori/midori-view.c index 665823d0..b2522826 100644 --- a/midori/midori-view.c +++ b/midori/midori-view.c @@ -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", diff --git a/toolbars/midori-transferbar.c b/toolbars/midori-transferbar.c index 0a8fec46..6b1de4c0 100644 --- a/toolbars/midori-transferbar.c +++ b/toolbars/midori-transferbar.c @@ -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; -- 2.39.5