diff options
-rw-r--r-- | lib/Makefile.am | 13 | ||||
-rw-r--r-- | lib/ephy-profile-migrator.c | 195 | ||||
-rw-r--r-- | lib/ephy-profile-utils.h | 2 |
3 files changed, 208 insertions, 2 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 82fd33713..d2d5cfafb 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -96,6 +96,18 @@ libephymisc_la_LIBADD = -lm bin_PROGRAMS = ephy-profile-migrator ephy_profile_migrator_SOURCES = \ + sqlite/ephy-sqlite-connection.c \ + sqlite/ephy-sqlite-connection.h \ + sqlite/ephy-sqlite-statement.c \ + sqlite/ephy-sqlite-statement.h \ + sqlite/ephy-sqlite.h \ + history/ephy-history-service.c \ + history/ephy-history-service.h \ + history/ephy-history-service-private.h \ + history/ephy-history-service-urls-table.c \ + history/ephy-history-service-visits-table.c \ + history/ephy-history-types.c \ + history/ephy-history-types.h \ ephy-profile-migrator.c \ ephy-profile-utils.c \ ephy-profile-utils.h \ @@ -123,6 +135,7 @@ endif # ENABLE_NSS ephy_profile_migrator_CPPFLAGS = \ -I$(top_builddir)/lib \ + -I$(srcdir)/history \ -DSHARE_DIR=\"$(pkgdatadir)\" \ $(AM_CPPFLAGS) diff --git a/lib/ephy-profile-migrator.c b/lib/ephy-profile-migrator.c index 5610d5fa4..aefc0dfc6 100644 --- a/lib/ephy-profile-migrator.c +++ b/lib/ephy-profile-migrator.c @@ -34,12 +34,14 @@ #include "ephy-debug.h" #include "ephy-file-helpers.h" +#include "ephy-history-service.h" #include "ephy-profile-utils.h" #ifdef ENABLE_NSS #include "ephy-nss-glue.h" #endif #include <glib/gi18n.h> +#include <glib/gstdio.h> #include <gnome-keyring.h> #include <libsoup/soup-gnome.h> @@ -394,6 +396,196 @@ migrate_passwords2 () #endif } +/* History migration */ + +static EphyHistoryService *history_service = NULL; +static gboolean all_done = FALSE; + +typedef struct { + char *title; + char *location; + char *current; + long long int visit_count; + long long int last_visit; + long long int first_visit; + GList *visits; +} HistoryParseData; + +static void +history_parse_start_element (GMarkupParseContext *context, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + gpointer user_data, + GError **error) +{ + HistoryParseData *parse_data = user_data; + + if (g_str_equal (element_name, "node") && parse_data) { + /* Starting a new node, reset all values */ + g_free (parse_data->title); + parse_data->title = NULL; + + g_free (parse_data->location); + parse_data->location = NULL; + + parse_data->visit_count = 0; + parse_data->last_visit = 0; + parse_data->first_visit = 0; + } else if (g_str_equal (element_name, "property")) { + const char **name, **value; + + for (name = attribute_names, value = attribute_values; *name; name++, value++) { + if (g_str_equal (*name, "id")) { + parse_data->current = g_strdup (*value); + break; + } + } + } +} + +static void +history_parse_text (GMarkupParseContext *context, + const char *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + HistoryParseData *parse_data = user_data; + + if (!parse_data || ! parse_data->current) + return; + + if (g_str_equal (parse_data->current, "2")) { + /* Title */ + parse_data->title = g_strndup (text, text_len); + } else if (g_str_equal (parse_data->current, "3")) { + /* Location */ + parse_data->location = g_strndup (text, text_len); + } else if (g_str_equal (parse_data->current, "4")) { + /* Visit count */ + GString *data = g_string_new_len (text, text_len); + sscanf(data->str, "%lld", &parse_data->visit_count); + g_string_free (data, TRUE); + } else if (g_str_equal (parse_data->current, "5")) { + /* Last visit */ + GString *data = g_string_new_len (text, text_len); + sscanf(data->str, "%lld", &parse_data->last_visit); + g_string_free (data, TRUE); + } else if (g_str_equal (parse_data->current, "6")) { + /* First visit */ + GString *data = g_string_new_len (text, text_len); + sscanf(data->str, "%lld", &parse_data->first_visit); + g_string_free (data, TRUE); + } + + g_free (parse_data->current); + parse_data->current = NULL; +} + +static void +visit_cb (EphyHistoryService *service, gboolean success, gpointer result, gpointer user_data) +{ + all_done = TRUE; +} + +static void +history_parse_end_element (GMarkupParseContext *context, + const char *element_name, + gpointer user_data, + GError **error) +{ + HistoryParseData *parse_data = user_data; + + if (g_str_equal (element_name, "node") && parse_data) { + /* Add one item to History */ + EphyHistoryPageVisit *visit = ephy_history_page_visit_new (parse_data->location ? parse_data->location : "", parse_data->last_visit, EPHY_PAGE_VISIT_TYPED); + g_free (visit->url->title); + visit->url->title = g_strdup (parse_data->title); + parse_data->visits = g_list_append (parse_data->visits, visit); + } +} + +static GMarkupParser history_parse_funcs = +{ + history_parse_start_element, + history_parse_end_element, + history_parse_text, + NULL, + NULL, +}; + +static EphyHistoryService * +ensure_empty_history (const char* filename) +{ + if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { + g_unlink (filename); + } + + return ephy_history_service_new (filename); +} + +static void +migrate_history () +{ + GFileInputStream *input; + GMarkupParseContext *context; + GError *error = NULL; + GFile *file; + char *filename; + char buffer[1024]; + HistoryParseData parse_data; + + gchar *temporary_file = g_build_filename (ephy_dot_dir (), "ephy-history.db", NULL); + history_service = ensure_empty_history (temporary_file); + g_free (temporary_file); + + memset (&parse_data, 0, sizeof (HistoryParseData)); + parse_data.location = NULL; + parse_data.title = NULL; + parse_data.visits = NULL; + + filename = g_build_filename (ephy_dot_dir (), + "ephy-history.xml", + NULL); + + file = g_file_new_for_path (filename); + g_free (filename); + + input = g_file_read (file, NULL, &error); + g_object_unref (file); + + if (error) { + if (error->code != G_IO_ERROR_NOT_FOUND) + g_warning ("Could not load Epiphany history data, migration aborted: %s", error->message); + + g_error_free (error); + return; + } + + context = g_markup_parse_context_new (&history_parse_funcs, 0, &parse_data, NULL); + while (TRUE) { + gssize count = g_input_stream_read (G_INPUT_STREAM (input), buffer, sizeof (buffer), NULL, &error); + if (count <= 0) + break; + + if (!g_markup_parse_context_parse (context, buffer, count, &error)) + break; + } + + g_markup_parse_context_free (context); + g_input_stream_close (G_INPUT_STREAM (input), NULL, NULL); + g_object_unref (input); + + ephy_history_service_add_visits (history_service, parse_data.visits, (EphyHistoryJobCallback)visit_cb, NULL); + ephy_history_page_visit_list_free (parse_data.visits); + + while (!all_done) + g_main_context_iteration (NULL, FALSE); + + g_object_unref (history_service); +} + const EphyProfileMigrator migrators[] = { migrate_cookies, migrate_passwords, @@ -402,7 +594,8 @@ const EphyProfileMigrator migrators[] = { migrate_passwords, /* Very similar to migrate_passwords, but this migrates * login/passwords for page forms, which we previously ignored */ - migrate_passwords2 + migrate_passwords2, + migrate_history }; static void diff --git a/lib/ephy-profile-utils.h b/lib/ephy-profile-utils.h index 7ea679734..e33b94633 100644 --- a/lib/ephy-profile-utils.h +++ b/lib/ephy-profile-utils.h @@ -26,7 +26,7 @@ #define FORM_USERNAME_KEY "form_username" #define FORM_PASSWORD_KEY "form_password" -#define EPHY_PROFILE_MIGRATION_VERSION 4 +#define EPHY_PROFILE_MIGRATION_VERSION 5 int ephy_profile_utils_get_migration_version (void); |