/* Copyright (C) 2009 Alexander Butenko Copyright (C) 2009 Christian Dywan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. */ #define MAXCHARS 60 #define MINCHARS 2 #include #include "config.h" #include "midori/sokoke.h" #include #if HAVE_UNISTD_H #include #endif static GHashTable* global_keys; static gchar* jsforms; static gboolean formhistory_prepare_js () { gchar* data_path; gchar* autosuggest; gchar* style; guint i; gchar* file; data_path = g_build_filename (PACKAGE_NAME, "res", "autosuggestcontrol.js", NULL); file = sokoke_find_data_filename (data_path); if (!g_file_get_contents (file, &autosuggest, NULL, NULL)) { g_free (data_path); g_free (file); return FALSE; } g_strchomp (autosuggest); katze_assign (data_path, g_build_filename (PACKAGE_NAME, "res", "autosuggestcontrol.css", NULL)); katze_assign (file, sokoke_find_data_filename (data_path)); if (!g_file_get_contents (file, &style, NULL, NULL)) { g_free (data_path); g_free (file); return FALSE; } g_strchomp (style); i = 0; while (style[i]) { if (style[i] == '\n') style[i] = ' '; i++; } jsforms = g_strdup_printf ( "%s" "window.addEventListener ('DOMContentLoaded'," "function () {" " if (document.getElementById('formhistory'))" " return;" " if (!initSuggestions ())" " return;" " var mystyle = document.createElement('style');" " mystyle.setAttribute('type', 'text/css');" " mystyle.setAttribute('id', 'formhistory');" " mystyle.appendChild(document.createTextNode('%s'));" " var head = document.getElementsByTagName('head')[0];" " if (head) head.appendChild(mystyle);" "}, true);", autosuggest, style); g_strstrip (jsforms); g_free (data_path); g_free (file); g_free (style); g_free (autosuggest); return TRUE; } static gchar* formhistory_fixup_value (char* value) { guint i = 0; g_strchomp (value); while (value[i]) { if (value[i] == '\n') value[i] = ' '; else if (value[i] == '"') value[i] = '\''; i++; } return value; } static gchar* formhistory_build_js () { gchar* suggestions = g_strdup (""); GHashTableIter iter; gpointer key, value; gchar* script; g_hash_table_iter_init (&iter, global_keys); while (g_hash_table_iter_next (&iter, &key, &value)) { gchar* _suggestions = g_strdup_printf ("%s arr[\"%s\"] = [%s]; ", suggestions, (char*)key, (char*)value); katze_assign (suggestions, _suggestions); } script = g_strdup_printf ("function FormSuggestions(eid) { " "arr = new Array();" "%s" "this.suggestions = arr[eid]; }" "%s", suggestions, jsforms); g_free (suggestions); return script; } static void formhistory_update_database (gpointer db, const gchar* key, const gchar* value) { gchar* sqlcmd; gchar* errmsg; gint success; sqlcmd = sqlite3_mprintf ("INSERT INTO forms VALUES" "('%q', '%q', '%q')", NULL, key, value); success = sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg); sqlite3_free (sqlcmd); if (success != SQLITE_OK) { g_printerr (_("Failed to add form value: %s\n"), errmsg); g_free (errmsg); return; } } static gboolean formhistory_update_main_hash (gchar* key, gchar* value) { guint length; gchar* tmp; if (!(value && *value)) return FALSE; length = strlen (value); if (length > MAXCHARS || length < MINCHARS) return FALSE; formhistory_fixup_value (key); formhistory_fixup_value (value); if ((tmp = g_hash_table_lookup (global_keys, (gpointer)key))) { gchar* rvalue = g_strdup_printf ("\"%s\"",value); gchar* patt = g_regex_escape_string (rvalue, -1); if (!g_regex_match_simple (patt, tmp, G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY)) { gchar* new_value = g_strdup_printf ("%s%s,", tmp, rvalue); g_hash_table_insert (global_keys, g_strdup (key), new_value); g_free (rvalue); g_free (patt); } else { g_free (rvalue); g_free (patt); return FALSE; } } else { gchar* new_value = g_strdup_printf ("\"%s\",",value); g_hash_table_replace (global_keys, g_strdup (key), new_value); } return TRUE; } static gboolean formhistory_navigation_decision_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, WebKitNetworkRequest* request, WebKitWebNavigationAction* action, WebKitWebPolicyDecision* decision, MidoriExtension* extension) { /* The script returns form data in the form "field_name|,|value|,|field_type". We are handling only input fields with 'text' or 'password' type. The field separator is "|||" */ const gchar* script = "function dumpForm (inputs) {" " var out = '';" " for (i=0;i autosuggest testcase

*/ #endif MidoriExtension* extension_init (void) { gboolean should_init = TRUE; const gchar* ver; gchar* desc; MidoriExtension* extension; if (formhistory_prepare_js ()) { ver = "1.0"; desc = g_strdup (_("Stores history of entered form data")); } else { desc = g_strdup_printf (_("Not available: %s"), _("Resource files not installed")); ver = NULL; should_init = FALSE; } extension = g_object_new (MIDORI_TYPE_EXTENSION, "name", _("Form history filler"), "description", desc, "version", ver, "authors", "Alexander V. Butenko ", NULL); g_free (desc); if (should_init) g_signal_connect (extension, "activate", G_CALLBACK (formhistory_activate_cb), NULL); return extension; }