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
This commit is contained in:
Christian Dywan 2011-03-12 21:02:48 +01:00
parent a9b771ab5c
commit 9ca1271020
2 changed files with 112 additions and 5 deletions

View file

@ -2857,6 +2857,13 @@ webkit_web_view_mime_type_decision_cb (GtkWidget* web_view,
GtkWidget* dialog; GtkWidget* dialog;
gchar* content_type; gchar* content_type;
gchar* description; 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) #if GTK_CHECK_VERSION (2, 14, 0)
GIcon* icon; GIcon* icon;
GtkWidget* image; GtkWidget* image;
@ -2916,12 +2923,38 @@ webkit_web_view_mime_type_decision_cb (GtkWidget* web_view,
#endif #endif
g_free (content_type); g_free (content_type);
if (g_strrstr (description, mime_type)) if (g_strrstr (description, mime_type))
file_type = g_strdup_printf (_("File Type: '%s'"), mime_type);
else
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), gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("File Type: '%s'"), mime_type); "%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 else
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("File Type: %s ('%s')"), description, mime_type); "%s", file_type);
g_free (description); }
g_strfreev (fingerprint);
g_free (file_type);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE); gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
/* i18n: A file open dialog title, ie. "Open http://fila.com/manual.tgz" */ /* i18n: A file open dialog title, ie. "Open http://fila.com/manual.tgz" */
title = g_strdup_printf (_("Open %s"), title = g_strdup_printf (_("Open %s"),
@ -2989,6 +3022,16 @@ webkit_web_view_download_requested_cb (GtkWidget* web_view,
MidoriView* view) MidoriView* view)
{ {
gboolean handled; 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_set_data (G_OBJECT (download), "open-download",
g_object_get_data (G_OBJECT (view), "open-download")); g_object_get_data (G_OBJECT (view), "open-download"));
g_object_set_data (G_OBJECT (download), "save-as-download", g_object_set_data (G_OBJECT (download), "save-as-download",

View file

@ -137,6 +137,11 @@ midori_transferbar_download_notify_status_cb (WebKitDownload* download,
case WEBKIT_DOWNLOAD_STATUS_FINISHED: case WEBKIT_DOWNLOAD_STATUS_FINISHED:
{ {
MidoriBrowser* browser = midori_browser_get_for_widget (button); 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); icon = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), icon); gtk_button_set_image (GTK_BUTTON (button), icon);
@ -155,6 +160,53 @@ midori_transferbar_download_notify_status_cb (WebKitDownload* download,
_("Transfer completed"), msg); _("Transfer completed"), msg);
g_free (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; break;
} }
case WEBKIT_DOWNLOAD_STATUS_CANCELLED: case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
@ -181,7 +233,19 @@ midori_transferbar_download_button_clicked_cb (GtkWidget* button,
case WEBKIT_DOWNLOAD_STATUS_FINISHED: case WEBKIT_DOWNLOAD_STATUS_FINISHED:
{ {
const gchar* uri = webkit_download_get_destination_uri (download); 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)) uri, gtk_get_current_event_time (), NULL))
gtk_widget_destroy (button); gtk_widget_destroy (button);
break; break;