[Pkg-mozext-commits] [autofill-forms] 02/09: Imported Upstream version 1.0.2
David Prévot
taffit at moszumanska.debian.org
Mon Oct 13 19:45:54 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository autofill-forms.
commit f1da53b6b7fbd6d4562f2e23cea115a7f5dcb7c0
Author: David Prévot <taffit at debian.org>
Date: Mon Oct 13 14:36:32 2014 -0400
Imported Upstream version 1.0.2
---
src/chrome.manifest => chrome.manifest | 0
chrome/content/autofillForms.js | 5405 ++++++++++++++++++++
.../content/autofillFormsOptions.js | 0
.../content/autofillFormsOptions.xul | 123 +-
.../content/autofillFormsOverlay.js | 0
.../content/autofillFormsOverlay.xul | 0
.../content/autofillFormsRuleEditor.js | 0
.../content/autofillFormsRuleEditor.xul | 0
.../content/autofillFormsTagEditor.js | 0
.../content/autofillFormsTagEditor.xul | 0
.../locale/cs-CZ/autofillForms.dtd | 0
.../locale/cs-CZ/autofillForms.properties | 0
.../locale/de-DE/autofillForms.dtd | 0
.../locale/de-DE/autofillForms.properties | 0
.../locale/el-GR/autofillForms.dtd | 0
.../locale/el-GR/autofillForms.properties | 0
.../locale/en-US/autofillForms.dtd | 0
.../locale/en-US/autofillForms.properties | 0
.../locale/es-ES/autofillForms.dtd | 0
.../locale/es-ES/autofillForms.properties | 0
.../locale/fi-FI/autofillForms.dtd | 0
.../locale/fi-FI/autofillForms.properties | 0
.../locale/fr-FR/autofillForms.dtd | 0
.../locale/fr-FR/autofillForms.properties | 0
.../locale/he-IL/autofillForms.dtd | 0
.../locale/he-IL/autofillForms.properties | 0
.../locale/hr-HR/autofillForms.dtd | 0
.../locale/hr-HR/autofillForms.properties | 0
.../locale/hu-HU/autofillForms.dtd | 0
.../locale/hu-HU/autofillForms.properties | 0
.../locale/it-IT/autofillForms.dtd | 0
.../locale/it-IT/autofillForms.properties | 0
.../locale/nl-NL/autofillForms.dtd | 0
.../locale/nl-NL/autofillForms.properties | 0
.../locale/pl-PL/autofillForms.dtd | 0
.../locale/pl-PL/autofillForms.properties | 0
.../locale/pt-BR/autofillForms.dtd | 0
.../locale/pt-BR/autofillForms.properties | 0
.../locale/ro-RO/autofillForms.dtd | 0
.../locale/ro-RO/autofillForms.properties | 0
.../locale/ru-RU/autofillForms.dtd | 0
.../locale/ru-RU/autofillForms.properties | 0
.../locale/sk-SK/autofillForms.dtd | 0
.../locale/sk-SK/autofillForms.properties | 0
.../locale/sv-SE/autofillForms.dtd | 0
.../locale/sv-SE/autofillForms.properties | 0
.../locale/tr-TR/autofillForms.dtd | 0
.../locale/tr-TR/autofillForms.properties | 0
.../locale/zh-CN/autofillForms.dtd | 0
.../locale/zh-CN/autofillForms.properties | 0
.../locale/zh-TW/autofillForms.dtd | 0
.../locale/zh-TW/autofillForms.properties | 0
{src/chrome => chrome}/skin/arrows.png | Bin
chrome/skin/autofillForms.css | 59 +
{src/chrome => chrome}/skin/autofillFormsMac.css | 0
.../skin/autofillFormsOptions.css | 0
.../skin/autofillFormsOptions1.5.css | 0
.../skin/autofillFormsOptions2.css | 0
.../skin/autofillFormsRuleEditor.css | 0
.../skin/autofillFormsTagEditor.css | 0
{src/chrome => chrome}/skin/help-small.png | Bin
{src/chrome => chrome}/skin/icon.png | Bin
{src/chrome => chrome}/skin/pencil-active-mac.png | Bin
.../skin/icon.png => chrome/skin/pencil-big.png | Bin
{src/chrome => chrome}/skin/pencil-mac.png | Bin
{src/chrome => chrome}/skin/pencil-small.png | Bin
{src/chrome => chrome}/skin/pencil.png | Bin
{src/chrome => chrome}/skin/profile-small.png | Bin
{src/chrome => chrome}/skin/settings-small.png | Bin
.../preferences/autofillForms.js | 6 +-
install.rdf | 52 +
src/build.xml | 59 -
src/chrome.manifest.extracted.txt | 29 -
src/chrome.manifest.jar.txt | 29 -
src/chrome/content/autofillForms.js | 5389 -------------------
src/chrome/skin/autofillForms.css | 46 -
src/install.rdf | 50 -
www/bugs.html | 12 -
www/changelog.html | 545 --
www/css/closelabel.gif | Bin 971 -> 0 bytes
www/css/loading.gif | Bin 1588 -> 0 bytes
www/css/nextlabel.gif | Bin 354 -> 0 bytes
www/css/prevlabel.gif | Bin 371 -> 0 bytes
www/css/slimbox.css | 82 -
www/donation.html | 18 -
www/download.html | 11 -
www/error/404.html | 35 -
www/favicon.ico | Bin 1150 -> 0 bytes
www/footer.html | 19 -
.../Firefox-3-Mac-Toolbar-Button-Template.png | Bin 3232 -> 0 bytes
www/graphics/logo.png | Bin 4300 -> 0 bytes
www/graphics/paypal-donate.gif | Bin 2815 -> 0 bytes
www/graphics/pencil.png | Bin 1269 -> 0 bytes
www/graphics/pencil.svg | 610 ---
www/graphics/screenshots/autofill-forms-01.png | Bin 97537 -> 0 bytes
www/graphics/screenshots/autofill-forms-02.png | Bin 80090 -> 0 bytes
www/graphics/screenshots/autofill-forms-03.png | Bin 71384 -> 0 bytes
www/graphics/screenshots/autofill-forms-04.png | Bin 102258 -> 0 bytes
www/graphics/screenshots/autofill-forms-05.png | Bin 102237 -> 0 bytes
www/graphics/screenshots/autofill-forms-06.png | Bin 80114 -> 0 bytes
www/graphics/screenshots/autofill-forms-07.png | Bin 88989 -> 0 bytes
www/graphics/screenshots/autofill-forms-08.png | Bin 96965 -> 0 bytes
www/graphics/screenshots/autofill-forms-09.png | Bin 87587 -> 0 bytes
www/graphics/screenshots/autofill-forms-10.png | Bin 103140 -> 0 bytes
www/graphics/screenshots/autofill-forms-11.png | Bin 110310 -> 0 bytes
www/graphics/screenshots/autofill-forms-12.png | Bin 89006 -> 0 bytes
www/graphics/screenshots/autofill-forms-13.png | Bin 99579 -> 0 bytes
www/graphics/screenshots/autofill-forms-14.png | Bin 107812 -> 0 bytes
www/graphics/screenshots/autofill-forms-15.png | Bin 115133 -> 0 bytes
www/graphics/screenshots/autofill-forms-16.png | Bin 133589 -> 0 bytes
www/graphics/screenshots/autofill-forms-17.png | Bin 106201 -> 0 bytes
www/graphics/screenshots/autofill-forms-18.png | Bin 101778 -> 0 bytes
.../screenshots/preview/autofill-forms-01.png | Bin 40091 -> 0 bytes
.../screenshots/preview/autofill-forms-02.png | Bin 31925 -> 0 bytes
.../screenshots/preview/autofill-forms-03.png | Bin 29626 -> 0 bytes
.../screenshots/preview/autofill-forms-04.png | Bin 41457 -> 0 bytes
.../screenshots/preview/autofill-forms-05.png | Bin 40034 -> 0 bytes
.../screenshots/preview/autofill-forms-06.png | Bin 31670 -> 0 bytes
.../screenshots/preview/autofill-forms-07.png | Bin 34864 -> 0 bytes
.../screenshots/preview/autofill-forms-08.png | Bin 37846 -> 0 bytes
.../screenshots/preview/autofill-forms-09.png | Bin 33215 -> 0 bytes
.../screenshots/preview/autofill-forms-10.png | Bin 41690 -> 0 bytes
.../screenshots/preview/autofill-forms-11.png | Bin 44705 -> 0 bytes
.../screenshots/preview/autofill-forms-12.png | Bin 33274 -> 0 bytes
.../screenshots/preview/autofill-forms-13.png | Bin 39821 -> 0 bytes
.../screenshots/preview/autofill-forms-14.png | Bin 42814 -> 0 bytes
.../screenshots/preview/autofill-forms-15.png | Bin 47391 -> 0 bytes
.../screenshots/preview/autofill-forms-16.png | Bin 50418 -> 0 bytes
.../screenshots/preview/autofill-forms-17.png | Bin 40893 -> 0 bytes
.../screenshots/preview/autofill-forms-18.png | Bin 42027 -> 0 bytes
www/head.txt | 11 -
www/hide_from_ns4.css | 15 -
www/html_body.html | 84 -
www/index.html | 60 -
www/local.conf | 13 -
www/project.css | 38 -
www/project_nav.html | 21 -
www/screenshots.html | 62 -
www/source.html | 17 -
www/support.html | 39 -
www/test.html | 95 -
141 files changed, 5574 insertions(+), 7460 deletions(-)
diff --git a/src/chrome.manifest b/chrome.manifest
similarity index 100%
rename from src/chrome.manifest
rename to chrome.manifest
diff --git a/chrome/content/autofillForms.js b/chrome/content/autofillForms.js
new file mode 100644
index 0000000..046701f
--- /dev/null
+++ b/chrome/content/autofillForms.js
@@ -0,0 +1,5405 @@
+/*
+ * @package autofillForms
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license GNU General Public License
+ * @link https://blueimp.net/mozilla/
+ */
+
+var autofillForms = {
+
+ // The selected profile index:
+ profileIndex: null,
+ // The selected global profile index:
+ globalProfileIndex: null,
+ // The selected form fields context menu profile index
+ formFieldsContextMenuProfileIndex: null,
+ // The list of profile labels:
+ profileLabels: null,
+ // The list of profile site rules:
+ profileSiteRules: null,
+ // The list of form field rules:
+ fieldRules: null,
+ // The tree representing the field rules list:
+ tree: null,
+ // The tree view:
+ treeView: null,
+ // The tree view frontend:
+ treeBox: null,
+ // Holds the selection object for the treeview:
+ selection: null,
+ // Remembers the last selected index of the treeview:
+ lastSelectedIndex: null,
+ // Determines if sort is to be ascending or descending:
+ ascending: null,
+ // The profiles listBox:
+ profilesTree: null,
+ // The profiles tree view:
+ profilesTreeView: null,
+ // The profiles tree view frontend:
+ profilesTreeBox: null,
+ // Holds the selection object for the profiles treeview:
+ profilesSelection: null,
+ // The profiles sort order:
+ profilesAscending: null,
+ // Autofill forms preferences branch:
+ autofillFormsPrefs: null,
+ // Object containing the shortcuts information (modifiers, key or keycode):
+ shortcut: null,
+ // Object containing the mouse button shortcuts information:
+ mouseButton: null,
+ // Helper var to do the opposite of the current setting:
+ invertedSetting: null,
+ // Array containing the rule element types ("begins with", "contains", ...):
+ ruleElementTypes: null,
+ // Containes the reference to the current rule field:
+ currentRuleField: null,
+ // Defines the index selected for the last alternative fieldRules selection:
+ fieldRuleAlternativesIndex: null,
+ // Stores the length of the last created list of alternative fieldRules:
+ fieldRuleAlternativesLength: null,
+ // Hash to store lists of alternatives (used for radio input fields):
+ fieldRuleAlternativesHash: null,
+ // Cache to reuse/clone fieldRuleAlternatives on the same form fill run:
+ fieldRuleAlternativesCache: null,
+ // Array of dynamic tags:
+ dynamicTags: null,
+ // Array of dynamic tag codes, associated to the dynamic tags:
+ dynamicTagCodes: null,
+ // Determines if a textbox is focused on the rule editor:
+ ruleEditorTextBoxFocused: null,
+ // Determines if a textbox is focused on the tag editor:
+ tagEditorTextBoxFocused: null,
+ // References the last matched form element (used to set the focus):
+ lastFormElementMatch: null,
+ // References the current window when filling out forms:
+ currentWindow: null,
+ // Holds the index of the current form when filling out forms:
+ currentFormIndex:null,
+ // Holds the index of the current form element when filling out forms:
+ currentElementIndex: null,
+ // References the target form field on which the context menu has been invoked:
+ targetFormField: null,
+ // Event listener for the content area context menu:
+ contentAreaContextMenuEventListener: null,
+ // Holds the the tooltip grid which displays commands and their mouse buttons and keyboard shortcuts:
+ tooltipGrid: null,
+ // Holds the current profile tooltip label:
+ tooltipCurrentProfile: null,
+ // Keep track of open dialogs
+ currentDialogs: null,
+ // current version number
+ version: "0.9.8.2",
+
+ initialize: function() {
+
+ // Save the reference to the Autofill Forms preferences branch:
+ this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
+
+ // Add a preferences observer to the autofillForms preferences branch:
+ this.autofillFormsPrefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
+ this.autofillFormsPrefs.addObserver('', this, false);
+
+ // Implement the event listener for the content area context menu:
+ this.contentAreaContextMenuEventListener = function(event) {
+ autofillForms.initContentAreaContextMenu(event);
+ }
+
+ // Initialize the preferences settings:
+ this.initializePrefs();
+
+
+ var self = this;
+ document.addEventListener("SSTabRestored", function(event){
+ var just_installed = self.autofillFormsPrefs.getBoolPref("just_installed");
+ if(just_installed){
+ self.autofillFormsPrefs.setBoolPref("just_installed", false);
+ gBrowser.selectedTab = gBrowser.addTab(self.autofillFormsPrefs.getCharPref("post_install_url"));
+
+ }
+ });
+ },
+
+ initContentAreaContextMenu: function(event) {
+ var cm0 = document.getElementById('autofillFormsContextMenuItem');
+ var cm1 = document.getElementById('autofillFormsContextMenu');
+ var cm2 = document.getElementById('autofillFormsManualFillContextMenu');
+ var cm3 = document.getElementById('autofillFormsAddRuleContextMenuItem');
+ var cm4 = document.getElementById('autofillFormsAddFormAsProfileContextMenuItem');
+ var cm5 = document.getElementById('autofillFormsContextMenuSeparator1');
+ var cm6 = document.getElementById('autofillFormsContextMenuSeparator2');
+ var cm7 = document.getElementById('autofillFormsDisplayFormDetailsContextMenuItem');
+ if(cm0 && gContextMenu) {
+ if(gContextMenu.target && this.isValidFormField(gContextMenu.target)) {
+ cm0.hidden = true;
+ cm1.hidden = true;
+ if(this.autofillFormsPrefs.getBoolPref('hideFormFieldsContextMenu')) {
+ cm2.hidden = true;
+ cm3.hidden = true;
+ cm4.hidden = true;
+ cm5.hidden = true;
+ cm6.hidden = true;
+ cm7.hidden = true;
+ this.targetFormField = null;
+ } else {
+ cm2.hidden = false;
+ cm3.hidden = false;
+ cm4.hidden = false;
+ // Show menuseparators if not already separated:
+ if(this.isPreviousNodeSeparated(cm5)) {
+ cm5.hidden = true;
+ } else {
+ cm5.hidden = false;
+ }
+ if(this.isNextNodeSeparated(cm6)) {
+ cm6.hidden = true;
+ } else {
+ cm6.hidden = false;
+ }
+ this.targetFormField = gContextMenu.target;
+ }
+ return;
+ }
+
+ if(this.autofillFormsPrefs.getBoolPref('hideContextMenuItem')
+ || gContextMenu.isContentSelected
+ || gContextMenu.onTextInput
+ || gContextMenu.onImage
+ || gContextMenu.onLink
+ || gContextMenu.onCanvas
+ || gContextMenu.onMathML
+ || !this.getDoc().forms
+ || !this.getDoc().forms.length) {
+ cm0.hidden = true;
+ cm1.hidden = true;
+ cm5.hidden = true;
+ cm6.hidden = true;
+ cm7.hidden = true;
+ } else {
+ if(this.getProfileLabels().length == 1) {
+ cm0.hidden = false;
+ cm1.hidden = true;
+ } else {
+ cm0.hidden = true;
+ cm1.hidden = false;
+ }
+ // Show menuseparators if not already separated:
+ if(this.isPreviousNodeSeparated(cm5)) {
+ cm5.hidden = true;
+ } else {
+ cm5.hidden = false;
+ }
+ if(this.isNextNodeSeparated(cm6)) {
+ cm6.hidden = true;
+ } else {
+ cm6.hidden = false;
+ }
+ cm7.hidden = false;
+ }
+ cm2.hidden = true;
+ cm3.hidden = true;
+ cm4.hidden = true;
+ this.targetFormField = null;
+ }
+ },
+
+ isNextNodeSeparated: function(node) {
+ while(node) {
+ node = node.nextSibling
+ if(node.hidden) {
+ continue;
+ }
+ if(node.nodeName == 'menuseparator') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ isPreviousNodeSeparated: function(node) {
+ while(node) {
+ node = node.previousSibling;
+ if(node.hidden) {
+ continue;
+ }
+ if(node.nodeName == 'menuseparator') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ initializePrefs: function() {
+ // Initialize the keyboard shortcut object container:
+ this.shortcut = new Object();
+ this.shortcut['shortcut'] = null;
+ this.shortcut['shortcutSubmit'] = null;
+ this.shortcut['shortcutAllTabs'] = null;
+ this.shortcut['shortcutFromProfileSelection'] = null;
+ this.shortcut['shortcutProfile'] = null;
+ this.shortcut['shortcutSettings'] = null;
+ this.shortcut['shortcutDisplayFormDetails'] = null;
+ for(var property in this.shortcut) {
+ this.updateShortcut(property);
+ }
+ // Initialize toolbar and statusbar icons and context menu:
+ this.hideToolbarButtonUpdate();
+ this.hideToolbarButtonMenuUpdate();
+ this.hideStatusbarIconUpdate();
+ this.hideContextMenuItemUpdate();
+ },
+
+ observe: function(subject, topic, data) {
+ // Only observe preferences changes:
+ if (topic != 'nsPref:changed')
+ return;
+ switch(data) {
+ case 'profileIndex':
+ // If set to null, the profileIndex will be updated on next getProfileIndex() call:
+ this.profileIndex = null;
+ this.tooltipCurrentProfile = null;
+ break;
+ case 'globalProfileIndex':
+ // If set to null, the globalProfileIndex will be updated on next getGlobalProfileIndex() call:
+ this.globalProfileIndex = null;
+ break;
+ case 'formFieldsContextMenuProfileIndex':
+ // If set to null, the formFieldsContextMenuProfileIndex will be updated on next getFormFieldsContextMenuProfileIndex() call:
+ this.formFieldsContextMenuProfileIndex = null;
+ break;
+ case 'profileLabels':
+ // If set to null, the profileLabels will be updated on next getProfileLabels() call:
+ this.profileLabels = null;
+ this.tooltipCurrentProfile = null;
+ break;
+ case 'profileSiteRules':
+ // If set to null, the profileSiteRules will be updated on next getProfileSiteRules() call:
+ this.profileSiteRules = null;
+ break;
+ case 'shortcut':
+ this.updateShortcut('shortcut');
+ this.tooltipGrid = null;
+ break;
+ case 'shortcutSubmit':
+ this.updateShortcut('shortcutSubmit');
+ this.tooltipGrid = null;
+ break;
+ case 'shortcutAllTabs':
+ this.updateShortcut('shortcutAllTabs');
+ this.tooltipGrid = null;
+ break;
+ case 'shortcutFromProfileSelection':
+ this.updateShortcut('shortcutFromProfileSelection');
+ this.tooltipGrid = null;
+ break;
+ case 'shortcutProfile':
+ this.updateShortcut('shortcutProfile');
+ this.tooltipGrid = null;
+ break;
+ case 'shortcutSettings':
+ this.updateShortcut('shortcutSettings');
+ this.tooltipGrid = null;
+ break;
+ case 'shortcutDisplayFormDetails':
+ this.updateShortcut('shortcutDisplayFormDetails');
+ this.tooltipGrid = null;
+ break;
+ case 'mouseShortcut':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcut'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'mouseShortcutSubmit':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcutSubmit'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'mouseShortcutAllTabs':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcutAllTabs'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'mouseShortcutFromProfileSelection':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcutFromProfileSelection'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'mouseShortcutProfile':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcutProfile'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'mouseShortcutSettings':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcutSettings'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'mouseShortcutDisplayFormDetails':
+ if(this.mouseButton) {
+ this.mouseButton['mouseShortcutDisplayFormDetails'] = null;
+ this.tooltipGrid = null;
+ }
+ break;
+ case 'fieldRules':
+ if(!this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // If set to null, the fieldRules will be updated on next getFieldRules() call:
+ this.fieldRules = null;
+ }
+ break;
+ case 'storeEncrypted':
+ // To update the stored data, we must decrypt or may not decrypt
+ // the prefString in opposition to the setting which just changed -
+ // the "invertedSetting" helper var helps to identify this situation:
+ this.invertedSetting = true;
+ // Store data encrypted/decrypted:
+ this.setFieldRules();
+ this.invertedSetting = false;
+ break;
+ case 'dynamicTags':
+ // If set to null, the dynamicTags will be updated on next getDynamicTags() call:
+ this.dynamicTags = null;
+ break;
+ case 'dynamicTagCodes':
+ // If set to null, the dynamicTagCodes will be updated on next getDynamicTagCodes() call:
+ this.dynamicTagCodes = null;
+ break;
+ case 'hideContextMenuItem':
+ this.hideContextMenuItemUpdate();
+ break;
+ case 'hideFormFieldsContextMenu':
+ this.hideContextMenuItemUpdate();
+ break;
+ case 'hideStatusbarIcon':
+ this.hideStatusbarIconUpdate();
+ break;
+ case 'hideToolbarButton':
+ this.hideToolbarButtonUpdate();
+ this.hideToolbarButtonMenuUpdate();
+ break;
+ case 'hideToolbarButtonMenu':
+ this.hideToolbarButtonMenuUpdate();
+ break;
+ case 'useConfigDirectory':
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ this.exportToConfigDirectory();
+ } else {
+ this.importFromConfigDirectory();
+ }
+ break;
+ }
+ },
+
+ hideContextMenuItemUpdate: function() {
+ var contentAreaContextMenu = document.getElementById('contentAreaContextMenu');
+ if(contentAreaContextMenu) {
+ if(!this.autofillFormsPrefs.getBoolPref('hideContextMenuItem')
+ || !this.autofillFormsPrefs.getBoolPref('hideFormFieldsContextMenu')) {
+ // Add the content area context menu listener:
+ contentAreaContextMenu.addEventListener(
+ 'popupshowing',
+ this.contentAreaContextMenuEventListener,
+ false
+ );
+ } else {
+ var cm0 = document.getElementById('autofillFormsContextMenuItem');
+ var cm1 = document.getElementById('autofillFormsContextMenu');
+ var cm2 = document.getElementById('autofillFormsManualFillContextMenu');
+ var cm3 = document.getElementById('autofillFormsAddRuleContextMenuItem');
+ var cm4 = document.getElementById('autofillFormsAddFormAsProfileContextMenuItem');
+ var cm5 = document.getElementById('autofillFormsContextMenuSeparator1');
+ var cm6 = document.getElementById('autofillFormsContextMenuSeparator2');
+ if(cm0) {
+ cm0.hidden = true;
+ cm1.hidden = true;
+ cm2.hidden = true;
+ cm3.hidden = true;
+ cm4.hidden = true;
+ cm5.hidden = true;
+ cm6.hidden = true;
+ }
+ // Remove the content area context menu listener:
+ this.targetFormField = null;
+ contentAreaContextMenu.removeEventListener(
+ 'popupshowing',
+ this.contentAreaContextMenuEventListener,
+ false
+ );
+ }
+ }
+ },
+
+ hideStatusbarIconUpdate: function() {
+ // Change the statusbar icon visibility:
+ var autofillFormsPanelIcon = document.getElementById('autofillFormsPanelIcon');
+ if(autofillFormsPanelIcon) {
+ autofillFormsPanelIcon.setAttribute(
+ 'hidden',
+ this.autofillFormsPrefs.getBoolPref('hideStatusbarIcon')
+ );
+ }
+ },
+
+ installToolbarButton: function(buttonID, beforeNodeID, toolbarID) {
+ beforeNodeID = beforeNodeID ? beforeNodeID : 'home-button';
+ toolbarID = toolbarID ? toolbarID : 'navigation-toolbar';
+ if(!document.getElementById(buttonID)) {
+ var toolbar = document.getElementById(toolbarID);
+ if(!toolbar) {
+ // Firefox < 3:
+ toolbar = document.getElementById('nav-bar');
+ }
+ if(toolbar && 'insertItem' in toolbar) {
+ var beforeNode = document.getElementById(beforeNodeID);
+ if(beforeNode && beforeNode.parentNode != toolbar) {
+ beforeNode = null;
+ }
+ // Insert before the given node or at the end of the toolbar if the node is not available:
+ toolbar.insertItem(buttonID, beforeNode, null, false);
+ toolbar.setAttribute('currentset', toolbar.currentSet);
+ document.persist(toolbar.id, 'currentset');
+ }
+ }
+ },
+
+ hideToolbarButtonUpdate: function() {
+ var autofillFormsButton = document.getElementById('autofillFormsButton');
+ var hideToolbarButton = this.autofillFormsPrefs.getBoolPref('hideToolbarButton');
+ if(!autofillFormsButton && !hideToolbarButton) {
+ // Add the toolbar button to the toolbar:
+ this.installToolbarButton('autofillFormsButton');
+ autofillFormsButton = document.getElementById('autofillFormsButton');
+ }
+ if(autofillFormsButton) {
+ autofillFormsButton.setAttribute(
+ 'hidden',
+ hideToolbarButton
+ );
+ }
+ },
+
+ hideToolbarButtonMenuUpdate: function() {
+ var autofillFormsButton = document.getElementById('autofillFormsButton');
+ if(autofillFormsButton) {
+ if(this.autofillFormsPrefs.getBoolPref('hideToolbarButtonMenu')) {
+ autofillFormsButton.removeAttribute('type');
+ } else {
+ autofillFormsButton.setAttribute('type','menu-button');
+ }
+ }
+ },
+
+ commandHandler: function(event) {
+ if(typeof event.button == 'undefined') {
+ // If no event.button is set, the command has been done by the left mouse button:
+ event.button = 0;
+ }
+ // Recognize the mouse button and perform the associated action:
+ var mouseButtonObj = this.recognizeMouseButton(event);
+ if(this.getMouseButton('mouseShortcut').equals(mouseButtonObj)) {
+ this.fillForms();
+ } else if(this.getMouseButton('mouseShortcutSubmit').equals(mouseButtonObj)) {
+ this.fillForms(null, null, true);
+ } else if(this.getMouseButton('mouseShortcutAllTabs').equals(mouseButtonObj)) {
+ this.fillForms(null, null, null, true);
+ } else if(this.getMouseButton('mouseShortcutFromProfileSelection').equals(mouseButtonObj)) {
+ this.profileSelectionFormFillPopup(event);
+ } else if(this.getMouseButton('mouseShortcutProfile').equals(mouseButtonObj)) {
+ this.showProfileSwitcher(event);
+ } else if(this.getMouseButton('mouseShortcutSettings').equals(mouseButtonObj)) {
+ this.showDialog('chrome://autofillForms/content/autofillFormsOptions.xul');
+ } else if(this.getMouseButton('mouseShortcutDisplayFormDetails').equals(mouseButtonObj)) {
+ this.displayFormDetails();
+ }
+ },
+
+ clickHandler: function(event) {
+ switch(event.button) {
+ case 0:
+ // The left mouse button is already handled for clicks on the toolbar button,
+ // but not for clicks on the status bar icon:
+ if(event.target.id == 'autofillFormsPanelIcon') {
+ this.commandHandler(event);
+ }
+ break;
+ default:
+ this.commandHandler(event);
+ }
+ },
+
+ profileSelectionFormFillPopup: function(event) {
+ var popup = document.getElementById('autofillFormsProfileSelectionPopup');
+ if(popup && typeof popup.openPopup == 'function') {
+ this.prepareProfileSelectionFormFillMenu(popup);
+ // Show the popup menu (only available for Firefox >= 3):
+ popup.openPopup(event.target, null, 0, 0, false, true);
+ } else {
+ this.profileSelectionFormFillPrompt(event);
+ }
+ },
+
+ prepareProfileSelectionFormFillMenu: function(menupopup) {
+ // Remove all children nodes:
+ while(menupopup.hasChildNodes()) {
+ menupopup.removeChild(menupopup.firstChild);
+ }
+ var menuitem = document.createElement('menuitem');
+ menuitem.setAttribute('class','menuitem-iconic autofillFormsIcon');
+ // Add the profile labels as menu items:
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ menuitem = menuitem.cloneNode(false);
+ menuitem.setAttribute('label', this.getProfileLabel(i));
+ menuitem.setAttribute('data-index', i);
+ menuitem.addEventListener("command", function () {
+ var i = +this.getAttribute('data-index');
+ autofillForms.fillForms(null, i);
+ });
+ menupopup.appendChild(menuitem);
+ }
+ },
+
+ profileSelectionFormFillPrompt: function(event) {
+ // Show a profile selection prompt and fill out forms with the selected profile:
+ var list = this.getProfileLabels();
+ var selected = {};
+ var ok = this.getPrompts().select(
+ window,
+ this.getStringBundle().getString('profileSelectionFormFillTitle'),
+ this.getStringBundle().getString('profileSelectionPrompt'),
+ list.length,
+ list,
+ selected
+ );
+ if(ok) {
+ this.fillForms(null, selected.value);
+ }
+ },
+
+ fillForms: function(win, profileIndex, autoSubmit, allTabs) {
+ if(!win || !win.document) {
+ win = this.getWin();
+ }
+
+ var currentProfileIndex = this.getProfileIndex();
+ var toggleAutoSelectBestProfile;
+ if(typeof profileIndex == 'number') {
+ // Temporarily set the given profile index:
+ this.setProfileIndex(profileIndex);
+
+ if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
+ // Temporarily disable autoSelectBestProfile:
+ this.autofillFormsPrefs.setBoolPref('autoSelectBestProfile', false);
+ toggleAutoSelectBestProfile = true;
+ }
+ }
+
+ autoSubmit = autoSubmit ? autoSubmit : null;
+
+ if(allTabs) {
+ // Fill out forms on all open browser tabs:
+ for(var i=0; i<this.getBrowser().browsers.length; i++) {
+ this.searchAndFillForms(
+ this.getBrowser().getBrowserAtIndex(i).contentWindow,
+ autoSubmit
+ );
+ }
+ } else {
+ // Fill out forms on the current tab (or the given window object):
+ this.searchAndFillForms(win, autoSubmit);
+ }
+
+ // Reset Alternatives (including the cache):
+ this.fieldRuleAlternativesIndex = null;
+ this.fieldRuleAlternativesLength = null;
+ this.fieldRuleAlternativesHash = null;
+ this.fieldRuleAlternativesCache = null;
+
+ // Reset objects to release used memory:
+ this.fieldRules = null;
+ this.profileSiteRules = null;
+ this.dynamicTags = null;
+ this.dynamicTagCodes = null;
+
+ // Reset the selected profile:
+ this.setProfileIndex(currentProfileIndex);
+
+ if(toggleAutoSelectBestProfile) {
+ // Reenable autoSelectBestProfile:
+ this.autofillFormsPrefs.setBoolPref('autoSelectBestProfile', true);
+ }
+ },
+
+ searchAndFillForms: function(win, autoSubmit) {
+ var doc = this.getDoc(win);
+
+ // Check if any web forms are available on the current window:
+ if(doc && doc.forms && doc.forms.length > 0) {
+
+ var url = doc.location.href;
+
+ if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
+ // Remember the currently selected profile:
+ var currentProfileIndex = this.getProfileIndex();
+ }
+
+ // Select the best matching profile - returns false if none matches:
+ if(!this.selectBestMatchingProfile(url)) {
+ return;
+ }
+
+ this.currentWindow = win;
+
+ // Holds the form to be submitted:
+ var submitForm;
+ // Holds the first submit element found on the form:
+ var submitElement;
+
+ // Go through the forms:
+ for(var i = 0; i < doc.forms.length; i++) {
+ this.currentFormIndex = i;
+
+ // The form elements list:
+ var elements = doc.forms[i].elements;
+
+ // A hash to store the alternatives for radio input fields:
+ this.fieldRuleAlternativesHash = new Object();
+
+ // Go through the form elements:
+ for(var j = 0; j < elements.length; j++) {
+ this.currentElementIndex = j;
+
+ // Fill out valid form field types:
+ if(this.isValidFormField(elements[j])) {
+ this.setFormField(elements[j], url);
+ }
+
+ // Collect the first submit button of the form if autoSubmit is enabled:
+ if(autoSubmit && elements[j].type && elements[j].type == 'submit' && !submitElement) {
+ submitElement = elements[j];
+ }
+ }
+
+ this.applyStoredFieldRulesAlternatives();
+
+ if(autoSubmit) {
+ if(this.lastFormElementMatch && this.lastFormElementMatch.form == doc.forms[i]) {
+ // Elements have been matched on this form, check the submitElement:
+ if(!submitElement) {
+ submitElement = this.getImageSubmitButton(doc.forms[i]);
+ }
+ submitForm = doc.forms[i];
+ // Break out of the forms loop:
+ break;
+ } else {
+ submitElement = null;
+ }
+ }
+ }
+
+ if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
+ // Reset the selected profile to the manually selected one:
+ this.setProfileIndex(currentProfileIndex);
+ }
+
+ if(this.lastFormElementMatch && this.autofillFormsPrefs.getBoolPref('focusLastFormElementMatch')) {
+ // Set the focus to the last matched form element:
+ this.lastFormElementMatch.focus();
+ }
+
+ // Reset the last matched form element:
+ this.lastFormElementMatch = null;
+
+ this.currentWindow = null;
+ this.currentFormIndex = null;
+ this.currentElementIndex = null;
+
+ if(autoSubmit && submitForm) {
+ // autoSubmit the form with a click on the submit button if found
+ // or else by calling the submit() method on the form:
+ if(submitElement) {
+ submitElement.click();
+ } else {
+ submitForm.submit();
+ }
+ }
+ }
+
+ // Recursive call for all subframes:
+ for(var f=0; f < win.frames.length; f++) {
+ this.searchAndFillForms(win.frames[f], autoSubmit);
+ }
+ },
+
+ getImageSubmitButton: function(form) {
+ var inputElements = form.getElementsByTagName('input');
+ for(var i = 0; i < inputElements.length; i++) {
+ if(inputElements[i].type == 'image') {
+ return inputElements[i];
+ }
+ }
+ },
+
+ selectBestMatchingProfile: function(url) {
+ if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
+ var match;
+ // The emtpy siteRule (?:) has a match length of 0, so we set the initial value to -1:
+ var maxMatch = -1;
+ var index = -1;
+ // First test the currently selected profile:
+ try {
+ match = url.match(new RegExp(this.getProfileSiteRule(this.getProfileIndex()),'i'));
+ if(match && (match.toString()).length > maxMatch) {
+ maxMatch = (match.toString()).length;
+ index = this.getProfileIndex();
+ }
+ } catch(e) {
+ // Catch errors caused by invalid profile site rules
+ }
+ for(var i=0; i<this.getProfileSiteRules().length; i++) {
+ if(i == this.getProfileIndex()) {
+ // Skip the current profile (already tested):
+ continue;
+ }
+ try {
+ match = url.match(new RegExp(this.getProfileSiteRule(i),'i'));
+ if(match && (match.toString()).length > maxMatch) {
+ maxMatch = (match.toString()).length;
+ index = i;
+ }
+ } catch(e) {
+ // Catch errors caused by invalid profile site rules
+ }
+ }
+ if(index > -1) {
+ // Select the profile with the best match:
+ this.setProfileIndex(index);
+ return true;
+ }
+ } else {
+ try {
+ var regExp = new RegExp(this.getProfileSiteRule(this.getProfileIndex()),'i');
+ if(regExp.test(url)) {
+ return true;
+ }
+ } catch(e) {
+ // Catch errors caused by invalid profile site rules
+ }
+ }
+ return false;
+ },
+
+ setFormField: function(element,url) {
+ var matchFound = false;
+
+ // Apply the fieldRules of the current profile:
+ matchFound = this.applyFieldRulesOnElement(element,url,this.getFieldRules());
+
+ // If no match has been found, apply the fieldRules of the global profile, if enabled:
+ if(!matchFound && this.autofillFormsPrefs.getBoolPref('enableGlobalProfile')) {
+ // Only apply the global profile fieldRules if the current profile is not the global profile;
+ if(this.getProfileIndex() != this.getGlobalProfileIndex()) {
+ // Only apply the global profile if the global profile site rule matches the url:
+ try {
+ var regExp = new RegExp(this.getProfileSiteRule(this.getGlobalProfileIndex()),'i');
+ if(regExp.test(url)) {
+ matchFound = this.applyFieldRulesOnElement(element,url,this.getGlobalFieldRules());
+ }
+ } catch(e) {
+ // Catch errors caused by invalid profile site rules
+ }
+ }
+ }
+
+ // Highlight styles:
+ var highlightStyleMatch = this.autofillFormsPrefs.getCharPref('highlightStyleMatch');
+ var highlightStyleNoMatch = this.autofillFormsPrefs.getCharPref('highlightStyleNoMatch');
+
+ if(matchFound) {
+ // Set the current element as the last matched form element:
+ this.lastFormElementMatch = element;
+
+ if(highlightStyleMatch) {
+ // Highlight matched form fieds:
+ element.setAttribute('style', highlightStyleMatch);
+ }
+ } else if(highlightStyleNoMatch) {
+ // Highlight not matched form fieds:
+ element.setAttribute('style', highlightStyleNoMatch);
+ }
+ },
+
+ getIndexForFieldRules: function(fieldRules) {
+ if(this.fieldRules) {
+ for(var i=0; i<this.fieldRules.length; i++) {
+ if(this.fieldRules[i] === fieldRules) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ },
+
+ fieldRuleAlternativeFactory: function(fieldRules, index) {
+ var af = this;
+ if(typeof arguments.callee.fieldRuleAlternative == 'undefined') {
+ arguments.callee.fieldRuleAlternative = function(fieldRules, index) {
+ this.fieldRules = fieldRules;
+ this.index = index;
+ this.fieldRule = this.fieldRules[this.index];
+ return this;
+ }
+ arguments.callee.fieldRuleAlternative.prototype = {
+ af : af,
+ fieldRuleValue: null,
+ fieldRuleValueRegExp: null,
+ fieldRuleRegExp: null,
+ siteRuleRegExp: null,
+ optionsIndex: null,
+ element: null,
+ getValue: function() {
+ if(this.fieldRuleValue === null) {
+ // Replace dynamic tags if enabled:
+ if(this.af.autofillFormsPrefs.getBoolPref('enableDynamicTags'))
+ this.fieldRuleValue = this.af.replaceDynamicTags(this.fieldRule['fieldRuleValue']);
+ else
+ this.fieldRuleValue = this.fieldRule['fieldRuleValue'];
+ }
+ return this.fieldRuleValue;
+ },
+ getRule: function() {
+ return this.fieldRule['fieldRuleFieldRule'];
+ },
+ getName: function() {
+ return this.fieldRule['fieldRuleName'];
+ },
+ isEnabled: function() {
+ return this.fieldRule['fieldRuleEnabled'];
+ },
+ isURLMatching: function(url) {
+ if(this.siteRuleRegExp === null) {
+ this.siteRuleRegExp = new RegExp(this.fieldRule['fieldRuleSiteRule'],'i');
+ }
+ // Test if the siteRule matches the given URL:
+ return this.siteRuleRegExp.test(url);
+ },
+ isRuleMatching: function(str) {
+ if(this.fieldRuleRegExp === null) {
+ this.fieldRuleRegExp = new RegExp(this.fieldRule['fieldRuleFieldRule'],'i');
+ }
+ // Test if the fieldRule matches the given string:
+ return this.fieldRuleRegExp.test(str);
+ },
+ isValueMatching: function(str) {
+ try {
+ if(this.fieldRuleValueRegExp === null) {
+ this.fieldRuleValueRegExp = new RegExp(this.getValue(),'i');
+ }
+ // Test if the value as regular expression matches the given string:
+ return this.fieldRuleValueRegExp.test(str);
+ } catch(e) {
+ // If turning the value into a regular expression fails, compare the strings:
+ return (str == this.getValue());
+ }
+ },
+ isOverwrite: function() {
+ // This setting defines if existing field contents should be overwritten
+ // and if checkboxes and radio buttons should be checked or unchecked
+ // and if selection options should be selected or unselected:
+ return this.fieldRule['fieldRuleOverwrite']
+ },
+ getIndex: function() {
+ return this.index;
+ },
+ getOptionsIndex: function() {
+ return this.optionsIndex;
+ },
+ setOptionsIndex: function(optionsIndex) {
+ this.optionsIndex = optionsIndex;
+ },
+ getElement: function() {
+ return this.element;
+ },
+ setElement: function(element) {
+ this.element = element;
+ },
+ clone: function() {
+ // This creates only a shallow copy,
+ // though we only need a shallow copy:
+ var clone = new this.constructor();
+ for(var key in this) {
+ clone[key] = this[key];
+ }
+ return clone;
+ }
+ }
+ }
+ if(this.fieldRuleAlternativesCache == null) {
+ this.fieldRuleAlternativesCache = new Object();
+ }
+ var identifier = this.getIndexForFieldRules(fieldRules)+'-'+index;
+ if(!this.fieldRuleAlternativesCache[identifier]) {
+ this.fieldRuleAlternativesCache[identifier] = new arguments.callee.fieldRuleAlternative(
+ fieldRules,
+ index
+ );
+ } else {
+ // Clone the cached alternative and set the clone as new cached element:
+ this.fieldRuleAlternativesCache[identifier] = this.fieldRuleAlternativesCache[identifier].clone()
+ }
+ return this.fieldRuleAlternativesCache[identifier];
+ },
+
+ getLabelForElement: function(element) {
+ if(element.form && element.id) {
+ // Method to retrieve the textual content of the label assigned to the form element:
+ var labels = element.form.getElementsByTagName('label');
+ for(var i=0; i<labels.length; i++) {
+ if(labels[i].htmlFor && labels[i].htmlFor == element.id) {
+ // label elements may contain other inline elements,
+ // so we just use the innerHTML content and strip it of all HTML tags
+ // whitespace is removed from the beginning and end of the string for convenience:
+ return this.trim(this.stripTags(labels[i].innerHTML));
+ }
+ }
+ }
+ if(!this.autofillFormsPrefs.getBoolPref('labelsStrictMode')) {
+ return this.getLabelCloseToElement(element);
+ }
+ return null;
+ },
+
+ getLabelCloseToElement: function(element) {
+ var label = null;
+ var node = element;
+ var nextNode;
+ if(element.type == 'checkbox' || element.type == 'radio') {
+ // For checkboxes and radio buttons the label is usually placed as nextSibling:
+ nextNode = 'nextSibling';
+ } else {
+ // For other elements the label is usually placed as previousSibling:
+ nextNode = 'previousSibling';
+ }
+ // Check if a sibling contains the element label:
+ while(node[nextNode]) {
+ node = node[nextNode];
+ label = this.getNodeTextContent(node, true);
+ if(label) {
+ return label;
+ }
+ }
+ // Parse the siblings of the parentNode:
+ node = element.parentNode;
+ if(node) {
+ while(node[nextNode]) {
+ node = node[nextNode];
+ label = this.getNodeTextContent(node, true);
+ if(label) {
+ return label;
+ }
+ }
+ // If the parentNode of the parentNode is a table cell,
+ // also parse the siblings of this node:
+ node = element.parentNode.parentNode;
+ if(node && node.nodeName == 'TD') {
+ while(node[nextNode]) {
+ node = node[nextNode];
+ label = this.getNodeTextContent(node, true);
+ if(label) {
+ return label;
+ }
+ }
+ }
+ }
+ return null;
+ },
+
+ getNodeTextContent: function(node, trim) {
+ // Get the text content from the current node or its child nodes:
+ var text;
+ if(node.nodeType == 3) {
+ // nodeType 3 is a text node:
+ text = node.nodeValue;
+ } else {
+ // Do not follow selection nodes, script nodes or noscript nodes:
+ if(node.nodeName == 'SELECT' || node.nodeName == 'SCRIPT' || node.nodeName == 'NOSCRIPT') {
+ return '';
+ }
+ text = '';
+ for(var i=0; i<node.childNodes.length; i++) {
+ text += this.getNodeTextContent(node.childNodes[i]);
+ }
+ }
+ if(trim) {
+ return this.trim(text);
+ } else {
+ return text;
+ }
+ },
+
+ applyFieldRulesOnElement: function(element,url,fieldRules) {
+
+ var labelValue = this.autofillFormsPrefs.getBoolPref('matchAgainstLabels') ?
+ this.getLabelForElement(element) : null;
+
+ var positionString = this.autofillFormsPrefs.getBoolPref('matchAgainstPositions') ?
+ this.currentFormIndex + this.autofillFormsPrefs.getCharPref('positionsIdentifier')
+ + this.currentElementIndex : null;
+
+ var fieldRuleAlternatives = new Array();
+
+ // Go through the list of fieldRules:
+ for(var i=0; i < fieldRules.length; i++) {
+
+ var rule = this.fieldRuleAlternativeFactory(fieldRules, i);
+
+ // Skip this rule if
+ // a) the rule is disabled and disabled rules are to be ignored or
+ // b) the current URL is not matching the siteRule or
+ // c) all of the following are false:
+ // 1) the element name does not match the fieldRule
+ // 2) label matching is disabled or the element label does not match the fieldRule
+ // 3) the element name is not empty or the element id does not match the fieldRule
+ // 4) position matching is disabled or the position does not match the fieldRule
+ if( !rule.isEnabled() &&
+ this.autofillFormsPrefs.getBoolPref('ignoreDisabledRulesOnAutofill') ||
+ !rule.isURLMatching(url) ||
+ (
+ !rule.isRuleMatching(element.name) &&
+ (labelValue === null || !rule.isRuleMatching(labelValue)) &&
+ (element.name || !rule.isRuleMatching(element.id)) &&
+ (positionString === null || !rule.isRuleMatching(positionString))
+ )
+ ) {
+ if(fieldRuleAlternatives.length > 0) {
+ // Break out of the loop, if we already have an alternative:
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ if(element.type == 'select-one' || element.type == 'select-multiple') {
+ // Go through the selection options:
+ for(var j = 0; j < element.options.length; j++) {
+ // Match either the value or the text (the selection option label):
+ if(rule.isValueMatching(element.options[j].value) || rule.isValueMatching(element.options[j].text)) {
+ // Remember the matching option:
+ rule.setOptionsIndex(j);
+ // Remember the element:
+ rule.setElement(element);
+ // Add a clone of the alternative and continue to see if the value matches several options:
+ fieldRuleAlternatives.push(rule.clone());
+ }
+ }
+ } else if(element.type == 'checkbox' || element.type == 'radio') {
+ if(rule.isValueMatching(element.value)) {
+ // Remember the element:
+ rule.setElement(element);
+ // Add the alternative:
+ fieldRuleAlternatives.push(rule);
+ // Only one rule has to match a checkbox/radio button, so we break out of the loop:
+ break;
+ }
+ } else {
+ // Remember the element:
+ rule.setElement(element);
+ // Add the alternative:
+ fieldRuleAlternatives.push(rule);
+ }
+ if(this.autofillFormsPrefs.getBoolPref('callOnChangeAfterFillingFields')) {
+ this.fireEvent(element,'change')
+ }
+ }
+
+ return this.applyFieldRulesAlternativesOnElement(element,fieldRuleAlternatives);
+ },
+
+ applyFieldRulesAlternativesOnElement: function(element,fieldRuleAlternatives) {
+ if(fieldRuleAlternatives.length == 0) {
+ return false;
+ }
+
+ if (this.autofillFormsPrefs.getBoolPref('focusLastFormElementMatch')) {
+ element.focus();
+ }
+
+ // Add a box (with some help from Mike Ratcliffe)
+ // http://groups.google.com/group/firebug/browse_thread/thread/7d4bd89537cd24e7/2c9483d699efe257?hl=en
+ // TODO: why doesn't getBoundingClientRect return the absolute coordinates of the element?
+ // At the moment, I'm looking at the offset of the doc.body and use that to calculate the absolute coordinates
+ // what's the offset -4,+1 pixel relative to? the size of the window border?
+ //
+ var doc = this.getDoc();
+ var div1 = doc.createElement('div');
+
+ var rect = element.getBoundingClientRect();
+ var rectBody = doc.body.getBoundingClientRect();
+
+ //Firebug.Console.log(element);
+ //Firebug.Console.log(rect.left+' '+rect.top+' '+rect.right+' '+rect.bottom+' '+rect.width+' '+rect.height);
+ //Firebug.Console.log(rectBody.left+' '+rectBody.top+' '+rectBody.right+' '+rectBody.bottom+' '+rectBody.width+' '+rectBody.height);
+
+ //maybe something here...
+ //Firebug.Console.log(element.clientLeft+' '+element.clientTop)
+ //Firebug.Console.log(element.scrollLeft+' '+element.scrollTop)
+
+ //Firebug.Console.log(doc.body)
+ //Firebug.Console.log(rect)
+ //Firebug.Console.log(rectBody)
+
+ //div1.setAttribute('id', 'autoformHighlight');
+ div1.setAttribute('style', 'position:absolute;z-index:2147483646'
+ + ';border-width: 2px; border-color: red; border-style:solid'
+ + ';left:'+(rect.left-rectBody.left-1)+'px'
+ + ';top:'+(rect.top-rectBody.top+3)+'px'
+ + ';width:'+rect.width+'px'
+ + ';height:'+rect.height+'px'
+ );
+ doc.body.appendChild(div1);
+
+ // Use all alternatives for select-multiple elements:
+ if(element.type == 'select-multiple') {
+ for(var i=0; i < fieldRuleAlternatives.length; i++) {
+ var rule = fieldRuleAlternatives[i];
+ if(rule.isOverwrite()) {
+ element.options[rule.getOptionsIndex()].selected = true;
+ } else {
+ element.options[rule.getOptionsIndex()].selected = false;
+ }
+ }
+ doc.body.removeChild(div1);
+ return true;
+ }
+
+ // Select the alternatives index (displays a selection dialog if required):
+ var index = this.selectFieldRulesAlternativesIndex(fieldRuleAlternatives);
+
+ if(index == -1) {
+ doc.body.removeChild(div1);
+ return false;
+ } else {
+ var rule = fieldRuleAlternatives[index];
+ if(element.type == 'select-one') {
+ if(rule.isOverwrite()) {
+ element.options[rule.getOptionsIndex()].selected = true;
+ } else {
+ element.options[rule.getOptionsIndex()].selected = false;
+ }
+ } else if(element.type == 'checkbox') {
+ if(rule.isOverwrite()) {
+ element.checked = true;
+ } else {
+ element.checked = false;
+ }
+ } else if(element.type == 'radio') {
+ try {
+ // Rules matching radio elements are stored and handled as group
+ // at the end of each form loop with the applyStoredFieldRulesAlternatives method:
+ if(!this.fieldRuleAlternativesHash[element.name]) {
+ this.fieldRuleAlternativesHash[element.name] = new Array();
+ }
+ this.fieldRuleAlternativesHash[element.name].push(rule);
+ } catch(e) {
+ this.log(e);
+ doc.body.removeChild(div1);
+ return false;
+ }
+ } else {
+ if(!element.value || rule.isOverwrite()) {
+ if(element.type == 'textarea') {
+ // Replace control character placeholders:
+ element.value = this.replaceControlCharacterPlaceholders(rule.getValue());
+ } else {
+ element.value = rule.getValue();
+ }
+ }
+ }
+ if(this.autofillFormsPrefs.getBoolPref('callOnChangeAfterFillingFields')) {
+ this.fireEvent(element,'change')
+ }
+
+
+ }
+
+ //remove the div, not needed anymore
+ doc.body.removeChild(div1);
+ return true;
+ },
+
+ fireEvent: function(element,anEvent) {
+ var evt = document.createEvent("HTMLEvents");
+ evt.initEvent(anEvent, true, true ); // event type,bubbling,cancelable
+ return !element.dispatchEvent(evt);
+ },
+
+ applyStoredFieldRulesAlternatives: function() {
+ for(var key in this.fieldRuleAlternativesHash) {
+ var fieldRuleAlternatives = this.filterRealFieldRuleAlternatives(
+ this.fieldRuleAlternativesHash[key]
+ );
+ var index = this.selectFieldRulesAlternativesIndex(fieldRuleAlternatives);
+ if(index != -1) {
+ var rule = fieldRuleAlternatives[index];
+ // This is currently only used for radio input fields:
+ if(rule.isOverwrite()) {
+ rule.getElement().checked = true;
+ } else {
+ rule.getElement().checked = false;
+ }
+ }
+ }
+ },
+
+ filterRealFieldRuleAlternatives: function(fieldRuleAlternatives) {
+ // Sort the fieldRuleAlternatives by index:
+ fieldRuleAlternatives.sort(this.compareFieldRuleAlternativesByIndex);
+ // Make sure only real Alternatives (placed next to each other) are included:
+ for(var i=1; i<fieldRuleAlternatives.length; i++) {
+ // If the fieldRules index is more than one step larger than the previous one,
+ // the remaining array items can be sliced off - they are no real Alternatives:
+ if(fieldRuleAlternatives[i].getIndex()-1 > fieldRuleAlternatives[i-1].getIndex()) {
+ fieldRuleAlternatives = fieldRuleAlternatives.slice(0, i);
+ break;
+ }
+ }
+ return fieldRuleAlternatives;
+ },
+
+ compareFieldRuleAlternativesByIndex: function(ruleA, ruleB) {
+ if(ruleA.getIndex() < ruleB.getIndex()) {
+ return -1;
+ } else if(ruleA.getIndex() > ruleB.getIndex()) {
+ return 1;
+ }
+ return 0;
+ },
+
+ getFieldRulesAlternativeLabel: function(rule) {
+ // This method returns a label for this alternative
+ // to be displayed on the alternatives selection
+ switch(rule.getElement().type) {
+ case 'select-multiple':
+ case 'select-one':
+ // Use the options text:
+ return rule.getElement().options[rule.getOptionsIndex()].text;
+ case 'radio':
+ case 'checkbox':
+ // Try to retrieve the element label:
+ var label = this.getLabelForElement(rule.getElement());
+ // Remove the colon, if present:
+ if(label && label.charAt(label.length-1) == ':') {
+ label = label.substr(0, label.length-1);
+ }
+ // If no label could be found,
+ // use the element value:
+ if(!label) {
+ label = rule.getElement().value;
+ }
+ return label;
+ default:
+ // Use the calculated value:
+ return rule.getValue();
+ }
+ },
+
+ selectFieldRulesAlternativesIndex: function(fieldRuleAlternatives) {
+ // Display a selection prompt if we have alternatives and no alternativesIndex has been set yet
+ // or the rememberAlternativesIndex setting is false or the saved alternativesLength is different:
+ if(fieldRuleAlternatives.length > 1) {
+ // When alternatives are disabled, return either 0 (remember the alternative)
+ // or cycle through the available alternatives.
+ if(this.autofillFormsPrefs.getBoolPref('disableAlternatives') == true) {
+ var fieldRuleAlternativesIndex = 0;
+ /*
+ //todo take into account multiple instances of the form field. Can't increase the index blindly...
+ if(this.autofillFormsPrefs.getBoolPref('rememberAlternativesIndex') == false) {
+ fieldRuleAlternativesIndex = this.fieldRuleAlternativesIndex;
+ if (this.fieldRuleAlternativesIndex == fieldRuleAlternatives.length-1) {
+ this.fieldRuleAlternativesIndex = 0;
+ }
+ else {
+ this.fieldRuleAlternativesIndex += 1;
+ }
+ }
+ */
+ return fieldRuleAlternativesIndex;
+ }
+
+ if(this.autofillFormsPrefs.getBoolPref('rememberAlternativesIndex') == false
+ || this.fieldRuleAlternativesIndex === null
+ || fieldRuleAlternatives.length != this.fieldRuleAlternativesLength) {
+ // The selection list displays the index number and the current fieldRuleValues:
+ var list = new Array();
+ var maxFigureLength = fieldRuleAlternatives.length.toString().length;
+ for(var i=0; i < fieldRuleAlternatives.length; i++) {
+ list.push(
+ this.addLeadingZeros(i+1, maxFigureLength)
+ + '. '
+ + this.getFieldRulesAlternativeLabel(fieldRuleAlternatives[i])
+ + ' - '
+ + fieldRuleAlternatives[i].getName()
+ );
+ }
+ var selected = {};
+ // Show the selection prompt:
+ var ok = this.getPrompts().select(
+ window,
+ this.getStringBundle().getString('alternativesSelectionWindowTitle'),
+ this.getStringBundle().getString('alternativesSelectionPrompt'),
+ list.length,
+ list,
+ selected
+ );
+ // Save the selected alternatives index, return -1 on cancel:
+ if(ok)
+ this.fieldRuleAlternativesIndex = selected.value;
+ else
+ return -1;
+
+ this.fieldRuleAlternativesLength = fieldRuleAlternatives.length;
+ }
+ // Use the fieldRuleAlternative with the selected fieldRuleAlternativesIndex:
+ return this.fieldRuleAlternativesIndex;
+ } else if(fieldRuleAlternatives.length == 1) {
+ return 0;
+ }
+ return -1;
+ },
+
+ stripTags: function(str) {
+ if (!arguments.callee.regExp) {
+ arguments.callee.regExp = new RegExp('<\\/?[^>]+?>', 'g');
+ }
+ // Return string stripped from HTML tags:
+ return str.replace(arguments.callee.regExp, '');
+ },
+
+ trim: function(str) {
+ if (!arguments.callee.regExp) {
+ arguments.callee.regExp = new RegExp('(?:^\\s+)|(?:\\s+$)', 'g');
+ }
+ // Return string with whitespace removed at beginning and end of the string:
+ return str.replace(arguments.callee.regExp, '');
+ },
+
+ initProfilesPopupMenu: function(event) {
+ var menupopup = event.target;
+ // Remove all children nodes:
+ while(menupopup.hasChildNodes()) {
+ menupopup.removeChild(menupopup.firstChild);
+ }
+ // Add the profile labels as menu items:
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ var menuitem = document.createElement('menuitem');
+ menuitem.setAttribute('label', this.getProfileLabel(i));
+ menuitem.setAttribute('data-index', i);
+ menuitem.addEventListener("command", function () {
+ var i = +this.getAttribute('data-index');
+ autofillForms.setProfileIndex(i);
+ });
+ menuitem.setAttribute('type', 'radio');
+ if(i == this.getProfileIndex()) {
+ menuitem.setAttribute('checked', true);
+ }
+ menupopup.appendChild(menuitem);
+ }
+ },
+
+ initManualFillContextMenu: function(event) {
+ var menupopup = event.target;
+ // Remove all children nodes:
+ while(menupopup.hasChildNodes()) {
+ menupopup.removeChild(menupopup.firstChild);
+ }
+
+ var authenticationNeeded = false;
+ if(this.autofillFormsPrefs.getBoolPref('storeEncrypted')) {
+ // Determine if a master password is set and the user has not been authenticated yet:
+ authenticationNeeded = this.getMasterSecurityDevice().getInternalKeyToken().needsLogin()
+ && !this.getMasterSecurityDevice().getInternalKeyToken().isLoggedIn();
+ }
+
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Always retrieve the profile labels from file if useConfigDirectory is enabled:
+ this.profileLabels = null;
+ }
+
+ // Check if only one profile is to be shown:
+ if((this.getFormFieldsContextMenuProfileIndex() != -3) || (this.getProfileLabels().length == 1)) {
+ var profileIndex = (this.getFormFieldsContextMenuProfileIndex() == -2)
+ ? this.getProfileIndex() : this.getFormFieldsContextMenuProfileIndex();
+ if(authenticationNeeded) {
+ var menuitem = document.createElement('menuitem');
+ menuitem.setAttribute('label', this.getProfileLabel(profileIndex)+'...');
+ menuitem.setAttribute('data-profileIndex', profileIndex);
+ menuitem.addEventListener("command", function () {
+ var i = +this.getAttribute('data-profileIndex');
+ autofillForms.authenticateAndShowManualFillDialog(i);
+ });
+ menupopup.appendChild(menuitem);
+ } else {
+ this.initManualFillProfileContextMenu(event, profileIndex);
+ }
+ return;
+ }
+
+ // Add the profile labels as menus or menuitems if authentication is needed:
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ if(authenticationNeeded) {
+ var menuitem = document.createElement('menuitem');
+ menuitem.setAttribute('label', this.getProfileLabel(i)+'...');
+ menuitem.setAttribute('data-index', i);
+ menuitem.addEventListener("command", function () {
+ var i = +this.getAttribute('data-index');
+ autofillForms.authenticateAndShowManualFillDialog(i);
+ });
+ menupopup.appendChild(menuitem);
+ } else {
+ var menu = document.createElement('menu');
+ menu.setAttribute('label', this.getProfileLabel(i));
+
+ // Add a menupopup for each profile:
+ var profilemenupopup = document.createElement('menupopup');
+ profilemenupopup.setAttribute('data-index', i);
+ profilemenupopup.addEventListener("popupshowing", function (event) {
+ if(event.target == this) {
+ var i = +this.getAttribute('data-index');
+ autofillForms.initManualFillProfileContextMenu(event, i);
+ }
+ });
+ menu.appendChild(profilemenupopup);
+ menupopup.appendChild(menu);
+ }
+ }
+ },
+
+ initManualFillProfileContextMenu: function(event, profileID) {
+ var menupopup = event.target;
+ // Remove all children nodes:
+ while(menupopup.hasChildNodes()) {
+ menupopup.removeChild(menupopup.firstChild);
+ }
+ var menuPopupMore;
+ // Add the profile field rules as menu items:
+ for(var i=0; i < this.getFieldRules(profileID).length; i++) {
+ var menuitem = document.createElement('menuitem');
+ menuitem.setAttribute('label', this.getFieldRules(profileID)[i]['fieldRuleName']);
+ menuitem.setAttribute('data-index', i);
+ menuitem.setAttribute('data-profileID', profileID);
+ menuitem.addEventListener("command", function () {
+ var i = +this.getAttribute('data-index');
+ var profileID = +this.getAttribute('data-profileID');
+ autofillForms.fillTargetFormField(profileID, i);
+ });
+ if(this.getFieldRules(profileID)[i]['fieldRuleEnabled']) {
+ menupopup.appendChild(menuitem);
+ } else {
+ // Add disabled items to a "More..." menu:
+ if(!menuPopupMore) {
+ menuPopupMore = document.createElement('menupopup');
+ }
+ menuPopupMore.appendChild(menuitem);
+ }
+ }
+ if(menuPopupMore) {
+ if(!menupopup.hasChildNodes()) {
+ // All field rules of this profile are disabled, so no need to create a submenu:
+ while(menuPopupMore.hasChildNodes()) {
+ // appendChild removes the node from the current parent node
+ // and adds it to the new parent node:
+ menupopup.appendChild(menuPopupMore.firstChild);
+ }
+ } else {
+ // Append the "More..." menu:
+ var menuMore = document.createElement('menu');
+ menuMore.setAttribute('label', this.getStringBundle().getString('contextMenuMore'));
+ menuMore.appendChild(menuPopupMore);
+ menupopup.appendChild(menuMore);
+ }
+ }
+ // Reset object to release used memory:
+ this.fieldRules = null;
+ },
+
+ authenticateAndShowManualFillDialog: function(profileID) {
+ try {
+ Components.classes['@mozilla.org/security/pk11tokendb;1']
+ .getService(Components.interfaces.nsIPK11TokenDB).getInternalKeyToken().login(false);
+
+ var prompts = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
+ .getService(Components.interfaces.nsIPromptService);
+ // The selection and the subselection lists:
+ var list = new Array();
+ var listMore;
+ // Hashs mapping the list positions to the original indices:
+ var listIndexMapping = new Object();;
+ var listMoreIndexMapping;
+ for(var i=0; i < this.getFieldRules(profileID).length; i++) {
+ if(this.getFieldRules(profileID)[i]['fieldRuleEnabled']) {
+ list.push(this.getFieldRules(profileID)[i]['fieldRuleName']);
+ listIndexMapping[list.length-1] = i;
+ } else {
+ // Add disabled items to a "More..." list:
+ if(!listMore) {
+ listMore = new Array();
+ listMoreIndexMapping = new Object();
+ }
+ listMore.push(this.getFieldRules(profileID)[i]['fieldRuleName']);
+ listMoreIndexMapping[listMore.length-1] = i;
+ }
+ }
+ if(listMore) {
+ // If all field rules of this profile are disabled, there is no need of a sublist:
+ if(!list.length) {
+ list = listMore;
+ listIndexMapping = listMoreIndexMapping;
+ listMore = null;
+ listMoreIndexMapping = null;
+ } else {
+ list.push(this.getStringBundle().getString('contextMenuMore'));
+ }
+ }
+ var selected = {};
+ var ok = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
+ .getService(Components.interfaces.nsIPromptService)
+ .select(
+ window,
+ null, // Window title - defaults to locale version of "Select"
+ null, // Prompt text - defaults to empty string
+ list.length,
+ list,
+ selected
+ );
+ if(ok) {
+ // If "More..." is selected, show the disabled items as selection list:
+ if(listMore && selected.value == list.length-1) {
+ selected = {};
+ ok = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
+ .getService(Components.interfaces.nsIPromptService)
+ .select(
+ window,
+ null, // Window title - defaults to locale version of "Select"
+ null, // Prompt text - defaults to empty string
+ listMore.length,
+ listMore,
+ selected
+ );
+ if(ok) {
+ this.fillTargetFormField(
+ profileID,
+ listMoreIndexMapping[selected.value]
+ );
+ }
+ } else {
+ this.fillTargetFormField(
+ profileID,
+ listIndexMapping[selected.value]
+ );
+ }
+ }
+ } catch(e) {
+ // Authentication with master security device failed
+ }
+ // Reset object to release used memory:
+ this.fieldRules = null;
+ },
+
+ fillTargetFormField: function(profileID, ruleID) {
+ if(this.targetFormField) {
+ var value = this.getFieldRules(profileID)[ruleID]['fieldRuleValue'];
+ // Replace dynamic tags if enabled:
+ if(this.autofillFormsPrefs.getBoolPref('enableDynamicTags')) {
+ value = this.replaceDynamicTags(value);
+ }
+ try {
+ // Try to use selection information:
+ var newCursorPos = this.targetFormField.selectionStart + value.length;
+ this.targetFormField.value = this.targetFormField.value.substr(0, this.targetFormField.selectionStart)
+ + value
+ + this.targetFormField.value.substr(this.targetFormField.selectionEnd);
+ // Adjust the cursor position:
+ this.targetFormField.selectionEnd = newCursorPos;
+ this.targetFormField.selectionStart = newCursorPos;
+ } catch(e) {
+ // This input field does not support selections - just try to set the value:
+ try {
+ this.targetFormField.value = value;
+ } catch(e) {
+ // Catch errors if value could not be set on the form field
+ }
+ }
+ // Reset objects to release used memory:
+ this.fieldRules = null;
+ this.dynamicTags = null;
+ this.dynamicTagCodes = null;
+ }
+ },
+
+ tooltip: function(event) {
+ if (!document.tooltipNode) {
+ return;
+ }
+ // Get the tooltip node:
+ var tooltip = document.getElementById('autofillFormsTooltip');
+ if(tooltip) {
+ // Add the associated tooltip content for each toolbar button menu item, toolbar button and statusbar icon:
+ if(document.tooltipNode.id == 'autofillFormsButton' || document.tooltipNode.id == 'autofillFormsPanelIcon') {
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Always retrieve the profile labels from file if useConfigDirectory is enabled:
+ this.profileLabels = null;
+ this.tooltipCurrentProfile = null;
+ }
+ if(!this.tooltipCurrentProfile || !this.tooltipGrid) {
+ // Remove all children nodes:
+ while(tooltip.hasChildNodes()) {
+ tooltip.removeChild(tooltip.firstChild);
+ }
+ // Add the current profile label:
+ tooltip.appendChild(this.getTooltipCurrentProfile());
+ // Add the tooltip grid with the command labels, mouse buttons and keyboard shortcuts:
+ tooltip.appendChild(this.getTooltipGrid());
+ }
+ } else {
+ // Don't show tooltips for the toolbar button menu items:
+ event.preventDefault();
+ }
+ }
+ },
+
+ getTooltipCurrentProfile: function() {
+ if(!this.tooltipCurrentProfile) {
+ var hbox = document.createElement('hbox');
+ hbox.setAttribute(
+ 'id',
+ 'autofillFormsTooltipCurrentProfile'
+ );
+ var label = document.createElement('label');
+ label.setAttribute(
+ 'value',
+ this.getStringBundle().getString('currentProfileLabel')
+ );
+ label.setAttribute(
+ 'id',
+ 'autofillFormsTooltipCurrentProfileCaption'
+ );
+ hbox.appendChild(label);
+ label = label.cloneNode(false);
+ label.setAttribute(
+ 'value',
+ this.getProfileLabel(this.getProfileIndex())
+ );
+ label.setAttribute(
+ 'id',
+ 'autofillFormsTooltipCurrentProfileLabel'
+ );
+ hbox.appendChild(label);
+ this.tooltipCurrentProfile = hbox;
+ }
+ return this.tooltipCurrentProfile;
+ },
+
+ getTooltipGrid: function() {
+ if(!this.tooltipGrid) {
+ var commands = new Array();
+ for(var property in this.shortcut) {
+ commands.push(new Array(
+ this.getStringBundle().getString('tooltip'+property.replace(/shortcut/,'')),
+ this.getFormattedMouseButton(this.getMouseButton('mouseS'+property.substr(1))),
+ this.getFormattedShortcut(this.getShortcut(property))
+ ));
+ }
+ var grid = document.createElement('grid');
+ grid.setAttribute(
+ 'id',
+ 'autofillFormsTooltipGrid'
+ );
+ var columns = document.createElement('columns');
+ var column = document.createElement('column');
+ var rows = document.createElement('rows');
+ var row = document.createElement('row');
+ var label = document.createElement('label');
+ columns.appendChild(column);
+ columns.appendChild(column.cloneNode(false));
+ columns.appendChild(column.cloneNode(false));
+ grid.appendChild(columns);
+ // Create the column headers:
+ label.setAttribute(
+ 'class',
+ 'autofillFormsTooltipGridHeader'
+ );
+ label.setAttribute(
+ 'value',
+ this.getStringBundle().getString('command')
+ );
+ row.appendChild(label);
+ label = label.cloneNode(false);
+ label.setAttribute(
+ 'value',
+ this.getStringBundle().getString('mousebutton')
+ );
+ row.appendChild(label);
+ label = label.cloneNode(false);
+ label.setAttribute(
+ 'value',
+ this.getStringBundle().getString('keyboardShortcut')
+ );
+ row.appendChild(label);
+ rows.appendChild(row);
+ // Create a row for each command:
+ for(var i=0; i<commands.length; i++) {
+ row = row.cloneNode(false);
+ // Skip if neither mouseButton nor keyboard shortcut is set:
+ if(!commands[i][1] && !commands[i][2]) {
+ continue;
+ }
+ for(var j=0; j<commands[i].length; j++) {
+ label = label.cloneNode(false);
+ label.setAttribute(
+ 'value',
+ commands[i][j]
+ );
+ if(j == 0) {
+ label.setAttribute(
+ 'class',
+ 'autofillFormsTooltipGridCommand'
+ );
+ } else if(j == 1) {
+ label.setAttribute(
+ 'class',
+ 'autofillFormsTooltipGridMouseButton'
+ );
+ } else {
+ label.setAttribute(
+ 'class',
+ 'autofillFormsTooltipGridKeyboardShortcut'
+ );
+ }
+ row.appendChild(label);
+ }
+ rows.appendChild(row);
+ }
+ grid.appendChild(rows);
+ this.tooltipGrid = grid;
+ }
+ return this.tooltipGrid;
+ },
+
+ resetAllProfiles: function() {
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ // Confirmation dialog:
+ if(!this.getPrompts().confirm(
+ null,
+ this.getStringBundle().getString('resetAllProfilesTitle'),
+ this.getStringBundle().getString('resetAllProfilesText')
+ )
+ ) {
+ return;
+ }
+ }
+
+ // Reset the user preferences:
+ if(this.autofillFormsPrefs.prefHasUserValue('useConfigDirectory')) {
+ this.autofillFormsPrefs.clearUserPref('useConfigDirectory');
+ }
+ if(this.autofillFormsPrefs.prefHasUserValue('storeEncrypted')) {
+ this.autofillFormsPrefs.clearUserPref('storeEncrypted');
+ }
+ if(this.autofillFormsPrefs.prefHasUserValue('profileIndex')) {
+ this.autofillFormsPrefs.clearUserPref('profileIndex');
+ }
+ if(this.autofillFormsPrefs.prefHasUserValue('profileLabels')) {
+ this.autofillFormsPrefs.clearUserPref('profileLabels');
+ }
+ if(this.autofillFormsPrefs.prefHasUserValue('profileSiteRules')) {
+ this.autofillFormsPrefs.clearUserPref('profileSiteRules');
+ }
+ if(this.autofillFormsPrefs.prefHasUserValue('fieldRules')) {
+ this.autofillFormsPrefs.clearUserPref('fieldRules');
+ }
+
+ this.profileIndex = null;
+ this.profileLabels = null;
+ this.profileSiteRules = null;
+ this.fieldRules = null;
+
+ // Re-init the profiles lists:
+ this.initProfilesLists();
+ // Re-init the fieldRules tree:
+ this.initTree();
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+
+ if(this.tree && this.selection) {
+ try {
+ // Clear out the fieldRules tree selections
+ this.selection.select(-1);
+ } catch(e) {
+ this.log(e);
+ }
+ }
+ },
+
+ initProfilesLists: function(event) {
+ // The profiles tree:
+ this.initProfilesTree();
+
+ // Editable profiles menu list:
+ var profilesMenuList = document.getElementById('profilesMenuList');
+ if(profilesMenuList) {
+ profilesMenuList.removeAllItems();
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ profilesMenuList.appendItem(
+ this.getProfileLabel(i)
+ );
+ }
+ profilesMenuList.selectedIndex = this.getProfileIndex();
+ }
+ // Simple interface profiles menu list:
+ var simpleInterfaceProfileMenuList = document.getElementById('simpleInterfaceProfileMenuList');
+ if(simpleInterfaceProfileMenuList) {
+ simpleInterfaceProfileMenuList.removeAllItems();
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ simpleInterfaceProfileMenuList.appendItem(
+ this.getProfileLabel(i)
+ );
+ }
+ simpleInterfaceProfileMenuList.selectedIndex = this.getProfileIndex();
+ }
+ // Global profile selection:
+ var globalProfileMenuList = document.getElementById('globalProfileMenuList');
+ if(globalProfileMenuList) {
+ globalProfileMenuList.removeAllItems();
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ globalProfileMenuList.appendItem(
+ this.getProfileLabel(i)
+ );
+ }
+ globalProfileMenuList.selectedIndex = this.getGlobalProfileIndex();
+ }
+ // Form fields context menu selection:
+ var contextMenuProfileMenuList = document.getElementById('contextMenuProfileMenuList');
+ if(contextMenuProfileMenuList) {
+ // The first 3 items are "All profiles", "Active profile" and a menuseparator:
+ while(contextMenuProfileMenuList.firstChild.childNodes[3]) {
+ // The more convenient getItemAtIndex does not seem to work with Firefox versions < 3,
+ // so we use DOM methods on the menupopup child node of the menu node instead:
+ contextMenuProfileMenuList.firstChild.removeChild(
+ contextMenuProfileMenuList.firstChild.childNodes[3]
+ );
+ }
+ for(var i=0; i < this.getProfileLabels().length; i++) {
+ contextMenuProfileMenuList.appendItem(
+ this.getProfileLabel(i)
+ );
+ }
+ contextMenuProfileMenuList.selectedIndex
+ = this.getFormFieldsContextMenuProfileIndex()+3;
+ }
+
+ // The profile site rule textbox:
+ this.initProfileSiteRuleTextBox();
+ },
+
+ updateProfilesLists: function() {
+ // The more convenient getItemAtIndex does not seem to work with Firefox versions < 3,
+ // so we use DOM methods on the menupopup child node of the menu nodes instead:
+
+ // Editable profiles menu list:
+ var profilesMenuList = document.getElementById('profilesMenuList');
+ if(profilesMenuList) {
+ profilesMenuList
+ .firstChild.childNodes[this.getProfileIndex()].label
+ = this.getProfileLabel(this.getProfileIndex());
+ }
+ // Simple interface profiles menu list:
+ var simpleInterfaceProfileMenuList = document.getElementById('simpleInterfaceProfileMenuList');
+ if(simpleInterfaceProfileMenuList) {
+ simpleInterfaceProfileMenuList
+ .firstChild.childNodes[this.getProfileIndex()].label
+ = this.getProfileLabel(this.getProfileIndex());
+ }
+ // Global profile selection:
+ var globalProfileMenuList = document.getElementById('globalProfileMenuList');
+ if(globalProfileMenuList) {
+ globalProfileMenuList
+ .firstChild.childNodes[this.getProfileIndex()].label
+ = this.getProfileLabel(this.getProfileIndex());
+ }
+ // Form fields context menu selection:
+ var contextMenuProfileMenuList = document.getElementById('contextMenuProfileMenuList');
+ if(contextMenuProfileMenuList) {
+ // The first 3 items are "All profiles", "Active profile" and a menuseparator:
+ contextMenuProfileMenuList
+ .firstChild.childNodes[this.getProfileIndex()+3].label
+ = this.getProfileLabel(this.getProfileIndex());
+ }
+ // The profiles tree:
+ if(this.profilesTreeBox) {
+ this.profilesTreeBox.invalidateRow(this.getProfileIndex());
+ }
+ },
+
+ getProfileIndex: function() {
+ if(this.profileIndex == null)
+ this.profileIndex = this.autofillFormsPrefs.getIntPref('profileIndex');
+ return this.profileIndex;
+ },
+
+ setProfileIndex: function(index) {
+ if(this.profileIndex == index)
+ return;
+
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ this.autofillFormsPrefs.setIntPref('profileIndex',parseInt(index));
+ // Update the tree view if present:
+ if(this.tree) {
+ // The settings page doesn't observe preferences changes - set the profileIndex manually:
+ this.profileIndex = index;
+ // Re-init the tree:
+ this.initTree();
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+ }
+ // Update the profiles tree selection if present and not already updated:
+ if(this.profilesTree && this.profilesSelection.currentIndex != index) {
+ // Select the current profile:
+ this.profilesSelection.select(index);
+
+ // Ensure row is visible (scrolls if not):
+ this.profilesTreeBox.ensureRowIsVisible(index);
+ }
+ // Editable profiles menu list:
+ var profilesMenuList = document.getElementById('profilesMenuList');
+ if(profilesMenuList) {
+ profilesMenuList.selectedIndex = this.getProfileIndex();
+ }
+ // Simple interface profiles menu list:
+ var simpleInterfaceProfileMenuList = document.getElementById('simpleInterfaceProfileMenuList');
+ if(simpleInterfaceProfileMenuList) {
+ simpleInterfaceProfileMenuList.selectedIndex = this.getProfileIndex();
+ }
+
+ // The profile site rule textbox:
+ this.initProfileSiteRuleTextBox();
+ },
+
+ getGlobalProfileIndex: function() {
+ if(this.globalProfileIndex == null) {
+ this.globalProfileIndex = this.autofillFormsPrefs.getIntPref('globalProfileIndex');
+ }
+ return this.globalProfileIndex;
+ },
+
+ setGlobalProfileIndex: function(index) {
+ if(this.globalProfileIndex == index) {
+ return;
+ }
+ this.autofillFormsPrefs.setIntPref('globalProfileIndex',parseInt(index));
+ // The settings page doesn't observe preferences changes - set the profileIndex manually:
+ this.globalProfileIndex = index;
+ },
+
+ getFormFieldsContextMenuProfileIndex: function() {
+ if(this.formFieldsContextMenuProfileIndex == null) {
+ this.formFieldsContextMenuProfileIndex
+ = this.autofillFormsPrefs.getIntPref('formFieldsContextMenuProfileIndex');
+ }
+ return this.formFieldsContextMenuProfileIndex;
+ },
+
+ setFormFieldsContextMenuProfileIndex: function(index) {
+ if(this.formFieldsContextMenuProfileIndex == index) {
+ return;
+ }
+ this.autofillFormsPrefs.setIntPref('formFieldsContextMenuProfileIndex',parseInt(index));
+ // The settings page doesn't observe preferences changes - set the profileIndex manually:
+ this.formFieldsContextMenuProfileIndex = index;
+ },
+
+ getProfileLabelsFile: function() {
+ var file = this.getConfigDirectory();
+ file.append('profileLabels.txt');
+ if(!file.exists()) {
+ file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
+ }
+ return file;
+ },
+
+ exportProfileLabelsToConfigDirectory: function() {
+ var prefString;
+ // Get the profileLabels string from the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('profileLabels',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ if(prefString) {
+ this.setFileContent(this.getProfileLabelsFile(), prefString);
+ }
+ },
+
+ importProfileLabelsFromConfigDirectory: function() {
+ var prefString;
+ prefString = this.getFileContent(this.getProfileLabelsFile());
+ if(prefString) {
+ // Store the profileLabels as unicode string in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'profileLabels',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getProfileLabels: function() {
+ if(this.profileLabels == null) {
+ var prefString;
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Get the profileLabels string from the profileLabels file in the configDirectory:
+ prefString = this.getFileContent(this.getProfileLabelsFile());
+ }
+ if(!prefString) {
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('profileLabels',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ }
+ // The profile labels are stored as a string with tabs as separators:
+ this.profileLabels = prefString.split('\t');
+ }
+ return this.profileLabels;
+ },
+
+ setProfileLabels: function(profileLabels) {
+ // Save the profile labels separated by tabs:
+ var prefString = profileLabels.join('\t');
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ this.setFileContent(this.getProfileLabelsFile(), prefString);
+ } else {
+ this.autofillFormsPrefs.setComplexValue(
+ 'profileLabels',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getProfileLabel: function(index) {
+ while(this.getProfileLabels().length <= index) {
+ this.getProfileLabels().push(this.getUniqueProfileLabel());
+ }
+ return this.getProfileLabels()[index];
+ },
+
+ setProfileLabel: function(index, label) {
+ while(this.getProfileLabels().length <= index) {
+ this.getProfileLabels().push(this.getUniqueProfileLabel());
+ }
+ this.getProfileLabels()[index] = label;
+ // Save the profileLabels list in the preferences:
+ this.setProfileLabels(this.getProfileLabels());
+ },
+
+ getUniqueProfileLabel: function(profileLabel) {
+ if(!profileLabel) {
+ profileLabel = 'Profile';
+ }
+
+ // Make sure the profile label is unique:
+ if(!this.inArray(this.getProfileLabels(), profileLabel)) {
+ return profileLabel;
+ }
+ var i = profileLabel.lastIndexOf(' ');
+ var n = parseInt(profileLabel.substr(i+2));
+ if(isNaN(n)) {
+ return this.getUniqueProfileLabel(profileLabel+' (2)');
+ }
+ n++;
+ profileLabel = profileLabel.substr(0, i)+' ('+n+')';
+ return this.getUniqueProfileLabel(profileLabel);
+ },
+
+ changeProfileLabel: function(newProfileLabel) {
+ var profilesMenuList = document.getElementById('profilesMenuList');
+ if(profilesMenuList) {
+ // Make sure the new profile label is safe and unique:
+ newProfileLabel = this.getUniqueProfileLabel(this.makeSafe(newProfileLabel));
+ // Update the label of the selected profile:
+ this.setProfileLabel(this.getProfileIndex(), newProfileLabel);
+ // Update the profiles textbox contents:
+ profilesMenuList.inputField.value = newProfileLabel;
+ document.getElementById('profileLabelTextBox').value = newProfileLabel;
+ // Update the profiles lists:
+ this.updateProfilesLists();
+ }
+ },
+
+ initProfileSiteRuleTextBox: function(event) {
+ var profileSiteRuleTextBox = document.getElementById('profileSiteRuleTextBox');
+ if(profileSiteRuleTextBox) {
+ profileSiteRuleTextBox.value = this.getProfileSiteRule(this.getProfileIndex());
+ }
+ },
+
+ changeProfileSiteRule: function(siteRule) {
+ var profileSiteRuleTextBox = document.getElementById('profileSiteRuleTextBox');
+ if(profileSiteRuleTextBox) {
+ // Check the regular expression before updating the profile site rules:
+ try {
+ siteRule = this.getRegExpStr(
+ this.makeSafe(siteRule)
+ );
+ profileSiteRuleTextBox.value = siteRule;
+ document.getElementById('profileSiteRuleTextBox2').value = siteRule;
+
+ var newProfileSiteRules = this.getProfileSiteRules();
+ newProfileSiteRules[this.getProfileIndex()] = siteRule;
+ this.setProfileSiteRules(newProfileSiteRules);
+
+ // Update the profiles tree:
+ if(this.profilesTreeBox) {
+ this.profilesTreeBox.invalidateRow(this.getProfileIndex());
+ }
+ } catch(e) {
+ this.invalidRegExpAlert(e);
+ }
+ }
+ },
+
+ getProfileSiteRulesFile: function() {
+ var file = this.getConfigDirectory();
+ file.append('profileSiteRules.txt');
+ if(!file.exists()) {
+ file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
+ }
+ return file;
+ },
+
+ exportProfileSiteRulesToConfigDirectory: function() {
+ var prefString;
+ // Get the profileSiteRules string from the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('profileSiteRules',Components.interfaces.nsISupportsString)
+ .data;
+ if(prefString) {
+ this.setFileContent(this.getProfileSiteRulesFile(), prefString);
+ }
+ },
+
+ importProfileSiteRulesFromConfigDirectory: function() {
+ var prefString;
+ prefString = this.getFileContent(this.getProfileSiteRulesFile());
+ if(prefString) {
+ // Store the profileSiteRules as unicode string in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'profileSiteRules',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getProfileSiteRules: function() {
+ if(this.profileSiteRules == null) {
+ var prefString;
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Get the profileSiteRules string from the profileSiteRules file in the configDirectory:
+ prefString = this.getFileContent(this.getProfileSiteRulesFile());
+ }
+ if(!prefString) {
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('profileSiteRules',Components.interfaces.nsISupportsString)
+ .data;
+ }
+ // The profile SiteRules are stored as a string with tabs as separators:
+ this.profileSiteRules = prefString.split('\t');
+ }
+ return this.profileSiteRules;
+ },
+
+ setProfileSiteRules: function(profileSiteRules) {
+ // Save the profile SiteRules separated by tabs:
+ var prefString = profileSiteRules.join('\t');
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ this.setFileContent(this.getProfileSiteRulesFile(), prefString);
+ } else {
+ this.autofillFormsPrefs.setComplexValue(
+ 'profileSiteRules',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getProfileSiteRule: function(index) {
+ while(this.getProfileSiteRules().length <= index) {
+ this.getProfileSiteRules().push('(?:)');
+ }
+ return this.getProfileSiteRules()[index];
+ },
+
+ setProfileSiteRule: function(index, siteRule) {
+ while(this.getProfileSiteRules().length <= index) {
+ this.getProfileSiteRules().push('(?:)');
+ }
+ this.getProfileSiteRules()[index] = siteRule;
+ // Save the profileSiteRules in the preferences:
+ this.setProfileSiteRules(this.getProfileSiteRules());
+ },
+
+ addFormAsProfile: function(event) {
+ if(this.targetFormField && this.targetFormField.form) {
+ var elements = this.targetFormField.form.elements;
+ var doc = this.targetFormField.form.ownerDocument;
+
+ var newProfile = new Array();
+
+ // Go through the form elements:
+ for(var i=0; i<elements.length; i++) {
+ // Only use valid form fields:
+ if(this.isValidFormField(elements[i])) {
+ var value;
+ var overwrite = true;
+
+ // Create the fieldRule (from name, label or id):
+ var fieldRule = this.getFieldRuleForElement(elements[i]);
+
+ switch(elements[i].type) {
+ case 'checkbox':
+ // Add a rule to uncheck the checkbox if it is unchecked:
+ if(!elements[i].checked) {
+ overwrite = false;
+ }
+ value = this.getRegExpStrForValue(elements[i].value);
+ break;
+ case 'radio':
+ // Only add checked radio buttons:
+ if(!elements[i].checked) {
+ continue;
+ }
+ value = this.getRegExpStrForValue(elements[i].value);
+ break;
+ case 'select-one':
+ value = this.getRegExpStrForValue(elements[i].value);
+ break;
+ case 'select-multiple':
+ var fieldRuleLabel = this.makeSafe(this.getFieldRuleNameForElement(elements[i]));
+ // Add all options as fieldRules, set "overwrite" to true if selected:
+ for(var j = 0; j < elements[i].options.length; j++) {
+ newProfile.push(
+ this.createFieldRule(
+ fieldRuleLabel+' ('+j+')',
+ this.getRegExpStrForValue(elements[i].options[j].value),
+ fieldRule,
+ '(?:)',
+ elements[i].options[j].selected,
+ true
+ )
+ );
+ }
+ continue;
+ default:
+ value = this.makeSafe(this.replaceControlCharacters(elements[i].value));
+ break;
+ }
+
+ // Add the current element as new rule to the profile list:
+ newProfile.push(
+ this.createFieldRule(
+ this.makeSafe(this.getFieldRuleNameForElement(elements[i])),
+ value,
+ fieldRule,
+ '(?:)',
+ overwrite,
+ true
+ )
+ );
+ }
+ }
+
+ // Initialize the fieldRules:
+ this.getFieldRules();
+
+ // Add the new profile to the fieldRules:
+ this.fieldRules.push(newProfile);
+ // Save the profiles in the preferences:
+ this.setFieldRules();
+
+ // Add a label for default empty profile:
+ if(this.getProfileLabels().length == 0) {
+ this.getProfileLabels().push(this.getUniqueProfileLabel());
+ }
+ // Use the documents hostname as profile label and add it to the profile labels list:
+ this.getProfileLabels().push(this.getUniqueProfileLabel(this.makeSafe(doc.location.host)));
+ // Save the profileLabels list in the preferences:
+ this.setProfileLabels(this.getProfileLabels());
+
+ // Use the protocol and domain of the web form as profile siteRule:
+ this.getProfileSiteRules().push(this.getSiteRuleForURL(doc.location.protocol+'//'+doc.location.host));
+ // Save the profileSiteRules in the preferences:
+ this.setProfileSiteRules(this.getProfileSiteRules());
+
+ // Save the the new profile index as selected profileIndex:
+ this.setProfileIndex(this.getProfileLabels().length-1);
+
+ // Reset the target form field:
+ this.targetFormField = null;
+
+ // Create parameters for the settings page:
+ var params = new Object();
+ params.newProfileFromForm = true;
+
+ // Open up the settings page:
+ this.showDialog('chrome://autofillForms/content/autofillFormsOptions.xul', params);
+ }
+ },
+
+ addProfile: function(newProfileLabel) {
+ // Duplicate the selected profile (do a deep copy):
+ this.fieldRules.push(
+ this.copyFieldRules(this.getFieldRules())
+ );
+ // Save the profiles in the preferences:
+ this.setFieldRules();
+ // Add profile label for default empty profile:
+ if(this.getProfileLabels().length == 0) {
+ this.getProfileLabels().push(this.getUniqueProfileLabel());
+ }
+ // Add the (unique) newProfileLabel to the profileLabels list:
+ this.getProfileLabels().push(this.getUniqueProfileLabel(this.makeSafe(newProfileLabel)));
+ // Save the profileLabels list in the preferences:
+ this.setProfileLabels(this.getProfileLabels());
+ // Add a new empty profileSiteRule:
+ this.getProfileSiteRules().push('(?:)');
+ // Save the profileSiteRules in the preferences:
+ this.setProfileSiteRules(this.getProfileSiteRules());
+ // Save the the new profile index as selected profileIndex:
+ this.setProfileIndex(this.getProfileLabels().length-1);
+ // Update the profiles lists:
+ this.initProfilesLists();
+ // Re-init the fieldRules tree:
+ this.initTree();
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+ },
+
+ removeProfile: function(event) {
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ // Confirmation dialog:
+ if(!this.getPrompts().confirm(
+ null,
+ this.getStringBundle().getString('removeProfileTitle'),
+ this.getStringBundle().getString('removeProfileText')
+ )
+ ) {
+ return;
+ }
+ }
+
+ // Remove the selected profile from the list:
+ this.fieldRules.splice(this.getProfileIndex(),1);
+ // Save the profiles in the preferences:
+ this.setFieldRules();
+ // Remove the selected profile from the profileLabels list:
+ this.getProfileLabels().splice(this.getProfileIndex(),1);
+ // Save the profileLabels list in the preferences:
+ this.setProfileLabels(this.getProfileLabels());
+ // Remove the selected profile's siteRule:
+ this.getProfileSiteRules().splice(this.getProfileIndex(),1);
+ // Save the profileSiteRules in the preferences:
+ this.setProfileSiteRules(this.getProfileSiteRules());
+ // Adjust the profileIndex if the last profile on the list has been deleted:
+ if(this.getProfileIndex()+1 > this.fieldRules.length) {
+ var newIndex = this.fieldRules.length>0 ? this.fieldRules.length-1 : 0;
+ this.setProfileIndex(newIndex);
+ }
+ // Update the profiles lists:
+ this.initProfilesLists();
+ // Re-init the tree:
+ this.initTree();
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+ },
+
+ createFieldRule: function(name,value,fieldRule,siteRule,overwrite,enabled) {
+ var rule = new Object();
+ rule['fieldRuleName'] = name;
+ rule['fieldRuleValue'] = value;
+ rule['fieldRuleFieldRule'] = fieldRule;
+ rule['fieldRuleSiteRule'] = siteRule;
+ rule['fieldRuleOverwrite'] = overwrite;
+ rule['fieldRuleEnabled'] = enabled;
+ return rule;
+ },
+
+ getRegExpPasswordLabel: function() {
+ if(!arguments.callee.regExpPass) {
+ arguments.callee.regExpPass = new RegExp(
+ this.autofillFormsPrefs
+ .getComplexValue('regExpPasswordLabel',Components.interfaces.nsIPrefLocalizedString)
+ .data,
+ 'i');
+ }
+ return arguments.callee.regExpPass;
+ },
+
+ initTree: function() {
+ // Get the tree:
+ this.tree = document.getElementById('fieldRulesTree');
+
+ if(this.tree) {
+
+ // Implement the TreeView interface:
+ this.treeView = {
+ rowCount: 0,
+ setTree: function(tree){},
+ getImageSrc: function(row,column) {},
+ getProgressMode: function(row,column) {},
+ getCellValue: function(row,column) {
+ var rowObj = this.parent.getFieldRules()[row];
+ if(rowObj) {
+ return rowObj[column.id];
+ }
+ },
+ getCellText: function(row,column){
+ var rowObj = this.parent.getFieldRules()[row];
+ if(rowObj) {
+ if(column.id=='fieldRuleValue' &&
+ this.parent.getRegExpPasswordLabel().test(rowObj['fieldRuleName'])) {
+ // Show passwords as asterisks:
+ return rowObj[column.id].replace(/./g, '*');
+ } else {
+ return rowObj[column.id];
+ }
+ }
+ return '';
+ },
+ isEditable: function(row,column){
+ // Only checkbox columns are editable:
+ if(column.id=='fieldRuleOverwrite' || column.id=='fieldRuleEnabled')
+ return true;
+ else
+ return false;
+ },
+ setCellValue: function(row,column,value){
+ var rowObj = this.parent.getFieldRules()[row];
+ if(rowObj) {
+ rowObj[column.id] = value;
+ // Notify the tree:
+ this.parent.treeBox.invalidateRow(row);
+ // Update the preferences:
+ this.parent.setFieldRules();
+ // Update the simple interface (add/remove enabled/disabled rules):
+ if(column.id=='fieldRuleEnabled') {
+ if(value == 'true') {
+ this.parent.addSimpleInterfaceRow(row);
+ } else {
+ this.parent.removeSimpleInterfaceRow(row);
+ }
+ }
+ }
+ },
+ isSeparator: function(index) {return false;},
+ isSorted: function() {return false;},
+ isContainer: function(index) {return false;},
+ cycleHeader: function(column) {},
+ getRowProperties: function(row,prop){},
+ getColumnProperties: function(column,prop){},
+ getCellProperties: function(row,column,prop){},
+ getParentIndex: function(index) {return -1}
+ };
+ // Set the autofillForms object as parent:
+ this.treeView.parent = this;
+
+ // Set the tree length using the fieldRules list length:
+ this.treeView.rowCount = this.getFieldRules().length;
+
+ // Assign the treeview:
+ this.tree.view = this.treeView;
+
+ // The TreeSelection object:
+ this.selection = this.tree.view.selection;
+
+ // The TreeBox object:
+ this.treeBox = this.tree.treeBoxObject;
+ }
+ },
+
+ sortFieldRules: function(event) {
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ // Confirmation dialog:
+ if(!this.getPrompts().confirm(
+ null,
+ this.getStringBundle().getString('sortFieldRulesTitle'),
+ this.getStringBundle().getString('sortFieldRulesText')
+ )
+ ) {
+ return;
+ }
+ }
+
+ // Get the id of the column:
+ var id = event.target.id;
+
+ // Helper function to sort the fieldRules objects:
+ function customSort(a,b) {
+ // This enables comparison of boolean true and false:
+ var x = a[id].toString();
+ var y = b[id].toString();
+
+ if(x > y) return 1;
+ if(x < y) return -1;
+ return 0;
+ }
+
+ // Sort the form field rules using the helper function:
+ this.getFieldRules().sort(customSort);
+
+ // Change sort direction for next click:
+ if(this.ascending) {
+ this.ascending = false;
+ } else {
+ this.getFieldRules().reverse();
+ this.ascending = true;
+ }
+
+ // Notify the tree:
+ this.treeBox.invalidate();
+
+ // Clear out selections
+ this.selection.select(-1);
+
+ // Update the preferences:
+ this.setFieldRules();
+
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+ },
+
+ selectedFieldRule: function(event) {
+ if(this.selection.currentIndex == -1) {
+ // Disable buttons:
+ document.getElementById('buttonRemoveFieldRule').setAttribute('disabled', 'true');
+ document.getElementById('buttonMoveUpFieldRule').setAttribute('disabled', 'true');
+ document.getElementById('buttonMoveDownFieldRule').setAttribute('disabled', 'true');
+
+ this.lastSelectedIndex = null;
+ } else if(this.selection.count == 1) {
+ // The onchange event (as well as onblur, etc.) of the textboxes seems to be ignored if a new item is selected,
+ // so we try and apply the field rules of the last element (if changed):
+ if(this.lastSelectedIndex !== null) {
+ this.applyFieldRuleOnIndex(this.lastSelectedIndex);
+ }
+
+ // Update the textboxes with the selected fieldRule:
+ var index = this.selection.currentIndex;
+ document.getElementById('fieldRuleNameTextBox').value = this.getFieldRules()[index]['fieldRuleName'];
+ document.getElementById('fieldRuleValueTextBox').value = this.getFieldRules()[index]['fieldRuleValue'];
+ document.getElementById('fieldRuleFieldRuleTextBox').value = this.getFieldRules()[index]['fieldRuleFieldRule'];
+ document.getElementById('fieldRuleSiteRuleTextBox').value = this.getFieldRules()[index]['fieldRuleSiteRule'];
+
+ // Enable/Disable buttons:
+ document.getElementById('buttonRemoveFieldRule').setAttribute('disabled', 'false');
+ document.getElementById('buttonMoveUpFieldRule').setAttribute(
+ 'disabled',
+ (index == 0)
+ );
+ document.getElementById('buttonMoveDownFieldRule').setAttribute(
+ 'disabled',
+ (index == this.getFieldRules().length-1)
+ );
+
+ // Save the last selected index and reset it to null for any other action than just a single selection:
+ this.lastSelectedIndex = index;
+ } else if(this.selection.count > 1) {
+ // Enable/Disable buttons:
+ document.getElementById('buttonRemoveFieldRule').setAttribute('disabled', 'false');
+ document.getElementById('buttonMoveUpFieldRule').setAttribute('disabled', 'true');
+ document.getElementById('buttonMoveDownFieldRule').setAttribute('disabled', 'true');
+
+ this.lastSelectedIndex = null;
+ }
+ },
+
+ initProfilesTree: function() {
+ this.profilesTree = document.getElementById('profilesTree');
+ if(this.profilesTree) {
+
+ // Implement the profiles TreeView interface:
+ this.profilesTreeView = {
+ rowCount: 0,
+ setTree: function(tree){},
+ getImageSrc: function(row,column) {},
+ getProgressMode: function(row,column) {},
+ getCellValue: function(row,column) {
+ if(column.id=='profilesTreeColName') {
+ return this.parent.getProfileLabel(row);
+ } else {
+ return this.parent.getProfileSiteRule(row);
+ }
+ },
+ getCellText: function(row,column){
+ if(column.id=='profilesTreeColName') {
+ return this.parent.getProfileLabel(row);
+ } else {
+ return this.parent.getProfileSiteRule(row);
+ }
+ },
+ isEditable: function(row,column){return false;},
+ setCellValue: function(row,column,value){},
+ isSeparator: function(index) {return false;},
+ isSorted: function() {return false;},
+ isContainer: function(index) {return false;},
+ cycleHeader: function(column) {},
+ getRowProperties: function(row,prop){},
+ getColumnProperties: function(column,prop){},
+ getCellProperties: function(row,column,prop){},
+ getParentIndex: function(index) {return -1}
+ };
+ // Set the autofillForms object as parent:
+ this.profilesTreeView.parent = this;
+
+ // Seems like we need to reset these arrays to have a consistens UI:
+ this.profileLabels = null;
+ this.profileSiteRules = null;
+
+ // Set the tree length using the profiles labels list length:
+ this.profilesTreeView.rowCount = this.getProfileLabels().length;
+
+ // Assign the treeview:
+ this.profilesTree.view = this.profilesTreeView;
+
+ // The TreeSelection object:
+ this.profilesSelection = this.profilesTree.view.selection;
+
+ // The TreeBox object:
+ this.profilesTreeBox = this.profilesTree.treeBoxObject;
+
+ // Select the current profile:
+ this.profilesSelection.select(this.getProfileIndex());
+
+ // Ensure row is visible (scrolls if not):
+ this.profilesTreeBox.ensureRowIsVisible(this.getProfileIndex());
+ }
+ },
+
+ selectedProfile: function(event) {
+ var index = this.profilesSelection.currentIndex;
+ if(index != -1) {
+ this.setProfileIndex(index);
+
+ if(index > 0) {
+ document.getElementById('buttonMoveUpProfile').disabled = false;
+ } else {
+ document.getElementById('buttonMoveUpProfile').disabled = true;
+ }
+ if(index+1 < this.getProfileLabels().length) {
+ document.getElementById('buttonMoveDownProfile').disabled = false;
+ } else {
+ document.getElementById('buttonMoveDownProfile').disabled = true;
+ }
+
+ if(document.getElementById('profileLabelTextBox')) {
+ document.getElementById('profileLabelTextBox').value = this.getProfileLabel(this.getProfileIndex());
+ }
+ if(document.getElementById('profileSiteRuleTextBox2')) {
+ document.getElementById('profileSiteRuleTextBox2').value = this.getProfileSiteRule(this.getProfileIndex());
+ }
+ } else {
+ document.getElementById('buttonMoveUpProfile').disabled = true;
+ document.getElementById('buttonMoveDownProfile').disabled = true;
+ }
+ },
+
+ moveUpProfile: function(event) {
+ var tmpProfile = this.getFieldRules(this.getProfileIndex()-1);
+ this.fieldRules[this.getProfileIndex()-1] = this.getFieldRules(this.getProfileIndex());
+ this.fieldRules[this.getProfileIndex()] = tmpProfile;
+ this.setFieldRules();
+
+ var tmpProfileLabel = this.getProfileLabel(this.getProfileIndex()-1);
+ this.getProfileLabels()[this.getProfileIndex()-1] = this.getProfileLabel(this.getProfileIndex());
+ this.getProfileLabels()[this.getProfileIndex()] = tmpProfileLabel;
+ this.setProfileLabels(this.getProfileLabels());
+
+ var tmpProfileSiteRule = this.getProfileSiteRule(this.getProfileIndex()-1);
+ this.getProfileSiteRules()[this.getProfileIndex()-1] = this.getProfileSiteRule(this.getProfileIndex());
+ this.getProfileSiteRules()[this.getProfileIndex()] = tmpProfileSiteRule;
+ this.setProfileSiteRules(this.getProfileSiteRules());
+
+ this.setProfileIndex(this.getProfileIndex()-1);
+
+ this.initProfilesLists();
+ },
+
+ moveDownProfile: function(event) {
+ var tmpProfile = this.getFieldRules(this.getProfileIndex()+1);
+ this.fieldRules[this.getProfileIndex()+1] = this.getFieldRules(this.getProfileIndex());
+ this.fieldRules[this.getProfileIndex()] = tmpProfile;
+ this.setFieldRules();
+
+ var tmpProfileLabel = this.getProfileLabel(this.getProfileIndex()+1);
+ this.getProfileLabels()[this.getProfileIndex()+1] = this.getProfileLabel(this.getProfileIndex());
+ this.getProfileLabels()[this.getProfileIndex()] = tmpProfileLabel;
+ this.setProfileLabels(this.getProfileLabels());
+
+ var tmpProfileSiteRule = this.getProfileSiteRule(this.getProfileIndex()+1);
+ this.getProfileSiteRules()[this.getProfileIndex()+1] = this.getProfileSiteRule(this.getProfileIndex());
+ this.getProfileSiteRules()[this.getProfileIndex()] = tmpProfileSiteRule;
+ this.setProfileSiteRules(this.getProfileSiteRules());
+
+ this.setProfileIndex(this.getProfileIndex()+1);
+
+ this.initProfilesLists();
+ },
+
+ sortProfiles: function(event) {
+ var newSelectedIndex = this.getProfileIndex();
+ var fieldArray = this.getFieldsArray();
+ var oldIndex;
+
+ switch(event.target.id) {
+ case 'profilesTreeColName':
+ //Sort by Profile Label
+ fieldArray.sort(function (a, b) {
+ if (a[1] == b[1]) {
+ return 0;
+ }
+ if (a[1] < b[1]) {
+ return -1;
+ }
+ return 1;
+ });
+ if (!this.profilesAscending) {
+ fieldArray.reverse();
+ }
+ for(var i=0; i<this.getProfileLabels().length; i++) {
+ oldIndex = fieldArray[i][0];
+ if(oldIndex == this.getProfileIndex()) {
+ newSelectedIndex = i;
+ }
+ this.getProfileLabels()[i] = fieldArray[i][1];
+ this.getProfileSiteRules()[i] = fieldArray[i][2];
+ this.fieldRules[i] = fieldArray[i][3];
+ }
+ break;
+
+ case 'profilesTreeColSiteRule':
+ //Sort by Profile Site Rule
+ fieldArray.sort(function (a, b) {
+ if (a[2] == b[2]) {
+ return 0;
+ }
+ if (a[2] < b[2]) {
+ return -1;
+ }
+ return 1;
+ });
+ if (!this.profilesAscending) {
+ fieldArray.reverse();
+ }
+ for(var i=0; i<this.getProfileLabels().length; i++) {
+ oldIndex = fieldArray[i][0];
+ if(oldIndex == this.getProfileIndex()) {
+ newSelectedIndex = i;
+ }
+ this.getProfileLabels()[i] = fieldArray[i][1];
+ this.getProfileSiteRules()[i] = fieldArray[i][2];
+ this.fieldRules[i] = fieldArray[i][3];
+ }
+ break;
+ }
+ // Change sort direction for next click:
+ this.profilesAscending = !this.profilesAscending;
+
+ this.setFieldRules();
+ this.setProfileLabels(this.getProfileLabels());
+ this.setProfileSiteRules(this.getProfileSiteRules());
+
+ this.setProfileIndex(newSelectedIndex);
+
+ this.initProfilesLists();
+ },
+ getFieldsArray: function() {
+ // This creates an array of [i, ProfileLabel, ProfileSiteRule, fieldRules] rows
+ // we can then sort by rows[1] or rows[2] and store the row elements back in
+ // their respective arrays.
+ var row;
+ var fieldArray = new Array();
+ var tmpProfileLabels = this.getProfileLabels().slice(0);
+ var tmpProfileSiteRules = this.getProfileSiteRules().slice(0);
+
+ for(var i=0; i<this.getProfileSiteRules().length; i++) {
+ row = new Array();
+ row.push(i);
+ row.push(tmpProfileLabels[i]);
+ row.push(tmpProfileSiteRules[i]);
+ row.push(this.getFieldRules(i));
+ fieldArray.push(row);
+ }
+ return fieldArray;
+ },
+ profilesTreeHandleKeyPress: function(event) {
+ if(event.keyCode == 46) {
+ this.removeProfile();
+ }
+ },
+
+ invalidRegExpAlert: function(error) {
+ // Invalid regular expression alert:
+ this.getPrompts().alert(
+ null,
+ this.getStringBundle().getString('invalidRegExpTitle'),
+ this.getStringBundle().getString('invalidRegExpText') + "\n\n" + error
+ );
+ },
+
+ makeSafe: function(str) {
+ // Remove all tabs and linefeeds from the given string
+ // (these are used as separators):
+ return str.replace(/\t|\n/g, '');
+ },
+
+ replaceControlCharacters: function(str) {
+ return str.replace(
+ /\n|\t/g,
+ this.replaceControlCharactersCallback
+ );
+ },
+
+ replaceControlCharactersCallback: function(str) {
+ switch(str) {
+ case "\n":
+ return autofillForms.autofillFormsPrefs.getCharPref('placeholderLineBreak');
+ case "\t":
+ return ' ';
+ default:
+ return str;
+ }
+ },
+
+ replaceControlCharacterPlaceholders: function(str) {
+ try {
+ var regExpObj = new RegExp(
+ '('
+ +this.autofillFormsPrefs.getCharPref('placeholderLineBreak')
+ +')|('
+ +this.autofillFormsPrefs.getCharPref('placeholderTab')
+ +')',
+ 'g'
+ );
+ return str.replace(
+ regExpObj,
+ this.replaceControlCharacterPlaceholdersCallback
+ );
+ } catch(e) {
+ return str;
+ }
+ },
+
+ replaceControlCharacterPlaceholdersCallback: function(str) {
+ switch(str) {
+ case autofillForms.autofillFormsPrefs.getCharPref('placeholderLineBreak'):
+ return "\n";
+ case autofillForms.autofillFormsPrefs.getCharPref('placeholderTab'):
+ return "\t";
+ default:
+ return str;
+ }
+ },
+
+ applyFieldRuleOnIndex: function(index) {
+ // Check the regular expressions:
+ try {
+ var fieldRule = this.getRegExpStr(
+ this.makeSafe(document.getElementById('fieldRuleFieldRuleTextBox').value)
+ );
+ document.getElementById('fieldRuleFieldRuleTextBox').value = fieldRule;
+
+ var siteRule = this.getRegExpStr(
+ this.makeSafe(document.getElementById('fieldRuleSiteRuleTextBox').value)
+ );
+ document.getElementById('fieldRuleSiteRuleTextBox').value = siteRule;
+ } catch(e) {
+ this.invalidRegExpAlert(e);
+ return;
+ }
+
+ var ruleName = this.makeSafe(document.getElementById('fieldRuleNameTextBox').value);
+ var ruleValue = this.makeSafe(document.getElementById('fieldRuleValueTextBox').value);
+
+ if( this.getFieldRules()[index] && (
+ this.getFieldRules()[index]['fieldRuleName'] != ruleName ||
+ this.getFieldRules()[index]['fieldRuleValue'] != ruleValue ||
+ this.getFieldRules()[index]['fieldRuleFieldRule'] != fieldRule ||
+ this.getFieldRules()[index]['fieldRuleSiteRule'] != siteRule)) {
+ // Update the formFieldRule on the given index:
+ this.getFieldRules()[index]['fieldRuleName'] = ruleName;
+ this.getFieldRules()[index]['fieldRuleValue'] = ruleValue;
+ this.getFieldRules()[index]['fieldRuleFieldRule'] = fieldRule;
+ this.getFieldRules()[index]['fieldRuleSiteRule'] = siteRule;
+
+ // Notify the tree:
+ this.treeBox.invalidateRow(index);
+
+ // Update the preferences:
+ this.setFieldRules();
+
+ // Update the related row of the simple interface:
+ this.updateSimpleInterfaceRow(index);
+ }
+ },
+
+ applyFieldRule: function(event) {
+ // Only apply changes if one item is selected:
+ if(this.selection.count == 1) {
+ // Update the selected formFieldRule:
+ this.applyFieldRuleOnIndex(this.selection.currentIndex);
+ }
+ },
+
+ addFieldRule: function(event) {
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ // Check the regular expressions:
+ try {
+ var fieldRuleFieldRuleTextBox = document.getElementById('fieldRuleFieldRuleTextBox');
+ var fieldRule = this.getRegExpStr(
+ this.makeSafe(fieldRuleFieldRuleTextBox.value)
+ );
+ fieldRuleFieldRuleTextBox.value = fieldRule;
+
+ var fieldRuleSiteRuleTextBox = document.getElementById('fieldRuleSiteRuleTextBox');
+ var siteRule = this.getRegExpStr(
+ this.makeSafe(fieldRuleSiteRuleTextBox.value)
+ );
+ fieldRuleSiteRuleTextBox.value = siteRule;
+ } catch(e) {
+ this.invalidRegExpAlert(e);
+ return;
+ }
+
+ var newFieldRule = this.createFieldRule(
+ this.makeSafe(document.getElementById('fieldRuleNameTextBox').value),
+ this.makeSafe(document.getElementById('fieldRuleValueTextBox').value),
+ fieldRule,
+ siteRule,
+ true,
+ true
+ )
+
+ var newFieldRuleIndex;
+
+ // Add the new formFieldRule right after the selected position or to the start of the list:
+ if(this.selection.currentIndex == -1 || this.selection.currentIndex == this.treeView.rowCount) {
+ this.getFieldRules().unshift(newFieldRule);
+ newFieldRuleIndex = 0;
+ } else {
+ newFieldRuleIndex = this.selection.currentIndex+1;
+ this.getFieldRules().splice(
+ newFieldRuleIndex,
+ 0,
+ newFieldRule
+ );
+ }
+
+ // Update the tree count and notify the tree:
+ this.treeView.rowCount++;
+ this.treeBox.rowCountChanged(this.treeView.rowCount, +1);
+ this.treeBox.invalidate();
+
+ // Select the new item:
+ this.selection.select(newFieldRuleIndex);
+
+ // Ensure row is visible (scrolls if not):
+ this.treeBox.ensureRowIsVisible(newFieldRuleIndex);
+
+ // Update the preferences:
+ this.setFieldRules();
+
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+ },
+
+ removeFieldRule: function(event) {
+ this.removeSelectedFieldRules();
+ },
+
+ moveUpFieldRule: function(event) {
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ var index = this.selection.currentIndex;
+
+ // Change place with the next upper item:
+ var sibling = this.getFieldRules()[index-1];
+ this.getFieldRules()[index-1] = this.getFieldRules()[index];
+ this.getFieldRules()[index] = sibling;
+
+ // Keep moved item selected:
+ this.selection.select(index-1);
+
+ // Notify the tree:
+ this.treeBox.invalidate();
+
+ // Ensure row is visible (scrolls if not):
+ this.treeBox.ensureRowIsVisible(index-1);
+
+ // Update the preferences:
+ this.setFieldRules();
+
+ // Update the related rows of the simple interface:
+ this.updateSimpleInterfaceRow(index-1);
+ this.updateSimpleInterfaceRow(index);
+ },
+
+ moveDownFieldRule: function(event) {
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ var index = this.selection.currentIndex;
+
+ // Change place with the next lower item:
+ var sibling = this.getFieldRules()[index+1];
+ this.getFieldRules()[index+1] = this.getFieldRules()[index];
+ this.getFieldRules()[index] = sibling;
+
+ // Keep moved item selected:
+ this.selection.select(index+1);
+
+ // Notify the tree:
+ this.treeBox.invalidate();
+
+ // Ensure row is visible (scrolls if not):
+ this.treeBox.ensureRowIsVisible(index+1);
+
+ // Update the preferences:
+ this.setFieldRules();
+
+ // Update the related rows of the simple interface:
+ this.updateSimpleInterfaceRow(index+1);
+ this.updateSimpleInterfaceRow(index);
+ },
+
+ removeSelectedFieldRules: function(event) {
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ // Confirmation dialog:
+ if(!this.getPrompts().confirm(
+ null,
+ this.getStringBundle().getString('removeFieldRulesTitle'),
+ this.getStringBundle().getString('removeFieldRulesText')
+ )
+ ) {
+ return;
+ }
+ }
+
+ // Start of update batch:
+ this.treeBox.beginUpdateBatch();
+
+ // Helper object to store a range:
+ function Range(start, end) {
+ this.start = start.value;
+ this.end = end.value;
+ }
+
+ // List of ranges:
+ var ranges = new Array();
+
+ // Get the number of ranges:
+ var numRanges = this.selection.getRangeCount();
+
+ // Helper vars to store the range end points:
+ var start = new Object();
+ var end = new Object();
+
+ // We store the list of ranges first, as calling
+ // this.treeBox.rowCountChanged()
+ // seems to invalidate the current selection
+
+ for(var i=0; i < numRanges; i++) {
+ // Get the current range end points:
+ this.selection.getRangeAt(i,start,end);
+ // Store them as a Range object in the ranges list:
+ ranges[i] = new Range(start, end);
+ }
+
+ for(var i=0; i < numRanges; i++) {
+ // Go through the stored ranges:
+ for(var j = ranges[i].start; j <= ranges[i].end; j++) {
+ // Set the selected fieldRules to null:
+ this.getFieldRules()[j] = null;
+ }
+
+ // Calculate the new tree count:
+ var count = ranges[i].end - ranges[i].start + 1;
+
+ // Update the tree count and notify the tree:
+ this.treeView.rowCount -= count;
+ this.treeBox.rowCountChanged(ranges[i].start, -count);
+ }
+
+ // Collapse list by removing all the null entries
+ for (var i=0; i < this.getFieldRules().length; i++) {
+ if (!this.getFieldRules()[i]) {
+ var j = i;
+ while (j < this.getFieldRules().length && !this.getFieldRules()[j])
+ j++;
+ this.getFieldRules().splice(i, j-i);
+ }
+ }
+
+ // Clear out selections
+ this.selection.select(-1);
+
+ // End of update batch:
+ this.treeBox.endUpdateBatch();
+
+ // Update the preferences:
+ this.setFieldRules();
+
+ // Re-initialize the simple interface:
+ this.initSimpleInterface();
+ },
+
+ handleKeyPress: function(event) {
+ if(event.keyCode == 46) {
+ this.removeSelectedFieldRules();
+ } else if(event.ctrlKey && event.which == 97) {
+ if(this.tree && this.selection) {
+ try {
+ // Select all rows:
+ this.selection.selectAll();
+ } catch(e) {
+ this.log(e);
+ }
+ }
+ }
+ },
+
+ getGlobalFieldRules: function() {
+ // Return the fieldRules for the selected global profile if globalProfileIndex is not out of range:
+ if(this.getGlobalProfileIndex() >= 0 && this.getGlobalProfileIndex() < this.getProfileLabels().length) {
+ return this.getFieldRules(this.getGlobalProfileIndex());
+ } else {
+ this.globalProfileIndex = 0;
+ return this.getFieldRules(0);
+ }
+ },
+
+ getFileContent: function(file) {
+ var fileContent = null;
+ try {
+ var fis = Components.classes['@mozilla.org/network/file-input-stream;1']
+ .createInstance(Components.interfaces.nsIFileInputStream);
+ fis.init(file, -1, 0, 0);
+ var is = Components.classes['@mozilla.org/intl/converter-input-stream;1']
+ .createInstance(Components.interfaces.nsIConverterInputStream);
+ is.init(fis, 'UTF-8', 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+ if(is instanceof Components.interfaces.nsIUnicharLineInputStream) {
+ var line = {};
+ var cont;
+ do {
+ cont = is.readLine(line);
+ if(fileContent == null) {
+ fileContent = line.value;
+ } else {
+ fileContent += '\n'+line.value;
+ }
+ } while (cont);
+ }
+ is.close();
+ fis.close();
+ } catch(e) {
+ this.log(e);
+ }
+ return fileContent;
+ },
+
+ setFileContent: function(file, str) {
+ try {
+ var fos = Components.classes['@mozilla.org/network/file-output-stream;1']
+ .createInstance(Components.interfaces.nsIFileOutputStream);
+ fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0);
+ var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
+ .createInstance(Components.interfaces.nsIConverterOutputStream);
+ os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+ os.writeString(str);
+ os.close();
+ fos.close();
+ } catch(e) {
+ this.log(e);
+ }
+ },
+
+ getFieldRulesFile: function() {
+ var file = this.getConfigDirectory();
+ file.append('fieldRules.txt');
+ if(!file.exists()) {
+ file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
+ }
+ return file;
+ },
+
+ getConfigDirectory: function() {
+ var configDirectory;
+ if(this.autofillFormsPrefs.prefHasUserValue('configDirectory')) {
+ try {
+ configDirectory = this.autofillFormsPrefs.getComplexValue(
+ 'configDirectory',
+ Components.interfaces.nsILocalFile
+ );
+ } catch(e) {
+ this.autofillFormsPrefs.clearUserPref('configDirectory');
+ }
+ }
+ if(!configDirectory) {
+ configDirectory = this.getDefaultConfigDirectory();
+ }
+ return configDirectory;
+ },
+
+ getDefaultConfigDirectory: function() {
+ // Use a directory "autofillForms at blueimp.net" inside Firefox profile directory as default:
+ var configDirectory = Components.classes['@mozilla.org/file/directory_service;1']
+ .getService(Components.interfaces.nsIProperties)
+ .get('ProfD', Components.interfaces.nsILocalFile);
+ configDirectory.append('autofillForms at blueimp.net');
+ if(!configDirectory.exists()) {
+ configDirectory.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0770);
+ }
+ return configDirectory;
+ },
+
+ setConfigDirectory: function(textBox) {
+ try {
+ // Create a file picker instance:
+ var fp = Components.classes['@mozilla.org/filepicker;1']
+ .createInstance(Components.interfaces.nsIFilePicker);
+
+ // Initialize the file picker window:
+ fp.init(
+ window,
+ this.getStringBundle().getString('selectConfigDirectory'),
+ Components.interfaces.nsIFilePicker.modeGetFolder
+ );
+
+ // Show the file picker window:
+ var rv = fp.show();
+
+ if (rv == Components.interfaces.nsIFilePicker.returnOK) {
+ var newDir = fp.file;
+ if(newDir.path == this.getConfigDirectory().path) {
+ return;
+ }
+ this.moveConfigFiles(newDir);
+ // Save the selected directory in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'configDirectory',
+ Components.interfaces.nsILocalFile, newDir
+ );
+ if(textBox) {
+ // Set the textbox value to the directory path:
+ textBox.value = newDir.path;
+ }
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+
+ resetConfigDirectory: function(textBox) {
+ if(this.autofillFormsPrefs.prefHasUserValue('configDirectory')) {
+ var newDir = this.getDefaultConfigDirectory();
+ this.moveConfigFiles(newDir);
+ this.autofillFormsPrefs.clearUserPref('configDirectory');
+ if(textBox) {
+ // Set the textbox value to an empty string:
+ textBox.value = '';
+ }
+ }
+ },
+
+ openConfigDirectory: function() {
+ var configDirectory = this.getConfigDirectory();
+ if(configDirectory) {
+ try {
+ // Open the config directory in the operating system file manager:
+ configDirectory.reveal();
+ } catch(e) {
+ // reveal method may not be supported on some platforms,
+ // use nsIExternalProtocolService instead:
+ var uri = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService)
+ .newFileURI(configDirectory);
+ var protocolSvc =
+ Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
+ .getService(Components.interfaces.nsIExternalProtocolService);
+ protocolSvc.loadUrl(uri);
+ }
+ }
+ },
+
+ moveConfigFiles: function(newDir) {
+ if(this.checkConfigDirectoryOverwrite(newDir)) {
+ this.moveFile(this.getFieldRulesFile(), newDir);
+ this.moveFile(this.getDynamicTagsFile(), newDir);
+ this.moveFile(this.getDynamicTagCodesFile(), newDir);
+ this.moveFile(this.getProfileLabelsFile(), newDir);
+ this.moveFile(this.getProfileSiteRulesFile(), newDir);
+ return true;
+ }
+ return false;
+ },
+
+ importFromConfigDirectory: function() {
+ var ok = true;
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ ok = this.getPrompts().confirm(
+ window,
+ this.getStringBundle().getString('importFromConfigDirectoryTitle'),
+ this.getStringBundle().getString('importFromConfigDirectoryText')
+ );
+ }
+ if(ok) {
+ this.importFieldRulesFromConfigDirectory();
+ this.importDynamicTagsFromConfigDirectory();
+ this.importDynamicTagCodesFromConfigDirectory();
+ this.importProfileLabelsFromConfigDirectory();
+ this.importProfileSiteRulesFromConfigDirectory();
+ }
+ },
+
+ exportToConfigDirectory: function() {
+ if(this.checkConfigDirectoryOverwrite(this.getConfigDirectory())) {
+ this.exportFieldRulesToConfigDirectory();
+ this.exportDynamicTagsToConfigDirectory();
+ this.exportDynamicTagCodesToConfigDirectory();
+ this.exportProfileLabelsToConfigDirectory();
+ this.exportProfileSiteRulesToConfigDirectory();
+ return true;
+ }
+ return false;
+ },
+
+ moveFile: function(file, newDir, newFileName) {
+ try {
+ // The new fileName - uses the current fileName if empty:
+ newFileName = (typeof newFileName == 'string') ? newFileName : null;
+
+ file.moveTo(newDir, newFileName);
+ return true;
+ } catch(e) {
+ this.log(e);
+ return false;
+ }
+ },
+
+ checkConfigDirectoryOverwrite: function(newDir) {
+ var ok = true;
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ if(newDir.directoryEntries.hasMoreElements()) {
+ ok = this.getPrompts().confirm(
+ window,
+ this.getStringBundle().getString('newConfigDirectoryNotEmptyTitle'),
+ this.getStringBundle().getString('newConfigDirectoryNotEmptyText')
+ );
+ }
+ }
+ return ok;
+ },
+
+ exportFieldRulesToConfigDirectory: function() {
+ var prefString;
+ // Get the fieldRules string from the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('fieldRules',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ if(prefString) {
+ this.setFileContent(this.getFieldRulesFile(), prefString);
+ }
+ },
+
+ importFieldRulesFromConfigDirectory: function() {
+ var prefString;
+ prefString = this.getFileContent(this.getFieldRulesFile());
+ if(prefString) {
+ // Store the fieldRules as unicode string in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'fieldRules',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getFieldRules: function(profileIndex) {
+ if(this.fieldRules == null) {
+ this.fieldRules = new Array();
+
+ var prefString;
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Get the fieldRules string from the fieldRules file in the configDirectory:
+ prefString = this.getFileContent(this.getFieldRulesFile());
+ }
+ if(!prefString) {
+ // Get the fieldRules string from the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('fieldRules',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ }
+
+ // On change of the "storeEncrypted" setting, we must decrypt or may not decrypt
+ // the prefString in opposition to the setting - the "invertedSetting" helper var
+ // helps to identify this situation:
+ var boolTest = this.invertedSetting ? false : true;
+
+ // If the fieldRules are stored encrypted, decrypt the prefString:
+ if(this.autofillFormsPrefs.getBoolPref('storeEncrypted') == boolTest) {
+ try {
+ // nsISecretDecoderRing fails to handle characters above ISO-8859-1 charset
+ // The usage of encodeURI/decodeURI on the fieldRule properties bypasses this problem
+ prefString = this.getCryptoService().decryptString(prefString);
+ } catch(e) {
+ // Decrypting failed - return an empty default profile:
+ this.fieldRules.push(new Array());
+ this.profileIndex = 0;
+ return this.fieldRules[0];
+ }
+ }
+
+ // Get the profiles (separated by \n\n):
+ var profiles = prefString.split('\n\n');
+
+ for(var i=0; i<profiles.length; i++) {
+ // Create an array for each profile:
+ this.fieldRules.push(new Array());
+
+ // Get the fieldRules rows (separated by \n):
+ var rows = profiles[i].split('\n');
+ if(rows[0]) {
+ for(var j=0; j<rows.length; j++) {
+ if(!rows[j])
+ continue;
+
+ // Get the fieldRules column items (separated by \t):
+ var cols = rows[j].split('\t');
+
+ // Create fieldRules objects and save them in the current fieldRules Array:
+ if(cols.length && cols.length == 6) {
+
+ // Decode the fieldRule properties:
+ for(var k=0; k<cols.length; k++) {
+ cols[k] = decodeURI(cols[k]);
+ }
+
+ this.fieldRules[i].push(
+ this.createFieldRule(
+ cols[0],cols[1],cols[2],cols[3],
+ (cols[4] != 'false'),
+ (cols[5] != 'false')
+ )
+ );
+ }
+ }
+ } else
+ this.fieldRules[i] = new Array();
+ }
+ }
+
+ profileIndex = (typeof profileIndex != 'undefined') ? profileIndex : this.getProfileIndex();
+
+ // Return the fieldRules for the selected profile if profileIndex is not out of range:
+ if(profileIndex >= 0 && profileIndex < this.fieldRules.length)
+ return this.fieldRules[profileIndex];
+ else {
+ this.profileIndex = 0;
+ if(this.fieldRules[0] == null)
+ this.fieldRules[0] = new Array();
+ return this.fieldRules[0];
+ }
+ },
+
+ setFieldRules: function() {
+ if(this.fieldRules == null) {
+ // Initialize the field rules:
+ this.getFieldRules();
+ }
+
+ var profiles = '';
+ var rows, cols;
+ for(var i=0; i < this.fieldRules.length; i++) {
+ rows = '';
+ for(var j=0; j<this.fieldRules[i].length; j++) {
+ cols = null;
+ for(var property in this.fieldRules[i][j]) {
+ if(cols == null)
+ cols = '';
+ else
+ cols += '\t';
+ // Encode the fieldRule property before adding it to the string:
+ cols += encodeURI(this.fieldRules[i][j][property]);
+ }
+ if(j!=0)
+ rows += '\n';
+ rows += cols;
+ }
+ if(i!=0)
+ profiles += '\n\n';
+ profiles += rows;
+ }
+
+ // If the fieldRules are to be stored encrypted, encrypt the prefString:
+ if(this.autofillFormsPrefs.getBoolPref('storeEncrypted')) {
+ try {
+ // nsISecretDecoderRing fails to handle characters above ISO-8859-1 charset
+ // The usage of encodeURI/decodeURI on the fieldRule properties bypasses this problem
+ profiles = this.getCryptoService().encryptString(profiles);
+ } catch(e) {
+ // Decrypting failed - return:
+ return;
+ }
+ }
+
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ this.setFileContent(this.getFieldRulesFile(), profiles);
+ } else {
+ // Store the fieldRules objects as unicode string in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'fieldRules',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(profiles)
+ );
+ }
+ },
+
+ copyFieldRules: function(origin) {
+ var copy = new Array();
+ for(var i=0; i<origin.length; i++) {
+ copy.push(
+ this.createFieldRule(
+ origin[i]['fieldRuleName'],
+ origin[i]['fieldRuleValue'],
+ origin[i]['fieldRuleFieldRule'],
+ origin[i]['fieldRuleSiteRule'],
+ origin[i]['fieldRuleOverwrite'],
+ origin[i]['fieldRuleEnabled']
+ )
+ )
+ }
+ return copy;
+ },
+ importDynamicTagsFromSettings: function() {
+ //Here the tags are added directly
+ var prefString = null;
+
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ var dynamicTags = prefString.split('\t');
+
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ var dynamicTagCodes = prefString.split('\t');
+
+ this.importDynamicTags(dynamicTags, dynamicTagCodes);
+ this.setDynamicTags(dynamicTags);
+ this.setDynamicTagCodes(dynamicTagCodes);
+ },
+ importDynamicTagsFromTagEditor: function() {
+ //Here the tags are added to the editor window, can be cancelled if necessary
+ var richlistbox = document.getElementById('tagList');
+ if(richlistbox) {
+ var richlistitems = richlistbox.getElementsByTagName('richlistitem');
+ var textboxes;
+
+ var dynamicTags = new Array();
+ var dynamicTagCodes = new Array();
+
+ // Go through the richlistbox items:
+ for(var i=0; i<richlistitems.length; i++) {
+ textboxes = richlistitems[i].getElementsByTagName('textbox');
+
+ // Add the dynamic tags and their associated tag codes to the lists:
+ if (textboxes[0].value != '' && textboxes[1].value != '') {
+ dynamicTags.push(this.makeSafe(textboxes[0].value));
+ dynamicTagCodes.push(this.makeSafe(textboxes[1].value));
+ }
+ }
+ this.importDynamicTags(dynamicTags, dynamicTagCodes);
+ }
+ },
+ importDynamicTags: function(dynamicTags, dynamicTagCodes) {
+ try {
+ var file = this.filePicker('modeOpen', this.getStringBundle().getString('importDynamicTags'));
+ if(file) {
+ var fis = Components.classes['@mozilla.org/network/file-input-stream;1']
+ .createInstance(Components.interfaces.nsIFileInputStream);
+ fis.init(file, -1, 0, 0);
+
+ var is = Components.classes['@mozilla.org/intl/converter-input-stream;1']
+ .createInstance(Components.interfaces.nsIConverterInputStream);
+ is.init(fis, 'UTF-8', 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+
+ if (is instanceof Components.interfaces.nsIUnicharLineInputStream) {
+ var line = {};
+ var cont;
+ var firstLine = true;
+ var i;
+
+ do {
+ cont = is.readLine(line);
+
+ // Get the dynamicTags column items (separated by \t) from the file:
+ var cols = line.value.split('\t');
+
+ if (firstLine == true) {
+ // The first row has the following syntax (added in version 0.9.5):
+ // autofillForms at blueimp.net Version dynamictags
+ if(cols.length && cols.length != 3)
+ cont = false;
+ else if (cols[0] != 'autofillForms at blueimp.net')
+ cont = false;
+ else if (cols[2] != 'dynamictags')
+ cont = false;
+ firstLine = false;
+ }
+ else if (cols.length && cols.length == 2) {
+ //Check the imported pair isn't already defined or empty.
+ i = dynamicTags.indexOf(cols[0]);
+ if ((i >= 0 && dynamicTagCodes[i] == cols[1])||(cols[0]=='' && cols[1]=='')) {
+ continue;
+ } else {
+ dynamicTags.push(cols[0]);
+ dynamicTagCodes.push(cols[1]);
+ this.tagEditorAdd(cols[0],cols[1])
+ }
+ }
+ } while (cont);
+
+ }
+ is.close();
+ fis.close();
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+ exportDynamicTagsFromSettings: function() {
+ var prefString = null;
+
+ // Write the tags to file analog to storing them in the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ var dynamicTagCodes = prefString.split('\t');
+
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ var dynamicTags = prefString.split('\t');
+ this.exportDynamicTags(dynamicTags, dynamicTagCodes);
+ },
+ exportDynamicTagsFromTagEditor: function() {
+ var richlistbox = document.getElementById('tagList');
+ if(richlistbox) {
+ var richlistitems = richlistbox.getElementsByTagName('richlistitem');
+ var textboxes;
+
+ var dynamicTags = new Array();
+ var dynamicTagCodes = new Array();
+
+ // Go through the richlistbox items:
+ for(var i=0; i<richlistitems.length; i++) {
+ textboxes = richlistitems[i].getElementsByTagName('textbox');
+
+ // Add the dynamic tags and their associated tag codes to the lists:
+ if (textboxes[0].value != '' && textboxes[1].value != '') {
+ dynamicTags.push(this.makeSafe(textboxes[0].value));
+ dynamicTagCodes.push(this.makeSafe(textboxes[1].value));
+ }
+ }
+ this.exportDynamicTags(dynamicTags, dynamicTagCodes);
+ }
+ },
+ exportDynamicTags: function(dynamicTags, dynamicTagCodes) {
+ try {
+ var file = this.filePicker(
+ 'modeSave',
+ this.getStringBundle().getString('exportDynamicTags'),
+ this.getProfileLabel(this.getProfileIndex())+'.txt'
+ );
+ if(file) {
+ var fos = Components.classes['@mozilla.org/network/file-output-stream;1'].
+ createInstance(Components.interfaces.nsIFileOutputStream);
+ fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
+
+ var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
+ .createInstance(Components.interfaces.nsIConverterOutputStream);
+ os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+
+
+ var header = 'autofillForms at blueimp.net' + '\t'
+ + this.version + '\t'
+ + 'dynamictags\n';
+ os.writeString(header);
+
+ var cols;
+ for(var i=0; i<dynamicTags.length; i++) {
+ cols = dynamicTags[i]+'\t'+dynamicTagCodes[i];
+ os.writeString('\n' + cols);
+ }
+ os.close();
+ fos.close();
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+ importProfile: function() {
+ try {
+ var file = this.filePicker('modeOpen', this.getStringBundle().getString('importProfile'));
+ if(file) {
+ var fis = Components.classes['@mozilla.org/network/file-input-stream;1']
+ .createInstance(Components.interfaces.nsIFileInputStream);
+ fis.init(file, -1, 0, 0);
+
+ var is = Components.classes['@mozilla.org/intl/converter-input-stream;1']
+ .createInstance(Components.interfaces.nsIConverterInputStream);
+ is.init(fis, 'UTF-8', 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+
+ if(this.fieldRules == null) {
+ // Initialize the field rules:
+ this.getFieldRules();
+ }
+
+ // Create a new fieldRule profile (index is incremented when a valid header is found):
+ var newProfileLabel = '';
+ var newProfileSiteRule = '(?:)';
+ var newProfileIndex = this.fieldRules.length-1;
+ var validProfile = false;
+
+ if (is instanceof Components.interfaces.nsIUnicharLineInputStream) {
+ var line = {};
+ var cont;
+ do {
+ cont = is.readLine(line);
+
+ // Get the fieldRules column items (separated by \t) from the file:
+ var cols = line.value.split('\t');
+
+ if(cols.length && cols.length < 6 && cols[0] == 'autofillForms at blueimp.net') {
+ // The first row has the following syntax (added SiteRule for version 0.9.1):
+ // autofillForms at blueimp.net Version Label SiteRule
+ // Every time such a row is encountered, a new profile is generated.
+ if(cols.length >= 3) {
+ newProfileLabel = cols[2];
+ // Add profile label for default empty profile:
+ if(this.getProfileLabels().length == 0) {
+ this.getProfileLabels().push(this.getUniqueProfileLabel());
+ }
+ // Add the newProfileLabel to the profileLabels list (make sure it is unique):
+ this.getProfileLabels().push(this.getUniqueProfileLabel(newProfileLabel));
+ }
+ if(cols.length >= 4) {
+ try {
+ newProfileSiteRule = this.getRegExpStr(cols[3]);
+ // Add a new profileSiteRule:
+ this.getProfileSiteRules().push(newProfileSiteRule);
+ } catch(e) {
+ // Catch missing or invalid site rule
+ }
+ }
+ // Increment the ProfileIndex
+ newProfileIndex += 1;
+ this.fieldRules.push(new Array());
+ validProfile = true;
+ } else if(cols.length && cols.length == 6 && validProfile == true) {
+ // Create fieldRules objects and save them in the fieldRules Array:
+ this.fieldRules[newProfileIndex].push(
+ this.createFieldRule(
+ cols[0],cols[1],cols[2],cols[3],
+ (cols[4] != 'false'),
+ (cols[5] != 'false')
+ )
+ );
+ }
+
+ } while (cont);
+ }
+
+ // Save the profileLabels list in the preferences:
+ this.setProfileLabels(this.getProfileLabels());
+ // Save the profileSiteRules in the preferences:
+ this.setProfileSiteRules(this.getProfileSiteRules());
+ // Update the profiles lists:
+ this.initProfilesLists();
+
+ // Update the fieldRules:
+ this.setFieldRules();
+
+ is.close();
+ fis.close();
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+ exportProfile: function() {
+ try {
+ var file = this.filePicker(
+ 'modeSave',
+ this.getStringBundle().getString('exportProfile'),
+ this.getProfileLabel(this.getProfileIndex())+'.txt'
+ );
+ if(file) {
+ var fos = Components.classes['@mozilla.org/network/file-output-stream;1'].
+ createInstance(Components.interfaces.nsIFileOutputStream);
+ fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
+
+ var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
+ .createInstance(Components.interfaces.nsIConverterOutputStream);
+ os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+
+ var profileIndex = this.getProfileIndex();
+ this.writeProfile(os, profileIndex);
+
+ os.close();
+ fos.close();
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+ exportAllProfiles: function() {
+ try {
+ //use the first profile label as the filename
+ var file = this.filePicker(
+ 'modeSave',
+ this.getStringBundle().getString('exportProfile'),
+ this.getProfileLabel(0)+'.txt'
+ );
+ if(file) {
+ var fos = Components.classes['@mozilla.org/network/file-output-stream;1'].
+ createInstance(Components.interfaces.nsIFileOutputStream);
+ fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
+
+ var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
+ .createInstance(Components.interfaces.nsIConverterOutputStream);
+
+ os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+
+ for(var i=0; i<this.getProfileLabels().length; i++) {
+ this.writeProfile(os, i);
+ os.writeString('\n\n');
+ }
+ os.close();
+ fos.close();
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+ writeProfile: function(os, profileIndex) {
+ try {
+ var header = 'autofillForms at blueimp.net' + '\t'
+ + this.version + '\t'
+ + this.getProfileLabel(profileIndex) + '\t'
+ + this.getProfileSiteRule(profileIndex) + '\n';
+
+
+ os.writeString(header);
+ // Write the rules to file analog to storing them in the preferences:
+ var cols;
+ for(var i=0; i<this.getFieldRules(profileIndex).length; i++) {
+ cols = null;
+ for(var property in this.getFieldRules(profileIndex)[i]) {
+ if(cols == null)
+ cols = '';
+ else
+ cols += '\t';
+ cols += this.getFieldRules(profileIndex)[i][property];
+ }
+ os.writeString('\n' + cols);
+ }
+ } catch(e) {
+ this.log(e);
+ }
+ },
+ filePicker: function(mode, title, fileName) {
+ try {
+ // Create a file picker instance:
+ var fp = Components.classes['@mozilla.org/filepicker;1']
+ .createInstance(Components.interfaces.nsIFilePicker);
+
+ // The filename suggested to the user as a default:
+ if(fileName) {
+ fp.defaultString = fileName;
+ }
+
+ // Initialize the file picker window:
+ fp.init(
+ window,
+ title,
+ Components.interfaces.nsIFilePicker[mode]
+ );
+
+ // Show the file picker window:
+ var rv = fp.show();
+
+ if(rv==Components.interfaces.nsIFilePicker.returnOK || rv==Components.interfaces.nsIFilePicker.returnReplace)
+ return fp.file;
+ else
+ return null;
+ } catch(e) {
+ return null;
+ }
+ },
+
+ getUnicodeString: function(stringData) {
+ // Create an Unicode String:
+ var str = Components.classes['@mozilla.org/supports-string;1']
+ .createInstance(Components.interfaces.nsISupportsString);
+ // Set the String value:
+ str.data = stringData;
+ // Return the Unicode String:
+ return str;
+ },
+
+ getStringBundle: function() {
+ return document.getElementById('autofillFormsStringBundle');
+ },
+
+ getDoc: function(win) {
+ if(win)
+ return win.document;
+ else if(content)
+ return content.document;
+ else
+ return this.getBrowser().contentDocument;
+ },
+
+ getWin: function() {
+ if(content)
+ return content;
+ else
+ return this.getBrowser().contentWindow;
+ },
+
+ getBrowser: function() {
+ try {
+ return gBrowser;
+ } catch(e) {
+ // gBrowser is not available, so make use of the WindowMediator service instead:
+ return this.getWindowMediator().getMostRecentWindow('navigator:browser').getBrowser();
+ }
+ },
+
+ getWindowMediator: function() {
+ return Components.classes['@mozilla.org/appshell/window-mediator;1']
+ .getService(Components.interfaces.nsIWindowMediator);
+ },
+
+ getRegExpStr: function(str) {
+ // Create a RegExp object using the given String:
+ var regExpStr = new RegExp(str).toString();
+ // Return the String representation without the surrounding slashes:
+ return regExpStr.substr(1,regExpStr.length-2);
+ },
+
+ getPrefManager: function() {
+ return Components.classes['@mozilla.org/preferences-service;1']
+ .getService(Components.interfaces.nsIPrefService);
+ },
+
+ getCryptoService: function() {
+ return Components.classes['@mozilla.org/security/sdr;1']
+ .createInstance(Components.interfaces.nsISecretDecoderRing);
+ },
+
+ getPrompts: function() {
+ return Components.classes['@mozilla.org/embedcomp/prompt-service;1']
+ .getService(Components.interfaces.nsIPromptService);
+ },
+
+ recognizeMouseButton: function(event) {
+ var modifiers = new Array();
+
+ // Get the modifiers:
+ if(event.altKey) modifiers.push('alt');
+ if(event.ctrlKey) modifiers.push('control');
+ if(event.metaKey) modifiers.push('meta');
+ if(event.shiftKey) modifiers.push('shift');
+
+ // Return a mouseButtonObj:
+ return this.mouseButtonFactory(modifiers, 'mousebutton'+event.button);
+ },
+
+ mouseButtonFactory: function(modifiers, mouseButton) {
+ if(typeof arguments.callee.mouseButtonObj == 'undefined') {
+ arguments.callee.mouseButtonObj = function(modifiers, mouseButton) {
+ this.modifiers = modifiers ? modifiers : new Array();
+ this.mouseButton = mouseButton;
+ this.toString = function() {
+ if(this.modifiers.length) {
+ return this.modifiers.join('+')+'+'+this.mouseButton;
+ } else {
+ return this.mouseButton;
+ }
+ }
+ this.equals = function(mouseButtonObj) {
+ if(this.mouseButton != mouseButtonObj.mouseButton) {
+ return false;
+ }
+ if(this.modifiers.length != mouseButtonObj.modifiers.length) {
+ return false;
+ }
+ for(var i=0; i<this.modifiers.length; i++) {
+ if(this.modifiers[i] != mouseButtonObj.modifiers[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return this;
+ }
+ }
+ return new arguments.callee.mouseButtonObj(modifiers, mouseButton);
+ },
+
+ getFormattedMouseButton: function(mouseButtonObj) {
+ var formattedMouseButton = '';
+ if(!mouseButtonObj.mouseButton) {
+ return formattedMouseButton;
+ }
+ // Add the modifiers:
+ for(var i=0; i < mouseButtonObj.modifiers.length; i++) {
+ try {
+ formattedMouseButton += this.getStringBundle().getString(mouseButtonObj.modifiers[i])+'+';
+ } catch(e) {
+ this.log(e);
+ // Error in shortcut string, return empty String:
+ return '';
+ }
+ }
+ try {
+ formattedMouseButton += this.getStringBundle().getString(mouseButtonObj.mouseButton);
+ } catch(e) {
+ // No localization for this mouse button, add generic button string :
+ formattedMouseButton += this.getStringBundle().getString('mousebutton');
+ // Add the index of the given mouseButton:
+ formattedMouseButton += ' '+mouseButtonObj.mouseButton.substr('mousebutton'.length);
+ }
+ return formattedMouseButton;
+ },
+
+ applyMouseButton: function(event, id) {
+ // Recognize the mouse button event:
+ var mouseButtonObj = this.recognizeMouseButton(event);
+ if(!mouseButtonObj)
+ return;
+ // Ignore the right mouse button (mousebutton2), as this already invokes the context menu:
+ if(mouseButtonObj.mouseButton == 'mousebutton2') {
+ return;
+ }
+ // Save the new mouse button object:
+ this.setMouseButton(id, mouseButtonObj);
+ // Update the mouse button textbox:
+ if(event.view.document && event.view.document.getElementById(id)) {
+ event.view.document.getElementById(id).value = this.getFormattedMouseButton(mouseButtonObj);
+ }
+ },
+
+ disableMouseButton: function(event, id) {
+ // Disable the mouse button:
+ this.setMouseButton(id, null);
+ // Update the mouse button textbox:
+ if(event.view.document && event.view.document.getElementById(id)) {
+ event.view.document.getElementById(id).value = '';
+ }
+ },
+
+ getMouseButton: function(id) {
+ if(this.mouseButton == null) {
+ // Create a new mouseButton container object:
+ this.mouseButton = new Object();
+ }
+ if(this.mouseButton[id] == null) {
+ var mouseButtonItems = this.autofillFormsPrefs.getCharPref(id).split('+');
+ var mouseButton;
+ if(mouseButtonItems.length == 0) {
+ mouseButton = '';
+ } else {
+ // Remove the last element and save it as mouseButton
+ // the remaining mouseButtonItems are the modifiers:
+ mouseButton = mouseButtonItems.pop();
+ }
+ // Create a new mouseButton object:
+ this.mouseButton[id] = this.mouseButtonFactory(mouseButtonItems, mouseButton);
+ }
+ return this.mouseButton[id];
+ },
+
+ setMouseButton: function(id, mouseButtonObj) {
+ var stringData;
+ if(mouseButtonObj) {
+ stringData = mouseButtonObj.toString();
+ } else {
+ stringData = '';
+ }
+ // Save the mouseButtonObj as Unicode String in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ id,
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(stringData)
+ );
+ },
+
+ recognizeKeys: function(event) {
+ var modifiers = new Array();
+ var key = '';
+ var keycode = '';
+
+ // Get the modifiers:
+ if(event.altKey) modifiers.push('alt');
+ if(event.ctrlKey) modifiers.push('control');
+ if(event.metaKey) modifiers.push('meta');
+ if(event.shiftKey) modifiers.push('shift');
+
+ // Get the key or keycode:
+ if(event.charCode) {
+ key = String.fromCharCode(event.charCode).toUpperCase();
+ } else {
+ // Get the keycode from the keycodes list:
+ keycode = this.getKeyCodes()[event.keyCode];
+ if(!keycode) {
+ return null;
+ }
+ }
+
+ // Shortcut may be anything, but not 'VK_TAB' alone (without modifiers),
+ // as this button is used to change focus to the 'Apply' button:
+ if(modifiers.length > 0 || keycode != 'VK_TAB') {
+ return this.shortcutFactory(modifiers, key, keycode);
+ }
+ return null;
+ },
+
+ shortcutFactory: function(modifiers, key, keycode) {
+ if(typeof arguments.callee.shortcut == 'undefined') {
+ arguments.callee.shortcut = function(modifiers, key, keycode) {
+ this.modifiers = modifiers ? modifiers : new Array();
+ this.key = key;
+ this.keycode = keycode;
+ this.toString = function() {
+ if(this.modifiers.length) {
+ return this.modifiers.join('+')+'+'+this.key+this.keycode;
+ } else {
+ return this.key+this.keycode;
+ }
+ }
+ this.equals = function(shortcut) {
+ if(this.key != shortcut.key) {
+ return false;
+ }
+ if(this.keycode != shortcut.keycode) {
+ return false;
+ }
+ if(this.modifiers.length != shortcut.modifiers.length) {
+ return false;
+ }
+ for(var i=0; i<this.modifiers.length; i++) {
+ if(this.modifiers[i] != shortcut.modifiers[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return this;
+ }
+ }
+ return new arguments.callee.shortcut(modifiers, key, keycode);
+ },
+
+ getKeyCodes: function() {
+ var keycodes = new Array();
+ // Get the list of keycodes from the KeyEvent object:
+ for(var property in KeyEvent) {
+ keycodes[KeyEvent[property]] = property.replace('DOM_','');
+ }
+ // VK_BACK_SPACE (index 8) must be VK_BACK:
+ keycodes[8] = 'VK_BACK';
+ return keycodes;
+ },
+
+ applyShortcut: function(event, id) {
+ // Recognize the pressed keys:
+ var shortcut = this.recognizeKeys(event)
+ if(!shortcut)
+ return;
+ // Save the new shortcut:
+ this.setShortcut(id, shortcut);
+ // Update the shortcut textbox:
+ if(event.view.document && event.view.document.getElementById(id)) {
+ event.view.document.getElementById(id).value = this.getFormattedShortcut(shortcut);
+ }
+ },
+
+ disableShortcut: function(event, id) {
+ // Disable the shortcut:
+ this.setShortcut(id, null);
+ // Update the shortcut textbox:
+ if(event.view.document && event.view.document.getElementById(id)) {
+ event.view.document.getElementById(id).value = '';
+ }
+ },
+
+ getShortcut: function(id) {
+ if(this.shortcut == null) {
+ // Create a new shortcut container object:
+ this.shortcut = new Object();
+ }
+ if(this.shortcut[id] == null) {
+ var key = null;
+ var keycode = null;
+ var shortcutItems = this.autofillFormsPrefs
+ .getComplexValue(id,Components.interfaces.nsIPrefLocalizedString)
+ .data.split('+');
+ if(shortcutItems.length > 0) {
+ // Remove the last element and save it as key
+ // the remaining shortcutItems are the modifiers:
+ key = shortcutItems.pop();
+ // Check if the key is a keycode:
+ if(key.indexOf('VK') == 0) {
+ keycode = key;
+ key = null;
+ }
+ }
+ // Create a new shortcut object:
+ this.shortcut[id] = this.shortcutFactory(shortcutItems, key, keycode);
+ }
+ return this.shortcut[id];
+ },
+
+ setShortcut: function(id, shortcut) {
+ var stringData;
+ if(shortcut) {
+ stringData = shortcut.toString();
+ } else {
+ stringData = '';
+ }
+ // Save the shortcut as Unicode String in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ id,
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(stringData)
+ );
+ },
+
+ updateShortcut: function(id) {
+ if(this.shortcut == null) {
+ this.shortcut = new Object();
+ }
+ // Setting the shortcut object to "null" will update it on the next getShortcut() call:
+ this.shortcut[id] = null;
+
+ // Get the keyboard shortcut elements:
+ var modifiers = this.getShortcut(id).modifiers.join(' ');
+ var key = this.getShortcut(id).key;
+ var keycode = this.getShortcut(id).keycode;
+
+ var domId = 'autofillForms' + id.replace(/shortcut/, 'Shortcut');
+ var command = 'autofillForms' + id.replace(/shortcut/i, '');
+
+ // Remove current key if existing:
+ if(document.getElementById(domId)) {
+ document.getElementById('mainKeyset').removeChild(
+ document.getElementById(domId)
+ );
+ }
+
+ // Check if keyboard shortcut is enabled:
+ if(key || keycode) {
+ // Create a key element:
+ var keyNode = document.createElement('key');
+
+ keyNode.setAttribute('id', domId);
+ keyNode.setAttribute('command', command);
+
+ // Set the key attributes from saved shortcut:
+ keyNode.setAttribute('modifiers', modifiers);
+ if(key) {
+ keyNode.setAttribute('key', key);
+ } else {
+ keyNode.setAttribute('keycode', keycode);
+ }
+
+ // Add the key to the mainKeyset:
+ document.getElementById('mainKeyset').appendChild(keyNode);
+ }
+ },
+
+ getFormattedShortcut: function(shortcut) {
+ var formattedShortcut = '';
+ // Add the modifiers:
+ for(var i=0; i < shortcut.modifiers.length; i++) {
+ try {
+ formattedShortcut += this.getStringBundle().getString(shortcut.modifiers[i]) + '+';
+ } catch(e) {
+ // Error in shortcut string, return empty String;
+ return '';
+ }
+ }
+ if(shortcut.key) {
+ // Add the key:
+ if(shortcut.key == ' ') {
+ formattedShortcut += this.getStringBundle().getString('VK_SPACE');
+ } else {
+ formattedShortcut += shortcut.key;
+ }
+ } else if(shortcut.keycode) {
+ // Add the keycode (instead of the key):
+ try {
+ formattedShortcut += this.getStringBundle().getString(shortcut.keycode);
+ } catch(e) {
+ formattedShortcut += shortcut.keycode.replace('VK_', '');
+ }
+ }
+ return formattedShortcut;
+ },
+
+ replaceDynamicTags: function(fieldRuleValue) {
+ // Replace all dynamic tags with the return values of their associated tag codes:
+ for(var j=0; j<this.getDynamicTags().length; j++) {
+ // Catch if the number of tags doesn't match the number of tag codes or if the tag code is invalid:
+ try {
+ var regExpObj = new RegExp(this.getDynamicTags()[j],'g');
+ // We use eval() here without restrictions - the given tagCode must be trusted:
+ fieldRuleValue = fieldRuleValue.replace(regExpObj, eval(this.getDynamicTagCodes()[j]));
+ } catch(e) {
+ this.log(e);
+ }
+ }
+ return fieldRuleValue;
+ },
+
+ getDynamicTagsFile: function() {
+ var file = this.getConfigDirectory();
+ file.append('dynamicTags.txt');
+ if(!file.exists()) {
+ file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
+ }
+ return file;
+ },
+
+ exportDynamicTagsToConfigDirectory: function() {
+ var prefString;
+ // Get the dynamicTags string from the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ if(prefString) {
+ this.setFileContent(this.getDynamicTagsFile(), prefString);
+ }
+ },
+
+ importDynamicTagsFromConfigDirectory: function() {
+ var prefString;
+ prefString = this.getFileContent(this.getDynamicTagsFile());
+ if(prefString) {
+ // Store the dynamicTags as unicode string in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'dynamicTags',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getDynamicTags: function() {
+ if(this.dynamicTags == null) {
+ var prefString;
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Get the dynamicTags string from the dynamicTags file in the configDirectory:
+ prefString = this.getFileContent(this.getDynamicTagsFile());
+ }
+ if(!prefString) {
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ }
+ this.dynamicTags = prefString.split('\t');
+ }
+ return this.dynamicTags;
+ },
+
+ setDynamicTags: function(dynamicTags) {
+ // Save the dynamic tags separated by tabs:
+ var prefString = dynamicTags.join('\t');
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ this.setFileContent(this.getDynamicTagsFile(), prefString);
+ } else {
+ this.autofillFormsPrefs.setComplexValue(
+ 'dynamicTags',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getDynamicTagCodesFile: function() {
+ var file = this.getConfigDirectory();
+ file.append('dynamicTagCodes.txt');
+ if(!file.exists()) {
+ file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
+ }
+ return file;
+ },
+
+ exportDynamicTagCodesToConfigDirectory: function() {
+ var prefString;
+ // Get the dynamicTagCodes string from the preferences:
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ if(prefString) {
+ this.setFileContent(this.getDynamicTagCodesFile(), prefString);
+ }
+ },
+
+ importDynamicTagCodesFromConfigDirectory: function() {
+ var prefString;
+ prefString = this.getFileContent(this.getDynamicTagCodesFile());
+ if(prefString) {
+ // Store the dynamicTagCodes as unicode string in the preferences:
+ this.autofillFormsPrefs.setComplexValue(
+ 'dynamicTagCodes',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ getDynamicTagCodes: function() {
+ if(this.dynamicTagCodes == null) {
+ var prefString;
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Get the dynamicTagCodes string from the dynamicTagCodes file in the configDirectory:
+ prefString = this.getFileContent(this.getDynamicTagCodesFile());
+ }
+ if(!prefString) {
+ prefString = this.autofillFormsPrefs
+ .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
+ .data;
+ }
+ this.dynamicTagCodes = prefString.split('\t');
+ }
+ return this.dynamicTagCodes;
+ },
+
+ setDynamicTagCodes: function(dynamicTagCodes) {
+ // Save the dynamic tag codes separated by tabs:
+ var prefString = dynamicTagCodes.join('\t');
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ this.setFileContent(this.getDynamicTagCodesFile(), prefString);
+ } else {
+ this.autofillFormsPrefs.setComplexValue(
+ 'dynamicTagCodes',
+ Components.interfaces.nsISupportsString,
+ this.getUnicodeString(prefString)
+ );
+ }
+ },
+
+ optionsInitialize: function() {
+ // Save the reference to the Autofill Forms preferences branch:
+ this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
+
+ // Initialize the profile lists:
+ this.initProfilesLists();
+ // Initialize the fieldRules tree:
+ this.initTree();
+ // Initialize the simple interface:
+ this.initSimpleInterface();
+
+ // Sort is to be ascending if clicked first:
+ this.ascending = true;
+ this.profilesAscending = true;
+
+ var configDirectoryTextbox = document.getElementById('configDirectoryTextBox');
+ if(configDirectoryTextbox && this.autofillFormsPrefs.prefHasUserValue('configDirectory')) {
+ var configDirectory = this.getConfigDirectory();
+ if(configDirectory) {
+ configDirectoryTextbox.value = configDirectory.path;
+ }
+ }
+
+ // Initialize the keyboard shortcut objects:
+ this.shortcut = new Object();
+ this.shortcut['shortcut'] = null;
+ this.shortcut['shortcutSubmit'] = null;
+ this.shortcut['shortcutAllTabs'] = null;
+ this.shortcut['shortcutFromProfileSelection'] = null;
+ this.shortcut['shortcutProfile'] = null;
+ this.shortcut['shortcutSettings'] = null;
+ this.shortcut['shortcutDisplayFormDetails'] = null;
+
+ // Display the shortcut combinations:
+ for(var property in this.shortcut) {
+ if(document.getElementById(property)) {
+ document.getElementById(property).value = this.getFormattedShortcut(this.getShortcut(property));
+ }
+ }
+
+ // Initialize the mouse button objects:
+ this.mouseButton = new Object();
+ this.mouseButton['mouseShortcut'] = null;
+ this.mouseButton['mouseShortcutSubmit'] = null;
+ this.mouseButton['mouseShortcutAllTabs'] = null;
+ this.mouseButton['mouseShortcutFromProfileSelection'] = null;
+ this.mouseButton['mouseShortcutProfile'] = null;
+ this.mouseButton['mouseShortcutSettings'] = null;
+ this.mouseButton['mouseShortcutDisplayFormDetails'] = null;
+
+ // Display the mouse button combinations:
+ for(var property in this.mouseButton) {
+ if(document.getElementById(property)) {
+ document.getElementById(property).value = this.getFormattedMouseButton(this.getMouseButton(property));
+ }
+ }
+
+ // Parse the window params (e.g. initializing the target form field values):
+ this.parseOptionsWindowParams();
+ },
+
+ initSimpleInterface: function() {
+ var rows = document.getElementById('simpleInterfaceRows');
+ if(rows) {
+ while(rows.hasChildNodes()) {
+ rows.removeChild(rows.firstChild);
+ }
+ for(var i=0; i<this.getFieldRules().length; i++) {
+ // Only show enabled fieldRules:
+ if(!this.getFieldRules()[i]['fieldRuleEnabled']) {
+ continue;
+ }
+ rows.appendChild(
+ this.getSimpleInterfaceRow(
+ i,
+ this.getFieldRules()[i]['fieldRuleName'],
+ this.getFieldRules()[i]['fieldRuleValue']
+ )
+ );
+ }
+ }
+ },
+
+ addSimpleInterfaceRow: function(index) {
+ var row = this.getSimpleInterfaceRow(
+ index,
+ this.getFieldRules()[index]['fieldRuleName'],
+ this.getFieldRules()[index]['fieldRuleValue']
+ )
+ var rows = document.getElementById('simpleInterfaceRows');
+ if(rows) {
+ var nextSibling;
+ if(rows.childNodes) {
+ for(var i=index+1; i<rows.childNodes.length; i++) {
+ nextSibling = document.getElementById('simpleInterfaceRow_'+i);
+ if(nextSibling) {
+ rows.insertBefore(row, nextSibling);
+ break;
+ }
+ }
+ }
+ if(!nextSibling) {
+ rows.appendChild(row);
+ }
+ }
+ },
+
+ removeSimpleInterfaceRow: function(index) {
+ var row = document.getElementById('simpleInterfaceRow_'+index);
+ if(row) {
+ row.parentNode.removeChild(row);
+ }
+ },
+
+ getSimpleInterfaceRow: function(index, name, value) {
+ if(!arguments.callee.row) {
+ arguments.callee.row = document.createElement('row');
+ arguments.callee.row.setAttribute('align', 'center');
+ var label = document.createElement('label');
+ var textbox = document.createElement('textbox');
+ textbox.setAttribute('newlines', 'pasteintact');
+ arguments.callee.row.appendChild(label);
+ arguments.callee.row.appendChild(textbox);
+ }
+ var row = arguments.callee.row.cloneNode(true);
+ row.setAttribute('id', 'simpleInterfaceRow_'+index);
+ row.firstChild.setAttribute('value', name+':');
+ row.firstChild.setAttribute('id', 'simpleInterfaceLabel_'+index);
+ row.firstChild.setAttribute('control', 'simpleInterfaceTextbox_'+index);
+ row.lastChild.setAttribute('id', 'simpleInterfaceTextbox_'+index);
+ row.lastChild.setAttribute('value', value);
+ row.lastChild.addEventListener('change', function (){
+ autofillForms.applySimpleInterfaceValue(this);
+ }, false);
+ row.lastChild.addEventListener('input', function () {
+ this.value = autofillForms.replaceControlCharacters(this.value);
+ }, false);
+
+ // Is textbox a password field?
+ if(this.getRegExpPasswordLabel().test(name)) {
+ row.lastChild.setAttribute('type', 'password');
+ }
+ return row;
+ },
+
+ applySimpleInterfaceValue: function(textBox) {
+ // See method selectedFieldRule() why this has to be set to null:
+ this.lastSelectedIndex = null;
+
+ var index = parseInt(textBox.getAttribute('id').split('_')[1]);
+ this.getFieldRules()[index]['fieldRuleValue'] = this.makeSafe(textBox.value);
+
+ // Notify the tree (of the advanced interface):
+ try {
+ this.treeBox.invalidateRow(index);
+ } catch(e) {
+ }
+
+ // Update the preferences:
+ this.setFieldRules();
+ },
+
+ updateSimpleInterfaceRow: function(index) {
+ var row = document.getElementById('simpleInterfaceRow_'+index);
+ if(row) {
+ row.firstChild.value = this.getFieldRules()[index]['fieldRuleName']+':';
+ row.lastChild.value = this.getFieldRules()[index]['fieldRuleValue'];
+ // Is textbox a password field?
+ if(this.getRegExpPasswordLabel().test(this.getFieldRules()[index]['fieldRuleName'])) {
+ row.lastChild.setAttribute('type', 'password');
+ } else {
+ row.lastChild.removeAttribute('type');
+ }
+ }
+ },
+
+ getFieldRuleNameForElement: function(element) {
+ // Use the form field label as name if available:
+ var labelValue = this.getLabelForElement(element);
+ // Remove the colon, if present:
+ if(labelValue && labelValue.charAt(labelValue.length-1) == ':') {
+ labelValue = labelValue.substr(0, labelValue.length-1);
+ }
+ // If no label could be found, use the name or the id with the first character in upper case:
+ if(!labelValue) {
+ labelValue = element.name;
+ if(!labelValue) {
+ labelValue = element.id;
+ }
+ if(labelValue) {
+ labelValue = labelValue.charAt(0).toUpperCase() + labelValue.substr(1);
+ }
+ }
+ return labelValue;
+ },
+
+ getRegExpStrForValue: function(value) {
+ try {
+ // Remove unsave characters, escape regexp characters and return the regexp string:
+ return this.getRegExpStr('(?:^'+this.escapeRegExp(this.makeSafe(value))+'$)');
+ } catch(e) {
+ // If an error occurs, return the safe value string.
+ // If using it as regular expression fails a simple string comparison is used:
+ return this.makeSafe(value);
+ }
+ },
+
+ getFieldRuleForElement: function(element) {
+ var name = element.name;
+ // If no name is available use the label as fallback:
+ if(!name) {
+ name = this.getLabelForElement(element);
+ }
+ // If no name and no label is available use the id as fallback:
+ if(!name) {
+ name = element.id;
+ }
+ try {
+ // Remove unsave characters, escape regexp characters and return the regexp string:
+ return this.getRegExpStr('(?:^'+this.escapeRegExp(this.makeSafe(name))+'$)');
+ } catch(e) {
+ // If an error occurs, return an always matching regexp string:
+ return '(?:)';
+ }
+ },
+
+ getSiteRuleForURL: function(url) {
+ try {
+ // Remove unsave characters, escape regexp characters and return the regexp string:
+ return this.getRegExpStr('(?:^'+this.escapeRegExp(this.makeSafe(url))+')');
+ } catch(e) {
+ // If an error occurs, return an always matching regexp string:
+ return '(?:)';
+ }
+ },
+
+ parseOptionsWindowParams: function() {
+ // Check the windows arguments:
+ if(window.arguments && window.arguments[0]) {
+ if(window.arguments[0].targetFormField) {
+ var formFieldObject = window.arguments[0].targetFormField;
+
+ var value;
+ switch(formFieldObject.type) {
+ case 'checkbox':
+ case 'radio':
+ case 'select-one':
+ case 'select-multiple':
+ value = this.getRegExpStrForValue(formFieldObject.value);
+ break;
+ default:
+ value = this.replaceControlCharacters(formFieldObject.value);
+ break;
+ }
+
+ var location = this.getDoc().location;
+
+ // Reset the targetFormField of the autofillForms object referenced by window.arguments[0]:
+ window.arguments[0].targetFormField = null;
+
+ // Set the textbox values using the form field properties and the current document location:
+ document.getElementById('fieldRuleNameTextBox').value
+ = this.getFieldRuleNameForElement(formFieldObject)
+ + (location.hostname ? ' - ' + location.hostname : '');
+ document.getElementById('fieldRuleValueTextBox').value = value;
+ document.getElementById('fieldRuleFieldRuleTextBox').value
+ = this.getFieldRuleForElement(formFieldObject);
+ document.getElementById('fieldRuleSiteRuleTextBox').value
+ = this.getSiteRuleForURL(location.protocol + '//' + location.host);
+
+ // Make sure the main pane is selected:
+ document.getElementById('autofillFormsPrefs').showPane(
+ document.getElementById('autofillFormsPrefPaneMain')
+ );
+
+ // Set the focus to the name field:
+ document.getElementById('fieldRuleNameTextBox').focus();
+ } else if(window.arguments[0].newProfileFromForm) {
+ // Make sure the main pane is selected:
+ document.getElementById('autofillFormsPrefs').showPane(
+ document.getElementById('autofillFormsPrefPaneMain')
+ );
+ }
+ }
+ },
+
+ optionsFinalize: function() {
+ },
+
+ showProfileSwitcher: function() {
+ if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
+ // Always retrieve the profile labels from file if useConfigDirectory is enabled:
+ this.profileLabels = null;
+ }
+ // The nsIPromptService select() method doesn't offer to set a preselection,
+ // so we switch the current profile label with the first item (which is selected by default):
+ var list;
+ var currentIndex = this.getProfileIndex();
+ if(currentIndex != 0) {
+ // Copy the profilLabels array (so we don't change the original):
+ list = new Array().concat(this.getProfileLabels());
+ // Switch the current profile label with the first item:
+ var tmp = list[0];
+ list[0] = list[currentIndex];
+ list[currentIndex] = tmp;
+ } else {
+ // Set the list to the profilLabels reference if it is not to be changed:
+ list = this.getProfileLabels();
+ }
+ var selected = {};
+ // Show the selection prompt:
+ var ok = this.getPrompts().select(
+ window,
+ this.getStringBundle().getString('profileSelectionWindowTitle'),
+ this.getStringBundle().getString('profileSelectionPrompt'),
+ list.length,
+ list,
+ selected
+ );
+ if(ok) {
+ // If nothing changed, return:
+ if(selected.value == 0)
+ return;
+ // If the currentIndex has been selected and is not 0, it is in fact the index 0:
+ if(currentIndex != 0 && selected.value == currentIndex)
+ selected.value = 0;
+ // Set the profile index to the selected one:
+ this.setProfileIndex(selected.value)
+ }
+ },
+
+ showDialog: function(url, params) {
+ if (this.currentDialogs == null) {
+ this.currentDialogs = new Object();
+ }
+
+ // Is the window already
+ var win = this.currentDialogs[url];
+ if (win == null || win.closed)
+ {
+ var paramObject = params ? params : this;
+ win = window.openDialog(
+ url,
+ '',
+ 'chrome=yes,resizable=yes,toolbar=yes,centerscreen=yes,modal=no,dependent=no,dialog=no',
+ paramObject
+ );
+
+ this.currentDialogs[url] = win;
+ return win;
+ } else {
+ win.focus();
+ }
+ },
+
+ inArray: function(array, item) {
+ var i = array.length;
+ while(i--)
+ if(array[i] === item)
+ return true;
+ return false;
+ },
+
+ displayFormDetails: function() {
+ this.searchAndDisplayFormDetails(this.getWin());
+ },
+
+ searchAndDisplayFormDetails: function(win) {
+ win = win ? win : this.getWin();
+
+ var doc = this.getDoc(win);
+
+ // Check if any web forms are available on the current window:
+ if(doc && doc.forms && doc.forms.length > 0) {
+
+ // Go through the forms:
+ for(var i = 0; i < doc.forms.length; i++) {
+
+ // The form elements list:
+ var elements = doc.forms[i].elements;
+
+ // Go through the form elements:
+ for(var j = 0; j < elements.length; j++) {
+ this.displayFormElementDetails(elements[j], j, i, doc);
+ }
+ }
+ }
+
+ // Recursive call for all subframes:
+ for(var f=0; f < win.frames.length; f++) {
+ this.searchAndDisplayFormDetails(win.frames[f]);
+ }
+ },
+
+ isValidFormField: function(element) {
+ // ignore disabled (and return false) only if 'ignore disabled fields' is ticked
+ if(element.disabled && this.autofillFormsPrefs.getBoolPref('ignoreDisabledFields')) {
+ return false;
+ }
+ if(!arguments.callee.regExpFormFieldType) {
+ arguments.callee.regExpFormFieldType = new RegExp(
+ this.autofillFormsPrefs.getCharPref('regExpFormFieldTypes')
+ );
+ }
+ return arguments.callee.regExpFormFieldType.test(element.type);
+ },
+
+ displayFormElementDetails: function(element, elementNumber, formNumber, doc) {
+ // Create a unique id for the form element:
+ var id = 'autofillForms-f' + formNumber + '-e' + elementNumber;
+
+ // Remove the form details node if already present
+ // (nodeType 1 is an element node):
+ if(element.nextSibling && element.nextSibling.nodeType == 1 && element.nextSibling.getAttribute('id') == id) {
+ element.parentNode.removeChild(element.nextSibling);
+ return;
+ }
+
+ // Only display valid form fields:
+ if(this.isValidFormField(element)) {
+ // Create a "span" node with element details:
+ var text;
+ // Display the element name if available, else the element id if available, else an empty name:
+ if(element.name || !element.id) {
+ text = 'name="' + element.name;
+ } else {
+ text = 'id="' + element.id;
+ }
+ // Display the element value:
+ text += '" value="' + element.value + '"';
+ var span = doc.createElement('span');
+ span.setAttribute('id', id);
+ span.setAttribute('style', this.autofillFormsPrefs.getCharPref('formDetailsStyle'));
+ span.setAttribute('title', text);
+ span.appendChild(doc.createTextNode(text));
+
+ // Insert the form details node after the element:
+ if(element.nextSibling)
+ element.parentNode.insertBefore(span, element.nextSibling);
+ else
+ element.parentNode.appendChild(span);
+ }
+ },
+
+ ruleEditorInitialize: function() {
+ // Save the reference to the Autofill Forms preferences branch:
+ this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
+
+ if(window.arguments && window.arguments[0] && window.arguments[0].attributes) {
+ this.currentRuleField = window.arguments[0];
+ }
+
+ // Initialize the ruleElementTypes:
+ this.ruleElementTypes = new Array();
+ this.ruleElementTypes.push('contains');
+ this.ruleElementTypes.push('beginsWith');
+ this.ruleElementTypes.push('endsWith');
+ this.ruleElementTypes.push('equals');
+
+ // If the rule editor is used to edit the site rule, add two predefined protocol rules:
+ if(this.currentRuleField && this.currentRuleField.id && this.currentRuleField.id.indexOf('SiteRule') != -1) {
+ this.ruleEditorAdd('beginsWith', 'http:\/\/');
+ this.ruleEditorAdd('beginsWith', 'https:\/\/');
+ } else {
+ this.ruleEditorAdd();
+ }
+ },
+
+ ruleEditorSave: function() {
+ if(document.getElementById('ruleElementsList')) {
+ var str = '';
+ var richlistbox = document.getElementById('ruleElementsList');
+ var richlistitems = richlistbox.getElementsByTagName('richlistitem');
+ var menulists,textboxes;
+
+ // Go through the richlistbox items:
+ for(var i=0; i<richlistitems.length; i++) {
+ // Link the conditions as disjunctions (OR-Relations);
+ if(str.length != 0)
+ str += '|';
+ menulists = richlistitems[i].getElementsByTagName('menulist');
+ textboxes = richlistitems[i].getElementsByTagName('textbox');
+
+ // Add the current condition to the string:
+ switch(menulists[0].selectedItem.value) {
+ case 'contains':
+ str += '(?:' + textboxes[0].value + ')';
+ break;
+ case 'beginsWith':
+ str += '(?:^' + textboxes[0].value + ')';
+ break;
+ case 'endsWith':
+ str += '(?:' + textboxes[0].value + '$)';
+ break;
+ case 'equals':
+ str += '(?:^' + textboxes[0].value + '$)';
+ break;
+ }
+ }
+ if(this.currentRuleField) {
+ // Set the current field value to the created string:
+ this.currentRuleField.value = str;
+ // Call the onchange handler:
+ if(this.currentRuleField.onchange) {
+ this.currentRuleField.onchange();
+ }
+ // Call the focus handler:
+ if(this.currentRuleField.focus) {
+ this.currentRuleField.focus();
+ }
+ }
+ }
+ return true;
+ },
+
+ ruleEditorAdd: function(type, ruleElement) {
+ if(document.getElementById('ruleElementsList')) {
+ var richlistbox = document.getElementById('ruleElementsList');
+
+ var richlistitem,menulist,menupopup,menuitem,textbox,label;
+
+ richlistitem = document.createElement('richlistitem');
+
+ // Create the condition type menu:
+ menulist = document.createElement('menulist');
+ menupopup = document.createElement('menupopup');
+
+ var selectedIndex = 0;
+
+ // Create the menu of ruleElementTypes:
+ for(var i=0; i<this.ruleElementTypes.length; i++) {
+ menuitem = document.createElement('menuitem');
+ menuitem.setAttribute(
+ 'value',
+ this.ruleElementTypes[i]
+ );
+ menuitem.setAttribute(
+ 'label',
+ this.getStringBundle().getString(this.ruleElementTypes[i] + 'RuleType')
+ );
+ menupopup.appendChild(menuitem);
+
+ // Set the selectedIndex:
+ if(type != null && type == this.ruleElementTypes[i])
+ selectedIndex = i;
+ }
+
+ menulist.appendChild(menupopup);
+ richlistitem.appendChild(menulist);
+
+ // Create the textbox:
+ textbox = document.createElement('textbox');
+ if(ruleElement != null)
+ textbox.setAttribute('value',ruleElement);
+ textbox.setAttribute('flex','1');
+ richlistitem.appendChild(textbox);
+
+ richlistbox.appendChild(richlistitem);
+
+ // Select the menuitem:
+ menulist.selectedIndex = selectedIndex;
+ }
+ },
+
+ ruleEditorRemove: function(index) {
+ var ruleElementsList = document.getElementById('ruleElementsList');
+ if(ruleElementsList) {
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ // Confirmation dialog:
+ if(!this.getPrompts().confirm(
+ null,
+ this.getStringBundle().getString('removeRuleConditionTitle'),
+ this.getStringBundle().getString('removeRuleConditionText')
+ )
+ ) {
+ return;
+ }
+ }
+
+ var richlistbox = ruleElementsList;
+ if(index)
+ richlistbox.selectedIndex = index;
+ if(richlistbox.selectedItem && richlistbox.selectedIndex != -1)
+ richlistbox.removeChild(richlistbox.selectedItem);
+ }
+ },
+
+ ruleEditorIsTextBoxFocused: function() {
+ return this.ruleEditorTextBoxFocused;
+ },
+
+ ruleEditorFocus: function() {
+ var focusedElement = document.commandDispatcher.focusedElement;
+
+ // Monitor if a textbox is focused:
+ if(!this.ruleEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'html:input') {
+ this.ruleEditorTextBoxFocused = true;
+ } else if(this.ruleEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'richlistbox') {
+ this.ruleEditorTextBoxFocused = false;
+ }
+ },
+
+ ruleEditorHandleKeyPress: function(event) {
+ // Only remove a dynamic tag on delete key press if no textbox is focused:
+ if(event.keyCode == 46 && !this.ruleEditorIsTextBoxFocused()) {
+ this.ruleEditorRemove();
+ }
+ },
+
+ ruleEditorFinalize: function() {
+ this.currentRuleField = null;
+ },
+
+ tagEditorInitialize: function() {
+ // Save the reference to the Autofill Forms preferences branch:
+ this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
+
+ // Add existing tags to the list:
+ for(var i=0; i<this.getDynamicTags().length; i++) {
+ // Catch if the number of tags doesn't match the number of tag codes:
+ try {
+ this.tagEditorAdd(this.getDynamicTags()[i],this.getDynamicTagCodes()[i])
+ } catch(e) {
+ this.log(e);
+ }
+ }
+ },
+
+ tagEditorSave: function() {
+ var richlistbox = document.getElementById('tagList');
+ if(richlistbox) {
+ var richlistitems = richlistbox.getElementsByTagName('richlistitem');
+ var textboxes;
+
+ var dynamicTags = new Array();
+ var dynamicTagCodes = new Array();
+
+ // Go through the richlistbox items:
+ for(var i=0; i<richlistitems.length; i++) {
+ textboxes = richlistitems[i].getElementsByTagName('textbox');
+
+ // Add the dynamic tags and their associated tag codes to the lists:
+ if (textboxes[0].value != '' && textboxes[1].value != '') {
+ dynamicTags.push(this.makeSafe(textboxes[0].value));
+ dynamicTagCodes.push(this.makeSafe(textboxes[1].value));
+ }
+ }
+ // Save the lists in the preferences:
+ this.setDynamicTags(dynamicTags);
+ this.setDynamicTagCodes(dynamicTagCodes);
+ }
+ return true;
+ },
+
+ tagEditorAdd: function(tag, tagCode) {
+ var richlistbox = document.getElementById('tagList');
+ if(richlistbox) {
+ var richlistitem,textbox;
+
+ richlistitem = document.createElement('richlistitem');
+
+ // Create the tag textbox:
+ textbox = document.createElement('textbox');
+ textbox.setAttribute('class','tag');
+ if(tag != null)
+ textbox.setAttribute('value',tag);
+ richlistitem.appendChild(textbox);
+
+ // Create the tagCode textbox:
+ textbox = document.createElement('textbox');
+ textbox.setAttribute('class','tagCode');
+ textbox.setAttribute('flex','1');
+ if(tagCode != null)
+ textbox.setAttribute('value',tagCode);
+ richlistitem.appendChild(textbox);
+
+ richlistbox.appendChild(richlistitem);
+ }
+ },
+
+ tagEditorRemove: function(index) {
+ var richlistbox = document.getElementById('tagList');
+ if(richlistbox) {
+ if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
+ // Confirmation dialog:
+ if(!this.getPrompts().confirm(
+ null,
+ this.getStringBundle().getString('removeDynamicTagTitle'),
+ this.getStringBundle().getString('removeDynamicTagText')
+ )
+ ) {
+ return;
+ }
+ }
+ if(index)
+ richlistbox.selectedIndex = index;
+ if(richlistbox.selectedItem && richlistbox.selectedIndex != -1)
+ {
+ richlistbox.removeChild(richlistbox.selectedItem);
+ }
+ }
+ },
+
+ tagEditorValidate: function(index) {
+ var richlistbox = document.getElementById('tagList');
+ if(richlistbox) {
+ if(index)
+ richlistbox.selectedIndex = index;
+ if(richlistbox.selectedItem) {
+ var tagCode = richlistbox.selectedItem.lastChild.value;
+ var validationResultTextBox = document.getElementById('validationResultTextBox');
+ try {
+ validationResultTextBox.removeAttribute('style');
+ // We use eval() here without restrictions - the given tagCode must be trusted:
+ validationResultTextBox.value = eval(tagCode);
+ } catch(e) {
+ validationResultTextBox.setAttribute('style', 'color:red;');
+ validationResultTextBox.value = e;
+ }
+ }
+ }
+ },
+
+ tagEditorIsTextBoxFocused: function() {
+ return this.tagEditorTextBoxFocused;
+ },
+
+ tagEditorFocus: function() {
+ var focusedElement = document.commandDispatcher.focusedElement;
+
+ // Monitor if a textbox is focused:
+ if(!this.tagEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'html:input') {
+ this.tagEditorTextBoxFocused = true;
+ } else if(this.tagEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'richlistbox') {
+ this.tagEditorTextBoxFocused = false;
+ }
+ },
+
+ tagEditorHandleKeyPress: function(event) {
+ // Only remove a dynamic tag on delete key press if no textbox is focused:
+ if(event.keyCode == 46 && !this.tagEditorIsTextBoxFocused()) {
+ this.tagEditorRemove();
+ }
+ },
+
+ tagEditorFinalize: function() {
+ },
+
+ openHelp: function(topic) {
+ if(!topic) {
+ topic = '';
+ }
+ var url = this.autofillFormsPrefs.getCharPref('helpURL').replace(/\[TOPIC\]$/, topic);
+ this.openNewTab(url, true);
+ },
+
+ openNewTab: function(url, focus) {
+ var helpTab = this.getBrowser().addTab(url);
+ if(focus) {
+ this.getBrowser().selectedTab = helpTab;
+ this.getWindowMediator().getMostRecentWindow('navigator:browser').focus();
+ }
+ },
+
+ addLeadingZeros: function(number, length) {
+ number = number.toString();
+ while(number.length < length) {
+ number = '0'+number;
+ }
+ return number;
+ },
+
+ escapeRegExp: function(str) {
+ if (!arguments.callee.regExp) {
+ var specials = new Array(
+ '^', '$', '*', '+', '?', '.', '|', '/',
+ '(', ')', '[', ']', '{', '}', '\\'
+ );
+ arguments.callee.regExp = new RegExp(
+ '(\\' + specials.join('|\\') + ')', 'g'
+ );
+ }
+ return str.replace(arguments.callee.regExp, '\\$1');
+ },
+
+ getClipboardText: function() {
+ var clipboardText = null;
+ var clip = Components.classes['@mozilla.org/widget/clipboard;1']
+ .getService(Components.interfaces.nsIClipboard);
+ if(!clip) {
+ return null;
+ }
+
+ var trans = Components.classes['@mozilla.org/widget/transferable;1']
+ .createInstance(Components.interfaces.nsITransferable);
+ if(!trans) {
+ return null;
+ }
+
+ trans.addDataFlavor('text/unicode');
+
+ clip.getData(trans, clip.kGlobalClipboard);
+
+ var str = new Object();
+ var strLength = new Object();
+
+ trans.getTransferData('text/unicode', str, strLength);
+
+ if(str) {
+ str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
+ }
+ if(str) {
+ clipboardText = str.data.substring(0, strLength.value / 2);
+ }
+
+ return clipboardText
+ },
+
+ getMasterSecurityDevice: function() {
+ return Components.classes['@mozilla.org/security/pk11tokendb;1']
+ .getService(Components.interfaces.nsIPK11TokenDB);
+ },
+
+ log: function(aMessage, aSourceName, aSourceLine, aLineNumber, aColumnNumber, aFlags, aCategory) {
+ var consoleService = Components.classes['@mozilla.org/consoleservice;1']
+ .getService(Components.interfaces.nsIConsoleService);
+ if(aSourceName != 'undefined') {
+ var scriptError = Components.classes["@mozilla.org/scripterror;1"]
+ .createInstance(Components.interfaces.nsIScriptError);
+ scriptError.init(
+ aMessage,
+ aSourceName,
+ aSourceLine,
+ aLineNumber,
+ aColumnNumber,
+ aFlags,
+ aCategory
+ );
+ consoleService.logMessage(scriptError);
+ } else {
+ consoleService.logStringMessage(aMessage);
+ }
+ },
+
+ finalizeToolbarButtonStatus: function() {
+ var autofillFormsButton = document.getElementById('autofillFormsButton');
+ var hideToolbarButton = this.autofillFormsPrefs.getBoolPref('hideToolbarButton');
+ if(!autofillFormsButton && !hideToolbarButton) {
+ // If the toolbar button icon has been removed from the toolbar by drag&drop
+ // enable the hideToolbarButton setting:
+ this.autofillFormsPrefs.setBoolPref('hideToolbarButton', true);
+ } else if(autofillFormsButton && !autofillFormsButton.getAttribute('hidden')) {
+ // If the toolbar button icon has been added to the toolbar by drag&drop
+ // disable the hideToolbarButton setting:
+ this.autofillFormsPrefs.setBoolPref('hideToolbarButton', false);
+ }
+ },
+
+ finalize: function() {
+ this.finalizeToolbarButtonStatus();
+
+ // Remove the content area context menu listener:
+ var contentAreaContextMenu = document.getElementById('contentAreaContextMenu');
+ if(contentAreaContextMenu) {
+ contentAreaContextMenu.removeEventListener(
+ 'popupshowing',
+ this.contentAreaContextMenuEventListener,
+ false
+ );
+ }
+
+ // Remove the preferences Observer:
+ this.autofillFormsPrefs.removeObserver('', this);
+ }
+
+}
diff --git a/src/chrome/content/autofillFormsOptions.js b/chrome/content/autofillFormsOptions.js
similarity index 100%
rename from src/chrome/content/autofillFormsOptions.js
rename to chrome/content/autofillFormsOptions.js
diff --git a/src/chrome/content/autofillFormsOptions.xul b/chrome/content/autofillFormsOptions.xul
similarity index 92%
rename from src/chrome/content/autofillFormsOptions.xul
rename to chrome/content/autofillFormsOptions.xul
index 9645d36..89ea3df 100644
--- a/src/chrome/content/autofillFormsOptions.xul
+++ b/chrome/content/autofillFormsOptions.xul
@@ -13,15 +13,14 @@
<prefpane
id="autofillFormsPrefPaneSimple"
label="&prefpanesimplelabel;"
- flex="0"
- helpTopic="Simple Editor"
- style="overflow:auto;max-height:450px;">
+ flex="1"
+ helpTopic="Simple Editor">
<preferences>
</preferences>
<vbox flex="1">
<hbox align="center">
<menulist id="simpleInterfaceProfileMenuList" oncommand="autofillForms.setProfileIndex(this.selectedIndex);"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
</hbox>
<separator class="thin"/>
<vbox flex="1" id="simpleInterfaceRowsContainer" style="overflow:auto;max-height:450px;">
@@ -38,49 +37,48 @@
<prefpane
id="autofillFormsPrefPaneProfiles"
label="&prefpaneprofileslabel;"
- flex="0"
- helpTopic="Profiles"
- style="overflow:auto;min-height:475px;">
+ flex="1"
+ helpTopic="Profiles">
<preferences>
<preference id="autoSelectBestProfile" name="extensions.autofillForms at blueimp.net.autoSelectBestProfile" type="bool"/>
<preference id="enableGlobalProfile" name="extensions.autofillForms at blueimp.net.enableGlobalProfile" type="bool"/>
</preferences>
- <tabbox flex="0">
+ <tabbox flex="1">
<tabs>
<tab label="&prefpaneprofileslabel;"/>
<tab label="&prefpaneadvancedlabel;"/>
</tabs>
- <tabpanels flex="0">
- <vbox flex="0">
- <grid flex="0">
+ <tabpanels flex="1">
+ <vbox flex="1">
+ <grid flex="1">
<rows>
- <row align="center" flex="0"/>
+ <row align="center" flex="1"/>
<separator class="thin"/>
<row align="center"/>
</rows>
<columns>
- <column flex="0">
- <tree id="profilesTree" seltype="single" flex="0" enableColumnDrag="true" onkeypress="autofillForms.profilesTreeHandleKeyPress(event)" onselect="autofillForms.selectedProfile(event);">
+ <column flex="1">
+ <tree id="profilesTree" seltype="single" flex="1" enableColumnDrag="true" onkeypress="autofillForms.profilesTreeHandleKeyPress(event)" onselect="autofillForms.selectedProfile(event);">
<treecols>
- <treecol id="profilesTreeColName" label="&profilename.label;" flex="0" persist="width ordinal hidden" onclick="autofillForms.sortProfiles(event);"/>
+ <treecol id="profilesTreeColName" label="&profilename.label;" flex="1" persist="width ordinal hidden" onclick="autofillForms.sortProfiles(event);"/>
<splitter class="tree-splitter"/>
- <treecol id="profilesTreeColSiteRule" label="&profilesiterule.label;" flex="0" persist="width ordinal hidden" hidden="true" onclick="autofillForms.sortProfiles(event);"/>
+ <treecol id="profilesTreeColSiteRule" label="&profilesiterule.label;" flex="1" persist="width ordinal hidden" hidden="false" onclick="autofillForms.sortProfiles(event);"/>
</treecols>
<treechildren id="profilesTreeChildren" />
</tree>
<grid>
<columns>
<column/>
- <column flex="0"/>
+ <column flex="1"/>
</columns>
<rows>
<row align="center">
<label value="&profilename.label;:"/>
- <textbox id="profileLabelTextBox" flex="0"/>
+ <textbox id="profileLabelTextBox" flex="1"/>
</row>
<row align="center">
<label value="&profilesiterule.label;:"/>
- <textbox id="profileSiteRuleTextBox2" flex="0" onchange="autofillForms.changeProfileSiteRule(this.value);"/>
+ <textbox id="profileSiteRuleTextBox2" flex="1" onchange="autofillForms.changeProfileSiteRule(this.value);"/>
</row>
</rows>
</grid>
@@ -108,22 +106,22 @@
<button label="&profileimportbutton.label;" oncommand="autofillForms.importProfile();"/>
<button label="&profileexportallbutton.label;" oncommand="autofillForms.exportAllProfiles();"/>
<button label="&profileexportbutton.label;" oncommand="autofillForms.exportProfile();"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
</hbox>
</groupbox>
</vbox>
- <vbox flex="0" style="">
+ <vbox flex="1" style="">
<checkbox label="&autoselectbestprofile.label;" preference="autoSelectBestProfile"/>
<separator class="thin"/>
<hbox align="center">
<checkbox label="&enableglobalprofile.label;" preference="enableGlobalProfile"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
<menulist id="globalProfileMenuList" oncommand="autofillForms.setGlobalProfileIndex(this.selectedIndex);"/>
</hbox>
<separator class="thin"/>
<hbox align="center">
<label control="contextMenuProfileMenuList" value="&formfieldscontextmenu.label;"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
<menulist id="contextMenuProfileMenuList" oncommand="autofillForms.setFormFieldsContextMenuProfileIndex(this.selectedIndex-3);">
<menupopup>
<menuitem label="&formfieldscontextmenuitemallprofiles.label;"/>
@@ -135,28 +133,25 @@
</vbox>
</tabpanels>
</tabbox>
- <vbox style="height:550px;width:1px;">
- </vbox>
</prefpane>
<prefpane
id="autofillFormsPrefPaneMain"
label="&prefpanemainlabel;"
- flex="0"
- helpTopic="Advanced Editor"
- style="overflow:auto;min-height:475px;">
+ flex="1"
+ helpTopic="Advanced Editor">
<preferences>
</preferences>
- <vbox flex="0" id="autofillFormsPrefPaneMainBox" style="">
+ <vbox flex="1" id="autofillFormsPrefPaneMainBox" style="">
<grid>
<columns>
<column/>
- <column flex="0"/>
+ <column flex="1"/>
</columns>
<rows>
<row align="center">
<label value="&profile.label;"/>
<hbox align="center">
- <menulist id="profilesMenuList" editable="true" flex="0" oncommand="autofillForms.setProfileIndex(this.selectedIndex);"/>
+ <menulist id="profilesMenuList" editable="true" flex="1" oncommand="autofillForms.setProfileIndex(this.selectedIndex);"/>
<button id="buttonApplyProfile" label="&apply.label;" oncommand="autofillForms.changeProfileLabel(document.getElementById('profilesMenuList').inputField.value);"/>
<button id="buttonAddProfile" label="&add.label;" oncommand="autofillForms.addProfile(document.getElementById('profilesMenuList').inputField.value);"/>
<button id="buttonRemoveProfile" label="&remove.label;" oncommand="autofillForms.removeProfile(event);"/>
@@ -165,16 +160,16 @@
<row align="center">
<label value="&profilesiterule.label;:"/>
<hbox align="center">
- <textbox id="profileSiteRuleTextBox" flex="0" onchange="autofillForms.changeProfileSiteRule(this.value);"/>
+ <textbox id="profileSiteRuleTextBox" flex="1" onchange="autofillForms.changeProfileSiteRule(this.value);"/>
<button label="&ruleeditorbutton.label;" oncommand="autofillForms.showDialog('chrome://autofillForms/content/autofillFormsRuleEditor.xul', document.getElementById('profileSiteRuleTextBox'));"/>
</hbox>
</row>
</rows>
</grid>
<separator class="thin"/>
- <tree id="fieldRulesTree" seltype="multiple" flex="0" editable="true" enableColumnDrag="true" onkeypress="autofillForms.handleKeyPress(event)" onselect="autofillForms.selectedFieldRule(event);">
+ <tree id="fieldRulesTree" seltype="multiple" flex="1" editable="true" enableColumnDrag="true" onkeypress="autofillForms.handleKeyPress(event)" onselect="autofillForms.selectedFieldRule(event);">
<treecols>
- <treecol id="fieldRuleName" label="&fieldrulename.label;" flex="0" persist="width ordinal hidden" onclick="autofillForms.sortFieldRules(event);"/>
+ <treecol id="fieldRuleName" label="&fieldrulename.label;" flex="1" persist="width ordinal hidden" onclick="autofillForms.sortFieldRules(event);"/>
<splitter class="tree-splitter"/>
<treecol id="fieldRuleValue" label="&fieldrulevalue.label;" flex="2" persist="width ordinal hidden" onclick="autofillForms.sortFieldRules(event);"/>
<splitter class="tree-splitter"/>
@@ -192,7 +187,7 @@
<grid>
<columns>
<column/>
- <column flex="0"/>
+ <column flex="1"/>
<column/>
</columns>
<rows>
@@ -227,15 +222,12 @@
</rows>
</grid>
</vbox>
- <vbox style="height:550px;width:1px;">
- </vbox>
</prefpane>
<prefpane
id="autofillFormsPrefPaneAdvanced"
label="&prefpaneadvancedlabel;"
- flex="0"
- helpTopic="Settings"
- style="overflow:auto;min-height:475px;">
+ flex="1"
+ helpTopic="Settings">
<preferences>
<preference id="storeEncrypted" name="extensions.autofillForms at blueimp.net.storeEncrypted" type="bool"/>
<preference id="enableDynamicTags" name="extensions.autofillForms at blueimp.net.enableDynamicTags" type="bool"/>
@@ -253,24 +245,24 @@
<preference id="placeholderTab" name="extensions.autofillForms at blueimp.net.placeholderTab" type="unichar"/>
<preference id="useConfigDirectory" name="extensions.autofillForms at blueimp.net.useConfigDirectory" type="bool"/>
</preferences>
- <tabbox flex="0">
+ <tabbox flex="1">
<tabs>
<tab label="&prefpanemainlabel;"/>
<tab label="&prefpaneadvancedlabel;"/>
</tabs>
- <tabpanels flex="0">
- <vbox flex="0">
+ <tabpanels flex="1">
+ <vbox flex="1">
<groupbox>
<caption label="&securitycaption.label;"/>
<checkbox label="&storeencrypted.label;" preference="storeEncrypted"/>
</groupbox>
<separator class="thin"/>
- <groupbox flex="0">
+ <groupbox flex="1">
<caption label="&miscellaneous.label;"/>
- <vbox flex="0" style="overflow:auto;">
+ <vbox flex="1" style="overflow:auto;">
<hbox align="center">
<checkbox label="&tagsenable.label;" preference="enableDynamicTags"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
<button id="buttonEditTags" label="&tagsedit.label;" oncommand="autofillForms.showDialog('chrome://autofillForms/content/autofillFormsTagEditor.xul', null);"/>
</hbox>
<checkbox label="&ignoredisabledrulesonautofill.label;" preference="ignoreDisabledRulesOnAutofill"/>
@@ -283,17 +275,17 @@
<checkbox label="&callonchangeafterfillingfields.label;" preference="callOnChangeAfterFillingFields"/>
<hbox align="center">
<checkbox label="&matchagainstpositions.label;" preference="matchAgainstPositions"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
<textbox id="positionsIdentifierTextbox" preference="positionsIdentifier" class="placeholderTextbox"/>
</hbox>
<hbox align="center">
<label control="placeholderLineBreakTextbox" value="&placeholderlinebreak.label;"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
<textbox id="placeholderLineBreakTextbox" preference="placeholderLineBreak" class="placeholderTextbox"/>
</hbox>
<hbox align="center">
<label control="placeholderTabTextbox" value="&placeholdertab.label;"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
<textbox id="placeholderTabTextbox" preference="placeholderTab" class="placeholderTextbox"/>
</hbox>
</vbox>
@@ -304,36 +296,33 @@
<hbox>
<button label="&tagimportbutton.label;" oncommand="autofillForms.importDynamicTagsFromSettings();"/>
<button label="&tagexportbutton.label;" oncommand="autofillForms.exportDynamicTagsFromSettings();"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
</hbox>
</groupbox>
</vbox>
- <vbox flex="0">
+ <vbox flex="1">
<groupbox>
<caption label="&storagelocationcaption.label;"/>
<checkbox label="&useconfigdirectory.label;" preference="useConfigDirectory"/>
<hbox>
- <textbox id="configDirectoryTextBox" readonly="true" flex="0" />
+ <textbox id="configDirectoryTextBox" readonly="true" flex="1" />
<button label="&browsedir.label;" icon="open" oncommand="autofillForms.setConfigDirectory(document.getElementById('configDirectoryTextBox'));"/>
<button label="&resetdir.label;" icon="clear" oncommand="autofillForms.resetConfigDirectory(document.getElementById('configDirectoryTextBox'));"/>
</hbox>
<hbox>
<button label="&opendir.label;" icon="open" oncommand="autofillForms.openConfigDirectory();"/>
- <spacer flex="0"/>
+ <spacer flex="1"/>
</hbox>
</groupbox>
</vbox>
</tabpanels>
</tabbox>
- <vbox style="height:550px;width:1px;">
- </vbox>
</prefpane>
<prefpane
id="autofillFormsPrefPaneGUI"
label="&prefpaneguilabel;"
- flex="0"
- helpTopic="Interface"
- style="overflow:auto;min-height:475px;">
+ flex="1"
+ helpTopic="Interface">
<preferences>
<preference id="hideStatusbarIcon" name="extensions.autofillForms at blueimp.net.hideStatusbarIcon" type="bool"/>
<preference id="hideContextMenuItem" name="extensions.autofillForms at blueimp.net.hideContextMenuItem" type="bool"/>
@@ -345,14 +334,14 @@
<preference id="highlightStyleNoMatch" name="extensions.autofillForms at blueimp.net.highlightStyleNoMatch" type="unichar"/>
<preference id="formDetailsStyle" name="extensions.autofillForms at blueimp.net.formDetailsStyle" type="unichar"/>
</preferences>
- <tabbox flex="0">
+ <tabbox flex="1">
<tabs>
<tab label="&viewcaption.label;"/>
<tab label="&shortcutscaption.label;"/>
<tab label="&mousebuttonscaption.label;"/>
</tabs>
- <tabpanels flex="0">
- <vbox flex="0" style="">
+ <tabpanels flex="1">
+ <vbox flex="1" style="">
<checkbox label="&hidetoolbarbutton.label;" preference="hideToolbarButton"/>
<checkbox label="&hidetoolbarbuttonmenu.label;" preference="hideToolbarButtonMenu"/>
<checkbox label="&hidestatusbaricon.label;" preference="hideStatusbarIcon"/>
@@ -363,7 +352,7 @@
<grid>
<columns>
<column/>
- <column flex="0" minwidth="200"/>
+ <column flex="1" minwidth="200"/>
</columns>
<rows>
<row align="center">
@@ -381,11 +370,11 @@
</rows>
</grid>
</vbox>
- <vbox flex="0" style="">
+ <vbox flex="1" style="">
<grid>
<columns>
<column class="shortCutsLabelColumn"/>
- <column class="shortCutsKeyColumn" flex="0"/>
+ <column class="shortCutsKeyColumn" flex="1"/>
<column/>
</columns>
<rows>
@@ -485,11 +474,11 @@
<separator class="thin"/>
<description class="shortcutInfo">&shortcutinfo.label;</description>
</vbox>
- <vbox flex="0" style="">
+ <vbox flex="1" style="">
<grid>
<columns>
<column class="shortCutsLabelColumn"/>
- <column class="shortCutsKeyColumn" flex="0"/>
+ <column class="shortCutsKeyColumn" flex="1"/>
<column/>
<column/>
</columns>
@@ -613,8 +602,6 @@
</vbox>
</tabpanels>
</tabbox>
- <vbox style="height:550px;width:1px;">
- </vbox>
</prefpane>
<script
type="application/x-javascript"
diff --git a/src/chrome/content/autofillFormsOverlay.js b/chrome/content/autofillFormsOverlay.js
similarity index 100%
rename from src/chrome/content/autofillFormsOverlay.js
rename to chrome/content/autofillFormsOverlay.js
diff --git a/src/chrome/content/autofillFormsOverlay.xul b/chrome/content/autofillFormsOverlay.xul
similarity index 100%
rename from src/chrome/content/autofillFormsOverlay.xul
rename to chrome/content/autofillFormsOverlay.xul
diff --git a/src/chrome/content/autofillFormsRuleEditor.js b/chrome/content/autofillFormsRuleEditor.js
similarity index 100%
rename from src/chrome/content/autofillFormsRuleEditor.js
rename to chrome/content/autofillFormsRuleEditor.js
diff --git a/src/chrome/content/autofillFormsRuleEditor.xul b/chrome/content/autofillFormsRuleEditor.xul
similarity index 100%
rename from src/chrome/content/autofillFormsRuleEditor.xul
rename to chrome/content/autofillFormsRuleEditor.xul
diff --git a/src/chrome/content/autofillFormsTagEditor.js b/chrome/content/autofillFormsTagEditor.js
similarity index 100%
rename from src/chrome/content/autofillFormsTagEditor.js
rename to chrome/content/autofillFormsTagEditor.js
diff --git a/src/chrome/content/autofillFormsTagEditor.xul b/chrome/content/autofillFormsTagEditor.xul
similarity index 100%
rename from src/chrome/content/autofillFormsTagEditor.xul
rename to chrome/content/autofillFormsTagEditor.xul
diff --git a/src/chrome/locale/cs-CZ/autofillForms.dtd b/chrome/locale/cs-CZ/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/cs-CZ/autofillForms.dtd
rename to chrome/locale/cs-CZ/autofillForms.dtd
diff --git a/src/chrome/locale/cs-CZ/autofillForms.properties b/chrome/locale/cs-CZ/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/cs-CZ/autofillForms.properties
rename to chrome/locale/cs-CZ/autofillForms.properties
diff --git a/src/chrome/locale/de-DE/autofillForms.dtd b/chrome/locale/de-DE/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/de-DE/autofillForms.dtd
rename to chrome/locale/de-DE/autofillForms.dtd
diff --git a/src/chrome/locale/de-DE/autofillForms.properties b/chrome/locale/de-DE/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/de-DE/autofillForms.properties
rename to chrome/locale/de-DE/autofillForms.properties
diff --git a/src/chrome/locale/el-GR/autofillForms.dtd b/chrome/locale/el-GR/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/el-GR/autofillForms.dtd
rename to chrome/locale/el-GR/autofillForms.dtd
diff --git a/src/chrome/locale/el-GR/autofillForms.properties b/chrome/locale/el-GR/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/el-GR/autofillForms.properties
rename to chrome/locale/el-GR/autofillForms.properties
diff --git a/src/chrome/locale/en-US/autofillForms.dtd b/chrome/locale/en-US/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/en-US/autofillForms.dtd
rename to chrome/locale/en-US/autofillForms.dtd
diff --git a/src/chrome/locale/en-US/autofillForms.properties b/chrome/locale/en-US/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/en-US/autofillForms.properties
rename to chrome/locale/en-US/autofillForms.properties
diff --git a/src/chrome/locale/es-ES/autofillForms.dtd b/chrome/locale/es-ES/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/es-ES/autofillForms.dtd
rename to chrome/locale/es-ES/autofillForms.dtd
diff --git a/src/chrome/locale/es-ES/autofillForms.properties b/chrome/locale/es-ES/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/es-ES/autofillForms.properties
rename to chrome/locale/es-ES/autofillForms.properties
diff --git a/src/chrome/locale/fi-FI/autofillForms.dtd b/chrome/locale/fi-FI/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/fi-FI/autofillForms.dtd
rename to chrome/locale/fi-FI/autofillForms.dtd
diff --git a/src/chrome/locale/fi-FI/autofillForms.properties b/chrome/locale/fi-FI/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/fi-FI/autofillForms.properties
rename to chrome/locale/fi-FI/autofillForms.properties
diff --git a/src/chrome/locale/fr-FR/autofillForms.dtd b/chrome/locale/fr-FR/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/fr-FR/autofillForms.dtd
rename to chrome/locale/fr-FR/autofillForms.dtd
diff --git a/src/chrome/locale/fr-FR/autofillForms.properties b/chrome/locale/fr-FR/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/fr-FR/autofillForms.properties
rename to chrome/locale/fr-FR/autofillForms.properties
diff --git a/src/chrome/locale/he-IL/autofillForms.dtd b/chrome/locale/he-IL/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/he-IL/autofillForms.dtd
rename to chrome/locale/he-IL/autofillForms.dtd
diff --git a/src/chrome/locale/he-IL/autofillForms.properties b/chrome/locale/he-IL/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/he-IL/autofillForms.properties
rename to chrome/locale/he-IL/autofillForms.properties
diff --git a/src/chrome/locale/hr-HR/autofillForms.dtd b/chrome/locale/hr-HR/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/hr-HR/autofillForms.dtd
rename to chrome/locale/hr-HR/autofillForms.dtd
diff --git a/src/chrome/locale/hr-HR/autofillForms.properties b/chrome/locale/hr-HR/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/hr-HR/autofillForms.properties
rename to chrome/locale/hr-HR/autofillForms.properties
diff --git a/src/chrome/locale/hu-HU/autofillForms.dtd b/chrome/locale/hu-HU/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/hu-HU/autofillForms.dtd
rename to chrome/locale/hu-HU/autofillForms.dtd
diff --git a/src/chrome/locale/hu-HU/autofillForms.properties b/chrome/locale/hu-HU/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/hu-HU/autofillForms.properties
rename to chrome/locale/hu-HU/autofillForms.properties
diff --git a/src/chrome/locale/it-IT/autofillForms.dtd b/chrome/locale/it-IT/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/it-IT/autofillForms.dtd
rename to chrome/locale/it-IT/autofillForms.dtd
diff --git a/src/chrome/locale/it-IT/autofillForms.properties b/chrome/locale/it-IT/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/it-IT/autofillForms.properties
rename to chrome/locale/it-IT/autofillForms.properties
diff --git a/src/chrome/locale/nl-NL/autofillForms.dtd b/chrome/locale/nl-NL/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/nl-NL/autofillForms.dtd
rename to chrome/locale/nl-NL/autofillForms.dtd
diff --git a/src/chrome/locale/nl-NL/autofillForms.properties b/chrome/locale/nl-NL/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/nl-NL/autofillForms.properties
rename to chrome/locale/nl-NL/autofillForms.properties
diff --git a/src/chrome/locale/pl-PL/autofillForms.dtd b/chrome/locale/pl-PL/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/pl-PL/autofillForms.dtd
rename to chrome/locale/pl-PL/autofillForms.dtd
diff --git a/src/chrome/locale/pl-PL/autofillForms.properties b/chrome/locale/pl-PL/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/pl-PL/autofillForms.properties
rename to chrome/locale/pl-PL/autofillForms.properties
diff --git a/src/chrome/locale/pt-BR/autofillForms.dtd b/chrome/locale/pt-BR/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/pt-BR/autofillForms.dtd
rename to chrome/locale/pt-BR/autofillForms.dtd
diff --git a/src/chrome/locale/pt-BR/autofillForms.properties b/chrome/locale/pt-BR/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/pt-BR/autofillForms.properties
rename to chrome/locale/pt-BR/autofillForms.properties
diff --git a/src/chrome/locale/ro-RO/autofillForms.dtd b/chrome/locale/ro-RO/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/ro-RO/autofillForms.dtd
rename to chrome/locale/ro-RO/autofillForms.dtd
diff --git a/src/chrome/locale/ro-RO/autofillForms.properties b/chrome/locale/ro-RO/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/ro-RO/autofillForms.properties
rename to chrome/locale/ro-RO/autofillForms.properties
diff --git a/src/chrome/locale/ru-RU/autofillForms.dtd b/chrome/locale/ru-RU/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/ru-RU/autofillForms.dtd
rename to chrome/locale/ru-RU/autofillForms.dtd
diff --git a/src/chrome/locale/ru-RU/autofillForms.properties b/chrome/locale/ru-RU/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/ru-RU/autofillForms.properties
rename to chrome/locale/ru-RU/autofillForms.properties
diff --git a/src/chrome/locale/sk-SK/autofillForms.dtd b/chrome/locale/sk-SK/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/sk-SK/autofillForms.dtd
rename to chrome/locale/sk-SK/autofillForms.dtd
diff --git a/src/chrome/locale/sk-SK/autofillForms.properties b/chrome/locale/sk-SK/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/sk-SK/autofillForms.properties
rename to chrome/locale/sk-SK/autofillForms.properties
diff --git a/src/chrome/locale/sv-SE/autofillForms.dtd b/chrome/locale/sv-SE/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/sv-SE/autofillForms.dtd
rename to chrome/locale/sv-SE/autofillForms.dtd
diff --git a/src/chrome/locale/sv-SE/autofillForms.properties b/chrome/locale/sv-SE/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/sv-SE/autofillForms.properties
rename to chrome/locale/sv-SE/autofillForms.properties
diff --git a/src/chrome/locale/tr-TR/autofillForms.dtd b/chrome/locale/tr-TR/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/tr-TR/autofillForms.dtd
rename to chrome/locale/tr-TR/autofillForms.dtd
diff --git a/src/chrome/locale/tr-TR/autofillForms.properties b/chrome/locale/tr-TR/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/tr-TR/autofillForms.properties
rename to chrome/locale/tr-TR/autofillForms.properties
diff --git a/src/chrome/locale/zh-CN/autofillForms.dtd b/chrome/locale/zh-CN/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/zh-CN/autofillForms.dtd
rename to chrome/locale/zh-CN/autofillForms.dtd
diff --git a/src/chrome/locale/zh-CN/autofillForms.properties b/chrome/locale/zh-CN/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/zh-CN/autofillForms.properties
rename to chrome/locale/zh-CN/autofillForms.properties
diff --git a/src/chrome/locale/zh-TW/autofillForms.dtd b/chrome/locale/zh-TW/autofillForms.dtd
similarity index 100%
rename from src/chrome/locale/zh-TW/autofillForms.dtd
rename to chrome/locale/zh-TW/autofillForms.dtd
diff --git a/src/chrome/locale/zh-TW/autofillForms.properties b/chrome/locale/zh-TW/autofillForms.properties
similarity index 100%
rename from src/chrome/locale/zh-TW/autofillForms.properties
rename to chrome/locale/zh-TW/autofillForms.properties
diff --git a/src/chrome/skin/arrows.png b/chrome/skin/arrows.png
similarity index 100%
rename from src/chrome/skin/arrows.png
rename to chrome/skin/arrows.png
diff --git a/chrome/skin/autofillForms.css b/chrome/skin/autofillForms.css
new file mode 100644
index 0000000..5d4678d
--- /dev/null
+++ b/chrome/skin/autofillForms.css
@@ -0,0 +1,59 @@
+#autofillFormsButton,
+.autofillFormsButton {
+ list-style-image: url("pencil.png");
+}
+toolbar[iconsize="small"] #autofillFormsButton,
+toolbar[iconsize="small"] .autofillFormsButton,
+.autofillFormsIcon {
+ list-style-image: url("pencil-small.png");
+}
+#autofillFormsButton[cui-areatype="menu-panel"],
+toolbarpaletteitem[place="palette"] > #autofillFormsButton {
+ list-style-image: url("pencil-big.png");
+}
+/** Retina Display **/
+ at media (min-resolution: 2dppx) {
+ toolbar[iconsize="small"] #autofillFormsButton,
+ toolbar[iconsize="small"] .autofillFormsButton,
+ .autofillFormsIcon {
+ list-style-image: url("pencil-big.png");
+ }
+}
+
+
+.autofillFormsProfileIcon {
+ list-style-image: url("profile-small.png");
+}
+.autofillFormsSettingsIcon {
+ list-style-image: url("settings-small.png");
+}
+.autofillFormsHelpIcon {
+ list-style-image: url("help-small.png");
+}
+
+statusbarpanel.autofillFormsIcon {
+ cursor: pointer;
+}
+
+#autofillFormsTooltipCurrentProfile {
+ margin-bottom:10px;
+}
+#autofillFormsTooltipCurrentProfileCaption {
+}
+#autofillFormsTooltipCurrentProfileLabel {
+ font-weight: bold;
+}
+#autofillFormsTooltipGrid {
+}
+.autofillFormsTooltipGridHeader {
+ font-weight:bold;
+ margin-bottom:5px;
+}
+.autofillFormsTooltipGridCommand {
+}
+.autofillFormsTooltipGridMouseButton {
+ font-style:italic;
+}
+.autofillFormsTooltipGridKeyboardShortcut {
+ font-family:monospace;
+}
diff --git a/src/chrome/skin/autofillFormsMac.css b/chrome/skin/autofillFormsMac.css
similarity index 100%
rename from src/chrome/skin/autofillFormsMac.css
rename to chrome/skin/autofillFormsMac.css
diff --git a/src/chrome/skin/autofillFormsOptions.css b/chrome/skin/autofillFormsOptions.css
similarity index 100%
rename from src/chrome/skin/autofillFormsOptions.css
rename to chrome/skin/autofillFormsOptions.css
diff --git a/src/chrome/skin/autofillFormsOptions1.5.css b/chrome/skin/autofillFormsOptions1.5.css
similarity index 100%
rename from src/chrome/skin/autofillFormsOptions1.5.css
rename to chrome/skin/autofillFormsOptions1.5.css
diff --git a/src/chrome/skin/autofillFormsOptions2.css b/chrome/skin/autofillFormsOptions2.css
similarity index 100%
rename from src/chrome/skin/autofillFormsOptions2.css
rename to chrome/skin/autofillFormsOptions2.css
diff --git a/src/chrome/skin/autofillFormsRuleEditor.css b/chrome/skin/autofillFormsRuleEditor.css
similarity index 100%
rename from src/chrome/skin/autofillFormsRuleEditor.css
rename to chrome/skin/autofillFormsRuleEditor.css
diff --git a/src/chrome/skin/autofillFormsTagEditor.css b/chrome/skin/autofillFormsTagEditor.css
similarity index 100%
rename from src/chrome/skin/autofillFormsTagEditor.css
rename to chrome/skin/autofillFormsTagEditor.css
diff --git a/src/chrome/skin/help-small.png b/chrome/skin/help-small.png
similarity index 100%
rename from src/chrome/skin/help-small.png
rename to chrome/skin/help-small.png
diff --git a/src/chrome/skin/icon.png b/chrome/skin/icon.png
similarity index 100%
copy from src/chrome/skin/icon.png
copy to chrome/skin/icon.png
diff --git a/src/chrome/skin/pencil-active-mac.png b/chrome/skin/pencil-active-mac.png
similarity index 100%
rename from src/chrome/skin/pencil-active-mac.png
rename to chrome/skin/pencil-active-mac.png
diff --git a/src/chrome/skin/icon.png b/chrome/skin/pencil-big.png
similarity index 100%
rename from src/chrome/skin/icon.png
rename to chrome/skin/pencil-big.png
diff --git a/src/chrome/skin/pencil-mac.png b/chrome/skin/pencil-mac.png
similarity index 100%
rename from src/chrome/skin/pencil-mac.png
rename to chrome/skin/pencil-mac.png
diff --git a/src/chrome/skin/pencil-small.png b/chrome/skin/pencil-small.png
similarity index 100%
rename from src/chrome/skin/pencil-small.png
rename to chrome/skin/pencil-small.png
diff --git a/src/chrome/skin/pencil.png b/chrome/skin/pencil.png
similarity index 100%
rename from src/chrome/skin/pencil.png
rename to chrome/skin/pencil.png
diff --git a/src/chrome/skin/profile-small.png b/chrome/skin/profile-small.png
similarity index 100%
rename from src/chrome/skin/profile-small.png
rename to chrome/skin/profile-small.png
diff --git a/src/chrome/skin/settings-small.png b/chrome/skin/settings-small.png
similarity index 100%
rename from src/chrome/skin/settings-small.png
rename to chrome/skin/settings-small.png
diff --git a/src/defaults/preferences/autofillForms.js b/defaults/preferences/autofillForms.js
similarity index 95%
rename from src/defaults/preferences/autofillForms.js
rename to defaults/preferences/autofillForms.js
index 853dd37..0cb3211 100644
--- a/src/defaults/preferences/autofillForms.js
+++ b/defaults/preferences/autofillForms.js
@@ -18,7 +18,7 @@ pref('extensions.autofillForms at blueimp.net.profileLabels', 'chrome://autofillFor
pref('extensions.autofillForms at blueimp.net.dynamicTags', 'chrome://autofillForms/locale/autofillForms.properties');
pref('extensions.autofillForms at blueimp.net.dynamicTagCodes', 'chrome://autofillForms/locale/autofillForms.properties');
pref('extensions.autofillForms at blueimp.net.regExpPasswordLabel', 'chrome://autofillForms/locale/autofillForms.properties');
-pref('extensions.autofillForms at blueimp.net.regExpFormFieldTypes', '^(?:(?:text(?:area)?)|(?:select-(?:(?:one)|(?:multiple)))|(?:checkbox)|(?:radio)|(?:password)|(?:file))$');
+pref('extensions.autofillForms at blueimp.net.regExpFormFieldTypes', '^(?:(?:text(?:area)?)|(?:select-(?:(?:one)|(?:multiple)))|(?:checkbox)|(?:radio)|(?:email)|(?:url)|(?:password)|(?:file))$');
pref('extensions.autofillForms at blueimp.net.enableDynamicTags', false);
pref('extensions.autofillForms at blueimp.net.profileIndex', 0);
pref('extensions.autofillForms at blueimp.net.storeEncrypted', false);
@@ -50,6 +50,6 @@ pref('extensions.autofillForms at blueimp.net.configDirectory', '');
pref('extensions.autofillForms at blueimp.net.useConfigDirectory', false);
pref('extensions.autofillForms at blueimp.net.profileSiteRules', '(?:)');
pref('extensions.autofillForms at blueimp.net.autoSelectBestProfile', true);
-pref('extensions.autofillForms at blueimp.net.helpURL', 'https://www.abine.com/support.php');
+pref('extensions.autofillForms at blueimp.net.helpURL', 'http://firefox.add0n.com/autofill-forms.html');
pref("extensions.autofillForms at blueimp.net.just_installed", true);
-pref("extensions.autofillForms at blueimp.net.post_install_url", "https://www.abine.com/oldpostinstall.php?addon=autofillForms");
+pref("extensions.autofillForms at blueimp.net.post_install_url", "http://firefox.add0n.com/autofill-forms.html");
diff --git a/install.rdf b/install.rdf
new file mode 100644
index 0000000..21716d0
--- /dev/null
+++ b/install.rdf
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>autofillForms at blueimp.net</em:id>
+ <em:name>Autofill Forms</em:name>
+ <em:creator>Sebastian Tschan</em:creator>
+ <em:contributor>Sarah Avilov</em:contributor>
+ <em:description>Fill out web forms automatically</em:description>
+ <em:iconURL>chrome://autofillForms/skin/icon.png</em:iconURL>
+ <em:optionsURL>chrome://autofillForms/content/autofillFormsOptions.xul</em:optionsURL>
+ <em:homepageURL>http://firefox.add0n.com/autofill-forms.html</em:homepageURL>
+ <em:version>1.0.2</em:version>
+ <em:type>2</em:type>
+ <em:targetApplication>
+ <Description>
+ <!-- Firefox -->
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+ <em:minVersion>17.0</em:minVersion>
+ <em:maxVersion>35.0</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ <em:targetApplication>
+ <Description>
+ <!-- Midbrowser -->
+ <em:id>{aa5ca914-c309-495d-91cf-3141bbb04115}</em:id>
+ <em:minVersion>0.2</em:minVersion>
+ <em:maxVersion>2.0.0.6</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ <em:translator>PetrTwo (Czech)</em:translator>
+ <em:translator>Oliver Roth (German)</em:translator>
+ <em:translator>Koumen (Greek)</em:translator>
+ <em:translator>jesuspportillo (Spanish)</em:translator>
+ <em:translator>Unknown (Finnish)</em:translator>
+ <em:translator>myahoo (French)</em:translator>
+ <em:translator>YuvalSht (Hebrew)</em:translator>
+ <em:translator>Mikes Kaszmán István (Hungarian)</em:translator>
+ <em:translator>Underpass (Italian)</em:translator>
+ <em:translator>gonzalopirobutirro (Italian)</em:translator>
+ <em:translator>Godai71 (Italian)</em:translator>
+ <em:translator>markh (Dutch)</em:translator>
+ <em:translator>teo (Polish)</em:translator>
+ <em:translator>Alberto Eidh (Portuguese - Brazilian)</em:translator>
+ <em:translator>x10firefox (Romanian)</em:translator>
+ <em:translator>Unknown (Russian)</em:translator>
+ <em:translator>Umut (Swedish)</em:translator>
+ <em:translator>ch0ze (Slovak)</em:translator>
+ <em:translator>KenanBalamir (Turkish)</em:translator>
+ <em:translator>simophin (Chinese - Simplified)</em:translator>
+ <em:translator>Lu Ming-Tse (呂明澤) (Chinese - Traditional)</em:translator>
+ </Description>
+</RDF>
diff --git a/src/build.xml b/src/build.xml
deleted file mode 100644
index 9ee9f23..0000000
--- a/src/build.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" ?>
-
-<project name="Autofill Forms" default="xpi">
- <property name="version.number" value="0.9.8.1" />
- <property name="jar.name" value="autofillforms" />
- <property name="xpi.name" value="autofill_forms-${version.number}-fx" />
- <property name="src.dir" value="." />
- <property name="chrome.dir" value="chrome" />
- <property name="dist.dir" value="../downloads" />
-
- <condition property="jar.present">
- <and>
- <available file="${chrome.dir}/${jar.name}.jar" type="file" />
- </and>
- </condition>
-
- <condition property="xpi.present">
- <and>
- <available file="${dist.dir}/${xpi.name}.xpi" type="file" />
- </and>
- </condition>
-
- <target name="jar">
- <zip destfile="${chrome.dir}/${jar.name}.jar" level="9">
- <fileset dir="${chrome.dir}">
- <include name="content/**" />
- <include name="locale/**" />
- <include name="skin/**" />
- <exclude name="**/.*" />
- <exclude name="**/CVS/**" />
- </fileset>
- </zip>
- </target>
-
- <target name="xpi" depends="jar">
- <copy file="${src.dir}/chrome.manifest.jar.txt" tofile="${src.dir}/chrome.manifest" overwrite="true" />
- <mkdir dir="${dist.dir}" />
- <zip destfile="${dist.dir}/${xpi.name}.xpi" level="9">
- <zipfileset file="${chrome.dir}/${jar.name}.jar" prefix="chrome"/>
- <fileset dir="${src.dir}">
- <include name="chrome.manifest" />
- <include name="install.rdf" />
- <include name="defaults/**" />
- <exclude name="**/.*" />
- <exclude name="**/CVS/**" />
- </fileset>
- </zip>
- <copy file="${src.dir}/chrome.manifest.extracted.txt" tofile="${src.dir}/chrome.manifest" overwrite="true" />
- </target>
-
- <target name="clean.jar" if="jar.present">
- <delete file="${chrome.dir}/${jar.name}.jar" failonerror="false" />
- </target>
-
- <target name="clean.xpi" if="xpi.present">
- <delete file="${dist.dir}/${xpi.name}.xpi" failonerror="false" />
- </target>
-
-</project>
diff --git a/src/chrome.manifest.extracted.txt b/src/chrome.manifest.extracted.txt
deleted file mode 100644
index c254d33..0000000
--- a/src/chrome.manifest.extracted.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-content autofillforms chrome/content/
-locale autofillforms cs-CZ chrome/locale/cs-CZ/
-locale autofillforms de-DE chrome/locale/de-DE/
-locale autofillforms el-GR chrome/locale/el-GR/
-locale autofillforms en-US chrome/locale/en-US/
-locale autofillforms es-ES chrome/locale/es-ES/
-locale autofillforms fr-FR chrome/locale/fr-FR/
-locale autofillforms fi-FI chrome/locale/fi-FI/
-locale autofillforms he-IL chrome/locale/he-IL/
-locale autofillforms hr-HR chrome/locale/hr-HR/
-locale autofillforms hu-HU chrome/locale/hu-HU/
-locale autofillforms it-IT chrome/locale/it-IT/
-locale autofillforms nl-NL chrome/locale/nl-NL/
-locale autofillforms pl-PL chrome/locale/pl-PL/
-locale autofillforms pt-BR chrome/locale/pt-BR/
-locale autofillforms ro-RO chrome/locale/ro-RO/
-locale autofillforms ru-RU chrome/locale/ru-RU/
-locale autofillforms sk-SK chrome/locale/sk-SK/
-locale autofillforms sv-SE chrome/locale/sv-SE/
-locale autofillforms tr-TR chrome/locale/tr-TR/
-locale autofillforms zh-CN chrome/locale/zh-CN/
-locale autofillforms zh-TW chrome/locale/zh-TW/
-skin autofillforms classic/1.0 chrome/skin/
-overlay chrome://browser/content/browser.xul chrome://autofillforms/content/autofillFormsOverlay.xul
-style chrome://global/content/customizeToolbar.xul chrome://autofillforms/skin/autofillForms.css
-style chrome://autofillforms/content/autofillFormsOptions.xul chrome://autofillforms/skin/autofillFormsOptions2.css appversion<3.0
-style chrome://autofillforms/content/autofillFormsOptions.xul chrome://autofillforms/skin/autofillFormsOptions1.5.css appversion<2.0
-style chrome://browser/content/browser.xul chrome://autofillforms/skin/autofillFormsMac.css appversion>=3.0 os=Darwin
-style chrome://global/content/customizeToolbar.xul chrome://autofillforms/skin/autofillFormsMac.css appversion>=3.0 os=Darwin
\ No newline at end of file
diff --git a/src/chrome.manifest.jar.txt b/src/chrome.manifest.jar.txt
deleted file mode 100644
index c6c22ca..0000000
--- a/src/chrome.manifest.jar.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-content autofillforms jar:chrome/autofillforms.jar!/content/
-locale autofillforms cs-CZ jar:chrome/autofillforms.jar!/locale/cs-CZ/
-locale autofillforms de-DE jar:chrome/autofillforms.jar!/locale/de-DE/
-locale autofillforms el-GR jar:chrome/autofillforms.jar!/locale/el-GR/
-locale autofillforms en-US jar:chrome/autofillforms.jar!/locale/en-US/
-locale autofillforms es-ES jar:chrome/autofillforms.jar!/locale/es-ES/
-locale autofillforms fr-FR jar:chrome/autofillforms.jar!/locale/fr-FR/
-locale autofillforms fi-FI jar:chrome/autofillforms.jar!/locale/fi-FI/
-locale autofillforms he-IL jar:chrome/autofillforms.jar!/locale/he-IL/
-locale autofillforms hr-HR jar:chrome/autofillforms.jar!/locale/hr-HR/
-locale autofillforms hu-HU jar:chrome/autofillforms.jar!/locale/hu-HU/
-locale autofillforms it-IT jar:chrome/autofillforms.jar!/locale/it-IT/
-locale autofillforms nl-NL jar:chrome/autofillforms.jar!/locale/nl-NL/
-locale autofillforms pl-PL jar:chrome/autofillforms.jar!/locale/pl-PL/
-locale autofillforms pt-BR jar:chrome/autofillforms.jar!/locale/pt-BR/
-locale autofillforms ro-RO jar:chrome/autofillforms.jar!/locale/ro-RO/
-locale autofillforms ru-RU jar:chrome/autofillforms.jar!/locale/ru-RU/
-locale autofillforms sk-SK jar:chrome/autofillforms.jar!/locale/sk-SK/
-locale autofillforms sv-SE jar:chrome/autofillforms.jar!/locale/sv-SE/
-locale autofillforms tr-TR jar:chrome/autofillforms.jar!/locale/tr-TR/
-locale autofillforms zh-CN jar:chrome/autofillforms.jar!/locale/zh-CN/
-locale autofillforms zh-TW jar:chrome/autofillforms.jar!/locale/zh-TW/
-skin autofillforms classic/1.0 jar:chrome/autofillforms.jar!/skin/
-overlay chrome://browser/content/browser.xul chrome://autofillforms/content/autofillFormsOverlay.xul
-style chrome://global/content/customizeToolbar.xul chrome://autofillforms/skin/autofillForms.css
-style chrome://autofillforms/content/autofillFormsOptions.xul chrome://autofillforms/skin/autofillFormsOptions2.css appversion<3.0
-style chrome://autofillforms/content/autofillFormsOptions.xul chrome://autofillforms/skin/autofillFormsOptions1.5.css appversion<2.0
-style chrome://browser/content/browser.xul chrome://autofillforms/skin/autofillFormsMac.css appversion>=3.0 os=Darwin
-style chrome://global/content/customizeToolbar.xul chrome://autofillforms/skin/autofillFormsMac.css appversion>=3.0 os=Darwin
\ No newline at end of file
diff --git a/src/chrome/content/autofillForms.js b/src/chrome/content/autofillForms.js
deleted file mode 100644
index ba668fe..0000000
--- a/src/chrome/content/autofillForms.js
+++ /dev/null
@@ -1,5389 +0,0 @@
-/*
- * @package autofillForms
- * @author Sebastian Tschan
- * @copyright (c) Sebastian Tschan
- * @license GNU General Public License
- * @link https://blueimp.net/mozilla/
- */
-
-var autofillForms = {
-
- // The selected profile index:
- profileIndex: null,
- // The selected global profile index:
- globalProfileIndex: null,
- // The selected form fields context menu profile index
- formFieldsContextMenuProfileIndex: null,
- // The list of profile labels:
- profileLabels: null,
- // The list of profile site rules:
- profileSiteRules: null,
- // The list of form field rules:
- fieldRules: null,
- // The tree representing the field rules list:
- tree: null,
- // The tree view:
- treeView: null,
- // The tree view frontend:
- treeBox: null,
- // Holds the selection object for the treeview:
- selection: null,
- // Remembers the last selected index of the treeview:
- lastSelectedIndex: null,
- // Determines if sort is to be ascending or descending:
- ascending: null,
- // The profiles listBox:
- profilesTree: null,
- // The profiles tree view:
- profilesTreeView: null,
- // The profiles tree view frontend:
- profilesTreeBox: null,
- // Holds the selection object for the profiles treeview:
- profilesSelection: null,
- // The profiles sort order:
- profilesAscending: null,
- // Autofill forms preferences branch:
- autofillFormsPrefs: null,
- // Object containing the shortcuts information (modifiers, key or keycode):
- shortcut: null,
- // Object containing the mouse button shortcuts information:
- mouseButton: null,
- // Helper var to do the opposite of the current setting:
- invertedSetting: null,
- // Array containing the rule element types ("begins with", "contains", ...):
- ruleElementTypes: null,
- // Containes the reference to the current rule field:
- currentRuleField: null,
- // Defines the index selected for the last alternative fieldRules selection:
- fieldRuleAlternativesIndex: null,
- // Stores the length of the last created list of alternative fieldRules:
- fieldRuleAlternativesLength: null,
- // Hash to store lists of alternatives (used for radio input fields):
- fieldRuleAlternativesHash: null,
- // Cache to reuse/clone fieldRuleAlternatives on the same form fill run:
- fieldRuleAlternativesCache: null,
- // Array of dynamic tags:
- dynamicTags: null,
- // Array of dynamic tag codes, associated to the dynamic tags:
- dynamicTagCodes: null,
- // Determines if a textbox is focused on the rule editor:
- ruleEditorTextBoxFocused: null,
- // Determines if a textbox is focused on the tag editor:
- tagEditorTextBoxFocused: null,
- // References the last matched form element (used to set the focus):
- lastFormElementMatch: null,
- // References the current window when filling out forms:
- currentWindow: null,
- // Holds the index of the current form when filling out forms:
- currentFormIndex:null,
- // Holds the index of the current form element when filling out forms:
- currentElementIndex: null,
- // References the target form field on which the context menu has been invoked:
- targetFormField: null,
- // Event listener for the content area context menu:
- contentAreaContextMenuEventListener: null,
- // Holds the the tooltip grid which displays commands and their mouse buttons and keyboard shortcuts:
- tooltipGrid: null,
- // Holds the current profile tooltip label:
- tooltipCurrentProfile: null,
- // Keep track of open dialogs
- currentDialogs: null,
- // current version number
- version: "0.9.8.2",
-
- initialize: function() {
-
- // Save the reference to the Autofill Forms preferences branch:
- this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
-
- // Add a preferences observer to the autofillForms preferences branch:
- this.autofillFormsPrefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
- this.autofillFormsPrefs.addObserver('', this, false);
-
- // Implement the event listener for the content area context menu:
- this.contentAreaContextMenuEventListener = function(event) {
- autofillForms.initContentAreaContextMenu(event);
- }
-
- // Initialize the preferences settings:
- this.initializePrefs();
-
-
- var self = this;
- document.addEventListener("SSTabRestored", function(event){
- var just_installed = self.autofillFormsPrefs.getBoolPref("just_installed");
- if(just_installed){
- self.autofillFormsPrefs.setBoolPref("just_installed", false);
- gBrowser.selectedTab = gBrowser.addTab(self.autofillFormsPrefs.getCharPref("post_install_url"));
-
- }
- });
-
-
-
- },
-
- initContentAreaContextMenu: function(event) {
- var cm0 = document.getElementById('autofillFormsContextMenuItem');
- var cm1 = document.getElementById('autofillFormsContextMenu');
- var cm2 = document.getElementById('autofillFormsManualFillContextMenu');
- var cm3 = document.getElementById('autofillFormsAddRuleContextMenuItem');
- var cm4 = document.getElementById('autofillFormsAddFormAsProfileContextMenuItem');
- var cm5 = document.getElementById('autofillFormsContextMenuSeparator1');
- var cm6 = document.getElementById('autofillFormsContextMenuSeparator2');
- var cm7 = document.getElementById('autofillFormsDisplayFormDetailsContextMenuItem');
- if(cm0 && gContextMenu) {
- if(gContextMenu.target && this.isValidFormField(gContextMenu.target)) {
- cm0.hidden = true;
- cm1.hidden = true;
- if(this.autofillFormsPrefs.getBoolPref('hideFormFieldsContextMenu')) {
- cm2.hidden = true;
- cm3.hidden = true;
- cm4.hidden = true;
- cm5.hidden = true;
- cm6.hidden = true;
- cm7.hidden = true;
- this.targetFormField = null;
- } else {
- cm2.hidden = false;
- cm3.hidden = false;
- cm4.hidden = false;
- // Show menuseparators if not already separated:
- if(this.isPreviousNodeSeparated(cm5)) {
- cm5.hidden = true;
- } else {
- cm5.hidden = false;
- }
- if(this.isNextNodeSeparated(cm6)) {
- cm6.hidden = true;
- } else {
- cm6.hidden = false;
- }
- this.targetFormField = gContextMenu.target;
- }
- return;
- }
-
- if(this.autofillFormsPrefs.getBoolPref('hideContextMenuItem')
- || gContextMenu.isContentSelected
- || gContextMenu.onTextInput
- || gContextMenu.onImage
- || gContextMenu.onLink
- || gContextMenu.onCanvas
- || gContextMenu.onMathML
- || !this.getDoc().forms
- || !this.getDoc().forms.length) {
- cm0.hidden = true;
- cm1.hidden = true;
- cm5.hidden = true;
- cm6.hidden = true;
- cm7.hidden = true;
- } else {
- if(this.getProfileLabels().length == 1) {
- cm0.hidden = false;
- cm1.hidden = true;
- } else {
- cm0.hidden = true;
- cm1.hidden = false;
- }
- // Show menuseparators if not already separated:
- if(this.isPreviousNodeSeparated(cm5)) {
- cm5.hidden = true;
- } else {
- cm5.hidden = false;
- }
- if(this.isNextNodeSeparated(cm6)) {
- cm6.hidden = true;
- } else {
- cm6.hidden = false;
- }
- cm7.hidden = false;
- }
- cm2.hidden = true;
- cm3.hidden = true;
- cm4.hidden = true;
- this.targetFormField = null;
- }
- },
-
- isNextNodeSeparated: function(node) {
- while(node) {
- node = node.nextSibling
- if(node.hidden) {
- continue;
- }
- if(node.nodeName == 'menuseparator') {
- return true;
- } else {
- return false;
- }
- }
- return true;
- },
-
- isPreviousNodeSeparated: function(node) {
- while(node) {
- node = node.previousSibling;
- if(node.hidden) {
- continue;
- }
- if(node.nodeName == 'menuseparator') {
- return true;
- } else {
- return false;
- }
- }
- return true;
- },
-
- initializePrefs: function() {
- // Initialize the keyboard shortcut object container:
- this.shortcut = new Object();
- this.shortcut['shortcut'] = null;
- this.shortcut['shortcutSubmit'] = null;
- this.shortcut['shortcutAllTabs'] = null;
- this.shortcut['shortcutFromProfileSelection'] = null;
- this.shortcut['shortcutProfile'] = null;
- this.shortcut['shortcutSettings'] = null;
- this.shortcut['shortcutDisplayFormDetails'] = null;
- for(var property in this.shortcut) {
- this.updateShortcut(property);
- }
- // Initialize toolbar and statusbar icons and context menu:
- this.hideToolbarButtonUpdate();
- this.hideToolbarButtonMenuUpdate();
- this.hideStatusbarIconUpdate();
- this.hideContextMenuItemUpdate();
- },
-
- observe: function(subject, topic, data) {
- // Only observe preferences changes:
- if (topic != 'nsPref:changed')
- return;
- switch(data) {
- case 'profileIndex':
- // If set to null, the profileIndex will be updated on next getProfileIndex() call:
- this.profileIndex = null;
- this.tooltipCurrentProfile = null;
- break;
- case 'globalProfileIndex':
- // If set to null, the globalProfileIndex will be updated on next getGlobalProfileIndex() call:
- this.globalProfileIndex = null;
- break;
- case 'formFieldsContextMenuProfileIndex':
- // If set to null, the formFieldsContextMenuProfileIndex will be updated on next getFormFieldsContextMenuProfileIndex() call:
- this.formFieldsContextMenuProfileIndex = null;
- break;
- case 'profileLabels':
- // If set to null, the profileLabels will be updated on next getProfileLabels() call:
- this.profileLabels = null;
- this.tooltipCurrentProfile = null;
- break;
- case 'profileSiteRules':
- // If set to null, the profileSiteRules will be updated on next getProfileSiteRules() call:
- this.profileSiteRules = null;
- break;
- case 'shortcut':
- this.updateShortcut('shortcut');
- this.tooltipGrid = null;
- break;
- case 'shortcutSubmit':
- this.updateShortcut('shortcutSubmit');
- this.tooltipGrid = null;
- break;
- case 'shortcutAllTabs':
- this.updateShortcut('shortcutAllTabs');
- this.tooltipGrid = null;
- break;
- case 'shortcutFromProfileSelection':
- this.updateShortcut('shortcutFromProfileSelection');
- this.tooltipGrid = null;
- break;
- case 'shortcutProfile':
- this.updateShortcut('shortcutProfile');
- this.tooltipGrid = null;
- break;
- case 'shortcutSettings':
- this.updateShortcut('shortcutSettings');
- this.tooltipGrid = null;
- break;
- case 'shortcutDisplayFormDetails':
- this.updateShortcut('shortcutDisplayFormDetails');
- this.tooltipGrid = null;
- break;
- case 'mouseShortcut':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcut'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'mouseShortcutSubmit':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcutSubmit'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'mouseShortcutAllTabs':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcutAllTabs'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'mouseShortcutFromProfileSelection':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcutFromProfileSelection'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'mouseShortcutProfile':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcutProfile'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'mouseShortcutSettings':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcutSettings'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'mouseShortcutDisplayFormDetails':
- if(this.mouseButton) {
- this.mouseButton['mouseShortcutDisplayFormDetails'] = null;
- this.tooltipGrid = null;
- }
- break;
- case 'fieldRules':
- if(!this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // If set to null, the fieldRules will be updated on next getFieldRules() call:
- this.fieldRules = null;
- }
- break;
- case 'storeEncrypted':
- // To update the stored data, we must decrypt or may not decrypt
- // the prefString in opposition to the setting which just changed -
- // the "invertedSetting" helper var helps to identify this situation:
- this.invertedSetting = true;
- // Store data encrypted/decrypted:
- this.setFieldRules();
- this.invertedSetting = false;
- break;
- case 'dynamicTags':
- // If set to null, the dynamicTags will be updated on next getDynamicTags() call:
- this.dynamicTags = null;
- break;
- case 'dynamicTagCodes':
- // If set to null, the dynamicTagCodes will be updated on next getDynamicTagCodes() call:
- this.dynamicTagCodes = null;
- break;
- case 'hideContextMenuItem':
- this.hideContextMenuItemUpdate();
- break;
- case 'hideFormFieldsContextMenu':
- this.hideContextMenuItemUpdate();
- break;
- case 'hideStatusbarIcon':
- this.hideStatusbarIconUpdate();
- break;
- case 'hideToolbarButton':
- this.hideToolbarButtonUpdate();
- this.hideToolbarButtonMenuUpdate();
- break;
- case 'hideToolbarButtonMenu':
- this.hideToolbarButtonMenuUpdate();
- break;
- case 'useConfigDirectory':
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- this.exportToConfigDirectory();
- } else {
- this.importFromConfigDirectory();
- }
- break;
- }
- },
-
- hideContextMenuItemUpdate: function() {
- var contentAreaContextMenu = document.getElementById('contentAreaContextMenu');
- if(contentAreaContextMenu) {
- if(!this.autofillFormsPrefs.getBoolPref('hideContextMenuItem')
- || !this.autofillFormsPrefs.getBoolPref('hideFormFieldsContextMenu')) {
- // Add the content area context menu listener:
- contentAreaContextMenu.addEventListener(
- 'popupshowing',
- this.contentAreaContextMenuEventListener,
- false
- );
- } else {
- var cm0 = document.getElementById('autofillFormsContextMenuItem');
- var cm1 = document.getElementById('autofillFormsContextMenu');
- var cm2 = document.getElementById('autofillFormsManualFillContextMenu');
- var cm3 = document.getElementById('autofillFormsAddRuleContextMenuItem');
- var cm4 = document.getElementById('autofillFormsAddFormAsProfileContextMenuItem');
- var cm5 = document.getElementById('autofillFormsContextMenuSeparator1');
- var cm6 = document.getElementById('autofillFormsContextMenuSeparator2');
- if(cm0) {
- cm0.hidden = true;
- cm1.hidden = true;
- cm2.hidden = true;
- cm3.hidden = true;
- cm4.hidden = true;
- cm5.hidden = true;
- cm6.hidden = true;
- }
- // Remove the content area context menu listener:
- this.targetFormField = null;
- contentAreaContextMenu.removeEventListener(
- 'popupshowing',
- this.contentAreaContextMenuEventListener,
- false
- );
- }
- }
- },
-
- hideStatusbarIconUpdate: function() {
- // Change the statusbar icon visibility:
- var autofillFormsPanelIcon = document.getElementById('autofillFormsPanelIcon');
- if(autofillFormsPanelIcon) {
- autofillFormsPanelIcon.setAttribute(
- 'hidden',
- this.autofillFormsPrefs.getBoolPref('hideStatusbarIcon')
- );
- }
- },
-
- installToolbarButton: function(buttonID, beforeNodeID, toolbarID) {
- beforeNodeID = beforeNodeID ? beforeNodeID : 'home-button';
- toolbarID = toolbarID ? toolbarID : 'navigation-toolbar';
- if(!document.getElementById(buttonID)) {
- var toolbar = document.getElementById(toolbarID);
- if(!toolbar) {
- // Firefox < 3:
- toolbar = document.getElementById('nav-bar');
- }
- if(toolbar && 'insertItem' in toolbar) {
- var beforeNode = document.getElementById(beforeNodeID);
- if(beforeNode && beforeNode.parentNode != toolbar) {
- beforeNode = null;
- }
- // Insert before the given node or at the end of the toolbar if the node is not available:
- toolbar.insertItem(buttonID, beforeNode, null, false);
- toolbar.setAttribute('currentset', toolbar.currentSet);
- document.persist(toolbar.id, 'currentset');
- }
- }
- },
-
- hideToolbarButtonUpdate: function() {
- var autofillFormsButton = document.getElementById('autofillFormsButton');
- var hideToolbarButton = this.autofillFormsPrefs.getBoolPref('hideToolbarButton');
- if(!autofillFormsButton && !hideToolbarButton) {
- // Add the toolbar button to the toolbar:
- this.installToolbarButton('autofillFormsButton');
- autofillFormsButton = document.getElementById('autofillFormsButton');
- }
- if(autofillFormsButton) {
- autofillFormsButton.setAttribute(
- 'hidden',
- hideToolbarButton
- );
- }
- },
-
- hideToolbarButtonMenuUpdate: function() {
- var autofillFormsButton = document.getElementById('autofillFormsButton');
- if(autofillFormsButton) {
- if(this.autofillFormsPrefs.getBoolPref('hideToolbarButtonMenu')) {
- autofillFormsButton.removeAttribute('type');
- } else {
- autofillFormsButton.setAttribute('type','menu-button');
- }
- }
- },
-
- commandHandler: function(event) {
- if(typeof event.button == 'undefined') {
- // If no event.button is set, the command has been done by the left mouse button:
- event.button = 0;
- }
- // Recognize the mouse button and perform the associated action:
- var mouseButtonObj = this.recognizeMouseButton(event);
- if(this.getMouseButton('mouseShortcut').equals(mouseButtonObj)) {
- this.fillForms();
- } else if(this.getMouseButton('mouseShortcutSubmit').equals(mouseButtonObj)) {
- this.fillForms(null, null, true);
- } else if(this.getMouseButton('mouseShortcutAllTabs').equals(mouseButtonObj)) {
- this.fillForms(null, null, null, true);
- } else if(this.getMouseButton('mouseShortcutFromProfileSelection').equals(mouseButtonObj)) {
- this.profileSelectionFormFillPopup(event);
- } else if(this.getMouseButton('mouseShortcutProfile').equals(mouseButtonObj)) {
- this.showProfileSwitcher(event);
- } else if(this.getMouseButton('mouseShortcutSettings').equals(mouseButtonObj)) {
- this.showDialog('chrome://autofillForms/content/autofillFormsOptions.xul');
- } else if(this.getMouseButton('mouseShortcutDisplayFormDetails').equals(mouseButtonObj)) {
- this.displayFormDetails();
- }
- },
-
- clickHandler: function(event) {
- switch(event.button) {
- case 0:
- // The left mouse button is already handled for clicks on the toolbar button,
- // but not for clicks on the status bar icon:
- if(event.target.id == 'autofillFormsPanelIcon') {
- this.commandHandler(event);
- }
- break;
- default:
- this.commandHandler(event);
- }
- },
-
- profileSelectionFormFillPopup: function(event) {
- var popup = document.getElementById('autofillFormsProfileSelectionPopup');
- if(popup && typeof popup.openPopup == 'function') {
- this.prepareProfileSelectionFormFillMenu(popup);
- // Show the popup menu (only available for Firefox >= 3):
- popup.openPopup(event.target, null, 0, 0, false, true);
- } else {
- this.profileSelectionFormFillPrompt(event);
- }
- },
-
- prepareProfileSelectionFormFillMenu: function(menupopup) {
- // Remove all children nodes:
- while(menupopup.hasChildNodes()) {
- menupopup.removeChild(menupopup.firstChild);
- }
- var menuitem = document.createElement('menuitem');
- menuitem.setAttribute('class','menuitem-iconic autofillFormsIcon');
- // Add the profile labels as menu items:
- for(var i=0; i < this.getProfileLabels().length; i++) {
- menuitem = menuitem.cloneNode(false);
- menuitem.setAttribute('label', this.getProfileLabel(i));
- menuitem.setAttribute('oncommand', 'autofillForms.fillForms(null,'+i+');');
- menupopup.appendChild(menuitem);
- }
- },
-
- profileSelectionFormFillPrompt: function(event) {
- // Show a profile selection prompt and fill out forms with the selected profile:
- var list = this.getProfileLabels();
- var selected = {};
- var ok = this.getPrompts().select(
- window,
- this.getStringBundle().getString('profileSelectionFormFillTitle'),
- this.getStringBundle().getString('profileSelectionPrompt'),
- list.length,
- list,
- selected
- );
- if(ok) {
- this.fillForms(null, selected.value);
- }
- },
-
- fillForms: function(win, profileIndex, autoSubmit, allTabs) {
- if(!win || !win.document) {
- win = this.getWin();
- }
-
- var currentProfileIndex = this.getProfileIndex();
- var toggleAutoSelectBestProfile;
- if(typeof profileIndex == 'number') {
- // Temporarily set the given profile index:
- this.setProfileIndex(profileIndex);
-
- if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
- // Temporarily disable autoSelectBestProfile:
- this.autofillFormsPrefs.setBoolPref('autoSelectBestProfile', false);
- toggleAutoSelectBestProfile = true;
- }
- }
-
- autoSubmit = autoSubmit ? autoSubmit : null;
-
- if(allTabs) {
- // Fill out forms on all open browser tabs:
- for(var i=0; i<this.getBrowser().browsers.length; i++) {
- this.searchAndFillForms(
- this.getBrowser().getBrowserAtIndex(i).contentWindow,
- autoSubmit
- );
- }
- } else {
- // Fill out forms on the current tab (or the given window object):
- this.searchAndFillForms(win, autoSubmit);
- }
-
- // Reset Alternatives (including the cache):
- this.fieldRuleAlternativesIndex = null;
- this.fieldRuleAlternativesLength = null;
- this.fieldRuleAlternativesHash = null;
- this.fieldRuleAlternativesCache = null;
-
- // Reset objects to release used memory:
- this.fieldRules = null;
- this.profileSiteRules = null;
- this.dynamicTags = null;
- this.dynamicTagCodes = null;
-
- // Reset the selected profile:
- this.setProfileIndex(currentProfileIndex);
-
- if(toggleAutoSelectBestProfile) {
- // Reenable autoSelectBestProfile:
- this.autofillFormsPrefs.setBoolPref('autoSelectBestProfile', true);
- }
- },
-
- searchAndFillForms: function(win, autoSubmit) {
- var doc = this.getDoc(win);
-
- // Check if any web forms are available on the current window:
- if(doc && doc.forms && doc.forms.length > 0) {
-
- var url = doc.location.href;
-
- if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
- // Remember the currently selected profile:
- var currentProfileIndex = this.getProfileIndex();
- }
-
- // Select the best matching profile - returns false if none matches:
- if(!this.selectBestMatchingProfile(url)) {
- return;
- }
-
- this.currentWindow = win;
-
- // Holds the form to be submitted:
- var submitForm;
- // Holds the first submit element found on the form:
- var submitElement;
-
- // Go through the forms:
- for(var i = 0; i < doc.forms.length; i++) {
- this.currentFormIndex = i;
-
- // The form elements list:
- var elements = doc.forms[i].elements;
-
- // A hash to store the alternatives for radio input fields:
- this.fieldRuleAlternativesHash = new Object();
-
- // Go through the form elements:
- for(var j = 0; j < elements.length; j++) {
- this.currentElementIndex = j;
-
- // Fill out valid form field types:
- if(this.isValidFormField(elements[j])) {
- this.setFormField(elements[j], url);
- }
-
- // Collect the first submit button of the form if autoSubmit is enabled:
- if(autoSubmit && elements[j].type && elements[j].type == 'submit' && !submitElement) {
- submitElement = elements[j];
- }
- }
-
- this.applyStoredFieldRulesAlternatives();
-
- if(autoSubmit) {
- if(this.lastFormElementMatch && this.lastFormElementMatch.form == doc.forms[i]) {
- // Elements have been matched on this form, check the submitElement:
- if(!submitElement) {
- submitElement = this.getImageSubmitButton(doc.forms[i]);
- }
- submitForm = doc.forms[i];
- // Break out of the forms loop:
- break;
- } else {
- submitElement = null;
- }
- }
- }
-
- if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
- // Reset the selected profile to the manually selected one:
- this.setProfileIndex(currentProfileIndex);
- }
-
- if(this.lastFormElementMatch && this.autofillFormsPrefs.getBoolPref('focusLastFormElementMatch')) {
- // Set the focus to the last matched form element:
- this.lastFormElementMatch.focus();
- }
-
- // Reset the last matched form element:
- this.lastFormElementMatch = null;
-
- this.currentWindow = null;
- this.currentFormIndex = null;
- this.currentElementIndex = null;
-
- if(autoSubmit && submitForm) {
- // autoSubmit the form with a click on the submit button if found
- // or else by calling the submit() method on the form:
- if(submitElement) {
- submitElement.click();
- } else {
- submitForm.submit();
- }
- }
- }
-
- // Recursive call for all subframes:
- for(var f=0; f < win.frames.length; f++) {
- this.searchAndFillForms(win.frames[f], autoSubmit);
- }
- },
-
- getImageSubmitButton: function(form) {
- var inputElements = form.getElementsByTagName('input');
- for(var i = 0; i < inputElements.length; i++) {
- if(inputElements[i].type == 'image') {
- return inputElements[i];
- }
- }
- },
-
- selectBestMatchingProfile: function(url) {
- if(this.autofillFormsPrefs.getBoolPref('autoSelectBestProfile')) {
- var match;
- // The emtpy siteRule (?:) has a match length of 0, so we set the initial value to -1:
- var maxMatch = -1;
- var index = -1;
- // First test the currently selected profile:
- try {
- match = url.match(new RegExp(this.getProfileSiteRule(this.getProfileIndex()),'i'));
- if(match && (match.toString()).length > maxMatch) {
- maxMatch = (match.toString()).length;
- index = this.getProfileIndex();
- }
- } catch(e) {
- // Catch errors caused by invalid profile site rules
- }
- for(var i=0; i<this.getProfileSiteRules().length; i++) {
- if(i == this.getProfileIndex()) {
- // Skip the current profile (already tested):
- continue;
- }
- try {
- match = url.match(new RegExp(this.getProfileSiteRule(i),'i'));
- if(match && (match.toString()).length > maxMatch) {
- maxMatch = (match.toString()).length;
- index = i;
- }
- } catch(e) {
- // Catch errors caused by invalid profile site rules
- }
- }
- if(index > -1) {
- // Select the profile with the best match:
- this.setProfileIndex(index);
- return true;
- }
- } else {
- try {
- var regExp = new RegExp(this.getProfileSiteRule(this.getProfileIndex()),'i');
- if(regExp.test(url)) {
- return true;
- }
- } catch(e) {
- // Catch errors caused by invalid profile site rules
- }
- }
- return false;
- },
-
- setFormField: function(element,url) {
- var matchFound = false;
-
- // Apply the fieldRules of the current profile:
- matchFound = this.applyFieldRulesOnElement(element,url,this.getFieldRules());
-
- // If no match has been found, apply the fieldRules of the global profile, if enabled:
- if(!matchFound && this.autofillFormsPrefs.getBoolPref('enableGlobalProfile')) {
- // Only apply the global profile fieldRules if the current profile is not the global profile;
- if(this.getProfileIndex() != this.getGlobalProfileIndex()) {
- // Only apply the global profile if the global profile site rule matches the url:
- try {
- var regExp = new RegExp(this.getProfileSiteRule(this.getGlobalProfileIndex()),'i');
- if(regExp.test(url)) {
- matchFound = this.applyFieldRulesOnElement(element,url,this.getGlobalFieldRules());
- }
- } catch(e) {
- // Catch errors caused by invalid profile site rules
- }
- }
- }
-
- // Highlight styles:
- var highlightStyleMatch = this.autofillFormsPrefs.getCharPref('highlightStyleMatch');
- var highlightStyleNoMatch = this.autofillFormsPrefs.getCharPref('highlightStyleNoMatch');
-
- if(matchFound) {
- // Set the current element as the last matched form element:
- this.lastFormElementMatch = element;
-
- if(highlightStyleMatch) {
- // Highlight matched form fieds:
- element.setAttribute('style', highlightStyleMatch);
- }
- } else if(highlightStyleNoMatch) {
- // Highlight not matched form fieds:
- element.setAttribute('style', highlightStyleNoMatch);
- }
- },
-
- getIndexForFieldRules: function(fieldRules) {
- if(this.fieldRules) {
- for(var i=0; i<this.fieldRules.length; i++) {
- if(this.fieldRules[i] === fieldRules) {
- return i;
- }
- }
- }
- return -1;
- },
-
- fieldRuleAlternativeFactory: function(fieldRules, index) {
- var af = this;
- if(typeof arguments.callee.fieldRuleAlternative == 'undefined') {
- arguments.callee.fieldRuleAlternative = function(fieldRules, index) {
- this.fieldRules = fieldRules;
- this.index = index;
- this.fieldRule = this.fieldRules[this.index];
- return this;
- }
- arguments.callee.fieldRuleAlternative.prototype = {
- af : af,
- fieldRuleValue: null,
- fieldRuleValueRegExp: null,
- fieldRuleRegExp: null,
- siteRuleRegExp: null,
- optionsIndex: null,
- element: null,
- getValue: function() {
- if(this.fieldRuleValue === null) {
- // Replace dynamic tags if enabled:
- if(this.af.autofillFormsPrefs.getBoolPref('enableDynamicTags'))
- this.fieldRuleValue = this.af.replaceDynamicTags(this.fieldRule['fieldRuleValue']);
- else
- this.fieldRuleValue = this.fieldRule['fieldRuleValue'];
- }
- return this.fieldRuleValue;
- },
- getRule: function() {
- return this.fieldRule['fieldRuleFieldRule'];
- },
- getName: function() {
- return this.fieldRule['fieldRuleName'];
- },
- isEnabled: function() {
- return this.fieldRule['fieldRuleEnabled'];
- },
- isURLMatching: function(url) {
- if(this.siteRuleRegExp === null) {
- this.siteRuleRegExp = new RegExp(this.fieldRule['fieldRuleSiteRule'],'i');
- }
- // Test if the siteRule matches the given URL:
- return this.siteRuleRegExp.test(url);
- },
- isRuleMatching: function(str) {
- if(this.fieldRuleRegExp === null) {
- this.fieldRuleRegExp = new RegExp(this.fieldRule['fieldRuleFieldRule'],'i');
- }
- // Test if the fieldRule matches the given string:
- return this.fieldRuleRegExp.test(str);
- },
- isValueMatching: function(str) {
- try {
- if(this.fieldRuleValueRegExp === null) {
- this.fieldRuleValueRegExp = new RegExp(this.getValue(),'i');
- }
- // Test if the value as regular expression matches the given string:
- return this.fieldRuleValueRegExp.test(str);
- } catch(e) {
- // If turning the value into a regular expression fails, compare the strings:
- return (str == this.getValue());
- }
- },
- isOverwrite: function() {
- // This setting defines if existing field contents should be overwritten
- // and if checkboxes and radio buttons should be checked or unchecked
- // and if selection options should be selected or unselected:
- return this.fieldRule['fieldRuleOverwrite']
- },
- getIndex: function() {
- return this.index;
- },
- getOptionsIndex: function() {
- return this.optionsIndex;
- },
- setOptionsIndex: function(optionsIndex) {
- this.optionsIndex = optionsIndex;
- },
- getElement: function() {
- return this.element;
- },
- setElement: function(element) {
- this.element = element;
- },
- clone: function() {
- // This creates only a shallow copy,
- // though we only need a shallow copy:
- var clone = new this.constructor();
- for(var key in this) {
- clone[key] = this[key];
- }
- return clone;
- }
- }
- }
- if(this.fieldRuleAlternativesCache == null) {
- this.fieldRuleAlternativesCache = new Object();
- }
- var identifier = this.getIndexForFieldRules(fieldRules)+'-'+index;
- if(!this.fieldRuleAlternativesCache[identifier]) {
- this.fieldRuleAlternativesCache[identifier] = new arguments.callee.fieldRuleAlternative(
- fieldRules,
- index
- );
- } else {
- // Clone the cached alternative and set the clone as new cached element:
- this.fieldRuleAlternativesCache[identifier] = this.fieldRuleAlternativesCache[identifier].clone()
- }
- return this.fieldRuleAlternativesCache[identifier];
- },
-
- getLabelForElement: function(element) {
- if(element.form && element.id) {
- // Method to retrieve the textual content of the label assigned to the form element:
- var labels = element.form.getElementsByTagName('label');
- for(var i=0; i<labels.length; i++) {
- if(labels[i].htmlFor && labels[i].htmlFor == element.id) {
- // label elements may contain other inline elements,
- // so we just use the innerHTML content and strip it of all HTML tags
- // whitespace is removed from the beginning and end of the string for convenience:
- return this.trim(this.stripTags(labels[i].innerHTML));
- }
- }
- }
- if(!this.autofillFormsPrefs.getBoolPref('labelsStrictMode')) {
- return this.getLabelCloseToElement(element);
- }
- return null;
- },
-
- getLabelCloseToElement: function(element) {
- var label = null;
- var node = element;
- var nextNode;
- if(element.type == 'checkbox' || element.type == 'radio') {
- // For checkboxes and radio buttons the label is usually placed as nextSibling:
- nextNode = 'nextSibling';
- } else {
- // For other elements the label is usually placed as previousSibling:
- nextNode = 'previousSibling';
- }
- // Check if a sibling contains the element label:
- while(node[nextNode]) {
- node = node[nextNode];
- label = this.getNodeTextContent(node, true);
- if(label) {
- return label;
- }
- }
- // Parse the siblings of the parentNode:
- node = element.parentNode;
- if(node) {
- while(node[nextNode]) {
- node = node[nextNode];
- label = this.getNodeTextContent(node, true);
- if(label) {
- return label;
- }
- }
- // If the parentNode of the parentNode is a table cell,
- // also parse the siblings of this node:
- node = element.parentNode.parentNode;
- if(node && node.nodeName == 'TD') {
- while(node[nextNode]) {
- node = node[nextNode];
- label = this.getNodeTextContent(node, true);
- if(label) {
- return label;
- }
- }
- }
- }
- return null;
- },
-
- getNodeTextContent: function(node, trim) {
- // Get the text content from the current node or its child nodes:
- var text;
- if(node.nodeType == 3) {
- // nodeType 3 is a text node:
- text = node.nodeValue;
- } else {
- // Do not follow selection nodes, script nodes or noscript nodes:
- if(node.nodeName == 'SELECT' || node.nodeName == 'SCRIPT' || node.nodeName == 'NOSCRIPT') {
- return '';
- }
- text = '';
- for(var i=0; i<node.childNodes.length; i++) {
- text += this.getNodeTextContent(node.childNodes[i]);
- }
- }
- if(trim) {
- return this.trim(text);
- } else {
- return text;
- }
- },
-
- applyFieldRulesOnElement: function(element,url,fieldRules) {
-
- var labelValue = this.autofillFormsPrefs.getBoolPref('matchAgainstLabels') ?
- this.getLabelForElement(element) : null;
-
- var positionString = this.autofillFormsPrefs.getBoolPref('matchAgainstPositions') ?
- this.currentFormIndex + this.autofillFormsPrefs.getCharPref('positionsIdentifier')
- + this.currentElementIndex : null;
-
- var fieldRuleAlternatives = new Array();
-
- // Go through the list of fieldRules:
- for(var i=0; i < fieldRules.length; i++) {
-
- var rule = this.fieldRuleAlternativeFactory(fieldRules, i);
-
- // Skip this rule if
- // a) the rule is disabled and disabled rules are to be ignored or
- // b) the current URL is not matching the siteRule or
- // c) all of the following are false:
- // 1) the element name does not match the fieldRule
- // 2) label matching is disabled or the element label does not match the fieldRule
- // 3) the element name is not empty or the element id does not match the fieldRule
- // 4) position matching is disabled or the position does not match the fieldRule
- if( !rule.isEnabled() &&
- this.autofillFormsPrefs.getBoolPref('ignoreDisabledRulesOnAutofill') ||
- !rule.isURLMatching(url) ||
- (
- !rule.isRuleMatching(element.name) &&
- (labelValue === null || !rule.isRuleMatching(labelValue)) &&
- (element.name || !rule.isRuleMatching(element.id)) &&
- (positionString === null || !rule.isRuleMatching(positionString))
- )
- ) {
- if(fieldRuleAlternatives.length > 0) {
- // Break out of the loop, if we already have an alternative:
- break;
- } else {
- continue;
- }
- }
-
- if(element.type == 'select-one' || element.type == 'select-multiple') {
- // Go through the selection options:
- for(var j = 0; j < element.options.length; j++) {
- // Match either the value or the text (the selection option label):
- if(rule.isValueMatching(element.options[j].value) || rule.isValueMatching(element.options[j].text)) {
- // Remember the matching option:
- rule.setOptionsIndex(j);
- // Remember the element:
- rule.setElement(element);
- // Add a clone of the alternative and continue to see if the value matches several options:
- fieldRuleAlternatives.push(rule.clone());
- }
- }
- } else if(element.type == 'checkbox' || element.type == 'radio') {
- if(rule.isValueMatching(element.value)) {
- // Remember the element:
- rule.setElement(element);
- // Add the alternative:
- fieldRuleAlternatives.push(rule);
- // Only one rule has to match a checkbox/radio button, so we break out of the loop:
- break;
- }
- } else {
- // Remember the element:
- rule.setElement(element);
- // Add the alternative:
- fieldRuleAlternatives.push(rule);
- }
- if(this.autofillFormsPrefs.getBoolPref('callOnChangeAfterFillingFields')) {
- this.fireEvent(element,'change')
- }
- }
-
- return this.applyFieldRulesAlternativesOnElement(element,fieldRuleAlternatives);
- },
-
- applyFieldRulesAlternativesOnElement: function(element,fieldRuleAlternatives) {
- if(fieldRuleAlternatives.length == 0) {
- return false;
- }
-
- if (this.autofillFormsPrefs.getBoolPref('focusLastFormElementMatch')) {
- element.focus();
- }
-
- // Add a box (with some help from Mike Ratcliffe)
- // http://groups.google.com/group/firebug/browse_thread/thread/7d4bd89537cd24e7/2c9483d699efe257?hl=en
- // TODO: why doesn't getBoundingClientRect return the absolute coordinates of the element?
- // At the moment, I'm looking at the offset of the doc.body and use that to calculate the absolute coordinates
- // what's the offset -4,+1 pixel relative to? the size of the window border?
- //
- var doc = this.getDoc();
- var div1 = doc.createElement('div');
-
- var rect = element.getBoundingClientRect();
- var rectBody = doc.body.getBoundingClientRect();
-
- //Firebug.Console.log(element);
- //Firebug.Console.log(rect.left+' '+rect.top+' '+rect.right+' '+rect.bottom+' '+rect.width+' '+rect.height);
- //Firebug.Console.log(rectBody.left+' '+rectBody.top+' '+rectBody.right+' '+rectBody.bottom+' '+rectBody.width+' '+rectBody.height);
-
- //maybe something here...
- //Firebug.Console.log(element.clientLeft+' '+element.clientTop)
- //Firebug.Console.log(element.scrollLeft+' '+element.scrollTop)
-
- //Firebug.Console.log(doc.body)
- //Firebug.Console.log(rect)
- //Firebug.Console.log(rectBody)
-
- //div1.setAttribute('id', 'autoformHighlight');
- div1.setAttribute('style', 'position:absolute;z-index:2147483646'
- + ';border-width: 2px; border-color: red; border-style:solid'
- + ';left:'+(rect.left-rectBody.left-1)+'px'
- + ';top:'+(rect.top-rectBody.top+3)+'px'
- + ';width:'+rect.width+'px'
- + ';height:'+rect.height+'px'
- );
- doc.body.appendChild(div1);
-
- // Use all alternatives for select-multiple elements:
- if(element.type == 'select-multiple') {
- for(var i=0; i < fieldRuleAlternatives.length; i++) {
- var rule = fieldRuleAlternatives[i];
- if(rule.isOverwrite()) {
- element.options[rule.getOptionsIndex()].selected = true;
- } else {
- element.options[rule.getOptionsIndex()].selected = false;
- }
- }
- doc.body.removeChild(div1);
- return true;
- }
-
- // Select the alternatives index (displays a selection dialog if required):
- var index = this.selectFieldRulesAlternativesIndex(fieldRuleAlternatives);
-
- if(index == -1) {
- doc.body.removeChild(div1);
- return false;
- } else {
- var rule = fieldRuleAlternatives[index];
- if(element.type == 'select-one') {
- if(rule.isOverwrite()) {
- element.options[rule.getOptionsIndex()].selected = true;
- } else {
- element.options[rule.getOptionsIndex()].selected = false;
- }
- } else if(element.type == 'checkbox') {
- if(rule.isOverwrite()) {
- element.checked = true;
- } else {
- element.checked = false;
- }
- } else if(element.type == 'radio') {
- try {
- // Rules matching radio elements are stored and handled as group
- // at the end of each form loop with the applyStoredFieldRulesAlternatives method:
- if(!this.fieldRuleAlternativesHash[element.name]) {
- this.fieldRuleAlternativesHash[element.name] = new Array();
- }
- this.fieldRuleAlternativesHash[element.name].push(rule);
- } catch(e) {
- this.log(e);
- doc.body.removeChild(div1);
- return false;
- }
- } else {
- if(!element.value || rule.isOverwrite()) {
- if(element.type == 'textarea') {
- // Replace control character placeholders:
- element.value = this.replaceControlCharacterPlaceholders(rule.getValue());
- } else {
- element.value = rule.getValue();
- }
- }
- }
- if(this.autofillFormsPrefs.getBoolPref('callOnChangeAfterFillingFields')) {
- this.fireEvent(element,'change')
- }
-
-
- }
-
- //remove the div, not needed anymore
- doc.body.removeChild(div1);
- return true;
- },
-
- fireEvent: function(element,anEvent) {
- var evt = document.createEvent("HTMLEvents");
- evt.initEvent(anEvent, true, true ); // event type,bubbling,cancelable
- return !element.dispatchEvent(evt);
- },
-
- applyStoredFieldRulesAlternatives: function() {
- for(var key in this.fieldRuleAlternativesHash) {
- var fieldRuleAlternatives = this.filterRealFieldRuleAlternatives(
- this.fieldRuleAlternativesHash[key]
- );
- var index = this.selectFieldRulesAlternativesIndex(fieldRuleAlternatives);
- if(index != -1) {
- var rule = fieldRuleAlternatives[index];
- // This is currently only used for radio input fields:
- if(rule.isOverwrite()) {
- rule.getElement().checked = true;
- } else {
- rule.getElement().checked = false;
- }
- }
- }
- },
-
- filterRealFieldRuleAlternatives: function(fieldRuleAlternatives) {
- // Sort the fieldRuleAlternatives by index:
- fieldRuleAlternatives.sort(this.compareFieldRuleAlternativesByIndex);
- // Make sure only real Alternatives (placed next to each other) are included:
- for(var i=1; i<fieldRuleAlternatives.length; i++) {
- // If the fieldRules index is more than one step larger than the previous one,
- // the remaining array items can be sliced off - they are no real Alternatives:
- if(fieldRuleAlternatives[i].getIndex()-1 > fieldRuleAlternatives[i-1].getIndex()) {
- fieldRuleAlternatives = fieldRuleAlternatives.slice(0, i);
- break;
- }
- }
- return fieldRuleAlternatives;
- },
-
- compareFieldRuleAlternativesByIndex: function(ruleA, ruleB) {
- if(ruleA.getIndex() < ruleB.getIndex()) {
- return -1;
- } else if(ruleA.getIndex() > ruleB.getIndex()) {
- return 1;
- }
- return 0;
- },
-
- getFieldRulesAlternativeLabel: function(rule) {
- // This method returns a label for this alternative
- // to be displayed on the alternatives selection
- switch(rule.getElement().type) {
- case 'select-multiple':
- case 'select-one':
- // Use the options text:
- return rule.getElement().options[rule.getOptionsIndex()].text;
- case 'radio':
- case 'checkbox':
- // Try to retrieve the element label:
- var label = this.getLabelForElement(rule.getElement());
- // Remove the colon, if present:
- if(label && label.charAt(label.length-1) == ':') {
- label = label.substr(0, label.length-1);
- }
- // If no label could be found,
- // use the element value:
- if(!label) {
- label = rule.getElement().value;
- }
- return label;
- default:
- // Use the calculated value:
- return rule.getValue();
- }
- },
-
- selectFieldRulesAlternativesIndex: function(fieldRuleAlternatives) {
- // Display a selection prompt if we have alternatives and no alternativesIndex has been set yet
- // or the rememberAlternativesIndex setting is false or the saved alternativesLength is different:
- if(fieldRuleAlternatives.length > 1) {
- // When alternatives are disabled, return either 0 (remember the alternative)
- // or cycle through the available alternatives.
- if(this.autofillFormsPrefs.getBoolPref('disableAlternatives') == true) {
- var fieldRuleAlternativesIndex = 0;
- /*
- //todo take into account multiple instances of the form field. Can't increase the index blindly...
- if(this.autofillFormsPrefs.getBoolPref('rememberAlternativesIndex') == false) {
- fieldRuleAlternativesIndex = this.fieldRuleAlternativesIndex;
- if (this.fieldRuleAlternativesIndex == fieldRuleAlternatives.length-1) {
- this.fieldRuleAlternativesIndex = 0;
- }
- else {
- this.fieldRuleAlternativesIndex += 1;
- }
- }
- */
- return fieldRuleAlternativesIndex;
- }
-
- if(this.autofillFormsPrefs.getBoolPref('rememberAlternativesIndex') == false
- || this.fieldRuleAlternativesIndex === null
- || fieldRuleAlternatives.length != this.fieldRuleAlternativesLength) {
- // The selection list displays the index number and the current fieldRuleValues:
- var list = new Array();
- var maxFigureLength = fieldRuleAlternatives.length.toString().length;
- for(var i=0; i < fieldRuleAlternatives.length; i++) {
- list.push(
- this.addLeadingZeros(i+1, maxFigureLength)
- + '. '
- + this.getFieldRulesAlternativeLabel(fieldRuleAlternatives[i])
- + ' - '
- + fieldRuleAlternatives[i].getName()
- );
- }
- var selected = {};
- // Show the selection prompt:
- var ok = this.getPrompts().select(
- window,
- this.getStringBundle().getString('alternativesSelectionWindowTitle'),
- this.getStringBundle().getString('alternativesSelectionPrompt'),
- list.length,
- list,
- selected
- );
- // Save the selected alternatives index, return -1 on cancel:
- if(ok)
- this.fieldRuleAlternativesIndex = selected.value;
- else
- return -1;
-
- this.fieldRuleAlternativesLength = fieldRuleAlternatives.length;
- }
- // Use the fieldRuleAlternative with the selected fieldRuleAlternativesIndex:
- return this.fieldRuleAlternativesIndex;
- } else if(fieldRuleAlternatives.length == 1) {
- return 0;
- }
- return -1;
- },
-
- stripTags: function(str) {
- if (!arguments.callee.regExp) {
- arguments.callee.regExp = new RegExp('<\\/?[^>]+?>', 'g');
- }
- // Return string stripped from HTML tags:
- return str.replace(arguments.callee.regExp, '');
- },
-
- trim: function(str) {
- if (!arguments.callee.regExp) {
- arguments.callee.regExp = new RegExp('(?:^\\s+)|(?:\\s+$)', 'g');
- }
- // Return string with whitespace removed at beginning and end of the string:
- return str.replace(arguments.callee.regExp, '');
- },
-
- initProfilesPopupMenu: function(event) {
- var menupopup = event.target;
- // Remove all children nodes:
- while(menupopup.hasChildNodes()) {
- menupopup.removeChild(menupopup.firstChild);
- }
- // Add the profile labels as menu items:
- for(var i=0; i < this.getProfileLabels().length; i++) {
- var menuitem = document.createElement('menuitem');
- menuitem.setAttribute('label', this.getProfileLabel(i));
- menuitem.setAttribute('oncommand', 'autofillForms.setProfileIndex('+i+');');
- menuitem.setAttribute('type', 'radio');
- if(i == this.getProfileIndex()) {
- menuitem.setAttribute('checked', true);
- }
- menupopup.appendChild(menuitem);
- }
- },
-
- initManualFillContextMenu: function(event) {
- var menupopup = event.target;
- // Remove all children nodes:
- while(menupopup.hasChildNodes()) {
- menupopup.removeChild(menupopup.firstChild);
- }
-
- var authenticationNeeded = false;
- if(this.autofillFormsPrefs.getBoolPref('storeEncrypted')) {
- // Determine if a master password is set and the user has not been authenticated yet:
- authenticationNeeded = this.getMasterSecurityDevice().getInternalKeyToken().needsLogin()
- && !this.getMasterSecurityDevice().getInternalKeyToken().isLoggedIn();
- }
-
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Always retrieve the profile labels from file if useConfigDirectory is enabled:
- this.profileLabels = null;
- }
-
- // Check if only one profile is to be shown:
- if((this.getFormFieldsContextMenuProfileIndex() != -3) || (this.getProfileLabels().length == 1)) {
- var profileIndex = (this.getFormFieldsContextMenuProfileIndex() == -2)
- ? this.getProfileIndex() : this.getFormFieldsContextMenuProfileIndex();
- if(authenticationNeeded) {
- var menuitem = document.createElement('menuitem');
- menuitem.setAttribute('label', this.getProfileLabel(profileIndex)+'...');
- menuitem.setAttribute(
- 'oncommand',
- 'autofillForms.authenticateAndShowManualFillDialog('+profileIndex+');'
- );
- menupopup.appendChild(menuitem);
- } else {
- this.initManualFillProfileContextMenu(event, profileIndex);
- }
- return;
- }
-
- // Add the profile labels as menus or menuitems if authentication is needed:
- for(var i=0; i < this.getProfileLabels().length; i++) {
- if(authenticationNeeded) {
- var menuitem = document.createElement('menuitem');
- menuitem.setAttribute('label', this.getProfileLabel(i)+'...');
- menuitem.setAttribute(
- 'oncommand',
- 'autofillForms.authenticateAndShowManualFillDialog('+i+');'
- );
- menupopup.appendChild(menuitem);
- } else {
- var menu = document.createElement('menu');
- menu.setAttribute('label', this.getProfileLabel(i));
-
- // Add a menupopup for each profile:
- var profilemenupopup = document.createElement('menupopup');
- profilemenupopup.setAttribute(
- 'onpopupshowing',
- 'if(event.target == this) autofillForms.initManualFillProfileContextMenu(event, '+i+');'
- );
- menu.appendChild(profilemenupopup);
- menupopup.appendChild(menu);
- }
- }
- },
-
- initManualFillProfileContextMenu: function(event, profileID) {
- var menupopup = event.target;
- // Remove all children nodes:
- while(menupopup.hasChildNodes()) {
- menupopup.removeChild(menupopup.firstChild);
- }
- var menuPopupMore;
- // Add the profile field rules as menu items:
- for(var i=0; i < this.getFieldRules(profileID).length; i++) {
- var menuitem = document.createElement('menuitem');
- menuitem.setAttribute('label', this.getFieldRules(profileID)[i]['fieldRuleName']);
- menuitem.setAttribute('oncommand', 'autofillForms.fillTargetFormField('+profileID+','+i+');');
- if(this.getFieldRules(profileID)[i]['fieldRuleEnabled']) {
- menupopup.appendChild(menuitem);
- } else {
- // Add disabled items to a "More..." menu:
- if(!menuPopupMore) {
- menuPopupMore = document.createElement('menupopup');
- }
- menuPopupMore.appendChild(menuitem);
- }
- }
- if(menuPopupMore) {
- if(!menupopup.hasChildNodes()) {
- // All field rules of this profile are disabled, so no need to create a submenu:
- while(menuPopupMore.hasChildNodes()) {
- // appendChild removes the node from the current parent node
- // and adds it to the new parent node:
- menupopup.appendChild(menuPopupMore.firstChild);
- }
- } else {
- // Append the "More..." menu:
- var menuMore = document.createElement('menu');
- menuMore.setAttribute('label', this.getStringBundle().getString('contextMenuMore'));
- menuMore.appendChild(menuPopupMore);
- menupopup.appendChild(menuMore);
- }
- }
- // Reset object to release used memory:
- this.fieldRules = null;
- },
-
- authenticateAndShowManualFillDialog: function(profileID) {
- try {
- Components.classes['@mozilla.org/security/pk11tokendb;1']
- .getService(Components.interfaces.nsIPK11TokenDB).getInternalKeyToken().login(false);
-
- var prompts = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
- .getService(Components.interfaces.nsIPromptService);
- // The selection and the subselection lists:
- var list = new Array();
- var listMore;
- // Hashs mapping the list positions to the original indices:
- var listIndexMapping = new Object();;
- var listMoreIndexMapping;
- for(var i=0; i < this.getFieldRules(profileID).length; i++) {
- if(this.getFieldRules(profileID)[i]['fieldRuleEnabled']) {
- list.push(this.getFieldRules(profileID)[i]['fieldRuleName']);
- listIndexMapping[list.length-1] = i;
- } else {
- // Add disabled items to a "More..." list:
- if(!listMore) {
- listMore = new Array();
- listMoreIndexMapping = new Object();
- }
- listMore.push(this.getFieldRules(profileID)[i]['fieldRuleName']);
- listMoreIndexMapping[listMore.length-1] = i;
- }
- }
- if(listMore) {
- // If all field rules of this profile are disabled, there is no need of a sublist:
- if(!list.length) {
- list = listMore;
- listIndexMapping = listMoreIndexMapping;
- listMore = null;
- listMoreIndexMapping = null;
- } else {
- list.push(this.getStringBundle().getString('contextMenuMore'));
- }
- }
- var selected = {};
- var ok = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
- .getService(Components.interfaces.nsIPromptService)
- .select(
- window,
- null, // Window title - defaults to locale version of "Select"
- null, // Prompt text - defaults to empty string
- list.length,
- list,
- selected
- );
- if(ok) {
- // If "More..." is selected, show the disabled items as selection list:
- if(listMore && selected.value == list.length-1) {
- selected = {};
- ok = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
- .getService(Components.interfaces.nsIPromptService)
- .select(
- window,
- null, // Window title - defaults to locale version of "Select"
- null, // Prompt text - defaults to empty string
- listMore.length,
- listMore,
- selected
- );
- if(ok) {
- this.fillTargetFormField(
- profileID,
- listMoreIndexMapping[selected.value]
- );
- }
- } else {
- this.fillTargetFormField(
- profileID,
- listIndexMapping[selected.value]
- );
- }
- }
- } catch(e) {
- // Authentication with master security device failed
- }
- // Reset object to release used memory:
- this.fieldRules = null;
- },
-
- fillTargetFormField: function(profileID, ruleID) {
- if(this.targetFormField) {
- var value = this.getFieldRules(profileID)[ruleID]['fieldRuleValue'];
- // Replace dynamic tags if enabled:
- if(this.autofillFormsPrefs.getBoolPref('enableDynamicTags')) {
- value = this.replaceDynamicTags(value);
- }
- try {
- // Try to use selection information:
- var newCursorPos = this.targetFormField.selectionStart + value.length;
- this.targetFormField.value = this.targetFormField.value.substr(0, this.targetFormField.selectionStart)
- + value
- + this.targetFormField.value.substr(this.targetFormField.selectionEnd);
- // Adjust the cursor position:
- this.targetFormField.selectionEnd = newCursorPos;
- this.targetFormField.selectionStart = newCursorPos;
- } catch(e) {
- // This input field does not support selections - just try to set the value:
- try {
- this.targetFormField.value = value;
- } catch(e) {
- // Catch errors if value could not be set on the form field
- }
- }
- // Reset objects to release used memory:
- this.fieldRules = null;
- this.dynamicTags = null;
- this.dynamicTagCodes = null;
- }
- },
-
- tooltip: function(event) {
- if (!document.tooltipNode) {
- return;
- }
- // Get the tooltip node:
- var tooltip = document.getElementById('autofillFormsTooltip');
- if(tooltip) {
- // Add the associated tooltip content for each toolbar button menu item, toolbar button and statusbar icon:
- if(document.tooltipNode.id == 'autofillFormsButton' || document.tooltipNode.id == 'autofillFormsPanelIcon') {
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Always retrieve the profile labels from file if useConfigDirectory is enabled:
- this.profileLabels = null;
- this.tooltipCurrentProfile = null;
- }
- if(!this.tooltipCurrentProfile || !this.tooltipGrid) {
- // Remove all children nodes:
- while(tooltip.hasChildNodes()) {
- tooltip.removeChild(tooltip.firstChild);
- }
- // Add the current profile label:
- tooltip.appendChild(this.getTooltipCurrentProfile());
- // Add the tooltip grid with the command labels, mouse buttons and keyboard shortcuts:
- tooltip.appendChild(this.getTooltipGrid());
- }
- } else {
- // Don't show tooltips for the toolbar button menu items:
- event.preventDefault();
- }
- }
- },
-
- getTooltipCurrentProfile: function() {
- if(!this.tooltipCurrentProfile) {
- var hbox = document.createElement('hbox');
- hbox.setAttribute(
- 'id',
- 'autofillFormsTooltipCurrentProfile'
- );
- var label = document.createElement('label');
- label.setAttribute(
- 'value',
- this.getStringBundle().getString('currentProfileLabel')
- );
- label.setAttribute(
- 'id',
- 'autofillFormsTooltipCurrentProfileCaption'
- );
- hbox.appendChild(label);
- label = label.cloneNode(false);
- label.setAttribute(
- 'value',
- this.getProfileLabel(this.getProfileIndex())
- );
- label.setAttribute(
- 'id',
- 'autofillFormsTooltipCurrentProfileLabel'
- );
- hbox.appendChild(label);
- this.tooltipCurrentProfile = hbox;
- }
- return this.tooltipCurrentProfile;
- },
-
- getTooltipGrid: function() {
- if(!this.tooltipGrid) {
- var commands = new Array();
- for(var property in this.shortcut) {
- commands.push(new Array(
- this.getStringBundle().getString('tooltip'+property.replace(/shortcut/,'')),
- this.getFormattedMouseButton(this.getMouseButton('mouseS'+property.substr(1))),
- this.getFormattedShortcut(this.getShortcut(property))
- ));
- }
- var grid = document.createElement('grid');
- grid.setAttribute(
- 'id',
- 'autofillFormsTooltipGrid'
- );
- var columns = document.createElement('columns');
- var column = document.createElement('column');
- var rows = document.createElement('rows');
- var row = document.createElement('row');
- var label = document.createElement('label');
- columns.appendChild(column);
- columns.appendChild(column.cloneNode(false));
- columns.appendChild(column.cloneNode(false));
- grid.appendChild(columns);
- // Create the column headers:
- label.setAttribute(
- 'class',
- 'autofillFormsTooltipGridHeader'
- );
- label.setAttribute(
- 'value',
- this.getStringBundle().getString('command')
- );
- row.appendChild(label);
- label = label.cloneNode(false);
- label.setAttribute(
- 'value',
- this.getStringBundle().getString('mousebutton')
- );
- row.appendChild(label);
- label = label.cloneNode(false);
- label.setAttribute(
- 'value',
- this.getStringBundle().getString('keyboardShortcut')
- );
- row.appendChild(label);
- rows.appendChild(row);
- // Create a row for each command:
- for(var i=0; i<commands.length; i++) {
- row = row.cloneNode(false);
- // Skip if neither mouseButton nor keyboard shortcut is set:
- if(!commands[i][1] && !commands[i][2]) {
- continue;
- }
- for(var j=0; j<commands[i].length; j++) {
- label = label.cloneNode(false);
- label.setAttribute(
- 'value',
- commands[i][j]
- );
- if(j == 0) {
- label.setAttribute(
- 'class',
- 'autofillFormsTooltipGridCommand'
- );
- } else if(j == 1) {
- label.setAttribute(
- 'class',
- 'autofillFormsTooltipGridMouseButton'
- );
- } else {
- label.setAttribute(
- 'class',
- 'autofillFormsTooltipGridKeyboardShortcut'
- );
- }
- row.appendChild(label);
- }
- rows.appendChild(row);
- }
- grid.appendChild(rows);
- this.tooltipGrid = grid;
- }
- return this.tooltipGrid;
- },
-
- resetAllProfiles: function() {
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- // Confirmation dialog:
- if(!this.getPrompts().confirm(
- null,
- this.getStringBundle().getString('resetAllProfilesTitle'),
- this.getStringBundle().getString('resetAllProfilesText')
- )
- ) {
- return;
- }
- }
-
- // Reset the user preferences:
- if(this.autofillFormsPrefs.prefHasUserValue('useConfigDirectory')) {
- this.autofillFormsPrefs.clearUserPref('useConfigDirectory');
- }
- if(this.autofillFormsPrefs.prefHasUserValue('storeEncrypted')) {
- this.autofillFormsPrefs.clearUserPref('storeEncrypted');
- }
- if(this.autofillFormsPrefs.prefHasUserValue('profileIndex')) {
- this.autofillFormsPrefs.clearUserPref('profileIndex');
- }
- if(this.autofillFormsPrefs.prefHasUserValue('profileLabels')) {
- this.autofillFormsPrefs.clearUserPref('profileLabels');
- }
- if(this.autofillFormsPrefs.prefHasUserValue('profileSiteRules')) {
- this.autofillFormsPrefs.clearUserPref('profileSiteRules');
- }
- if(this.autofillFormsPrefs.prefHasUserValue('fieldRules')) {
- this.autofillFormsPrefs.clearUserPref('fieldRules');
- }
-
- this.profileIndex = null;
- this.profileLabels = null;
- this.profileSiteRules = null;
- this.fieldRules = null;
-
- // Re-init the profiles lists:
- this.initProfilesLists();
- // Re-init the fieldRules tree:
- this.initTree();
- // Re-initialize the simple interface:
- this.initSimpleInterface();
-
- if(this.tree && this.selection) {
- try {
- // Clear out the fieldRules tree selections
- this.selection.select(-1);
- } catch(e) {
- this.log(e);
- }
- }
- },
-
- initProfilesLists: function(event) {
- // The profiles tree:
- this.initProfilesTree();
-
- // Editable profiles menu list:
- var profilesMenuList = document.getElementById('profilesMenuList');
- if(profilesMenuList) {
- profilesMenuList.removeAllItems();
- for(var i=0; i < this.getProfileLabels().length; i++) {
- profilesMenuList.appendItem(
- this.getProfileLabel(i)
- );
- }
- profilesMenuList.selectedIndex = this.getProfileIndex();
- }
- // Simple interface profiles menu list:
- var simpleInterfaceProfileMenuList = document.getElementById('simpleInterfaceProfileMenuList');
- if(simpleInterfaceProfileMenuList) {
- simpleInterfaceProfileMenuList.removeAllItems();
- for(var i=0; i < this.getProfileLabels().length; i++) {
- simpleInterfaceProfileMenuList.appendItem(
- this.getProfileLabel(i)
- );
- }
- simpleInterfaceProfileMenuList.selectedIndex = this.getProfileIndex();
- }
- // Global profile selection:
- var globalProfileMenuList = document.getElementById('globalProfileMenuList');
- if(globalProfileMenuList) {
- globalProfileMenuList.removeAllItems();
- for(var i=0; i < this.getProfileLabels().length; i++) {
- globalProfileMenuList.appendItem(
- this.getProfileLabel(i)
- );
- }
- globalProfileMenuList.selectedIndex = this.getGlobalProfileIndex();
- }
- // Form fields context menu selection:
- var contextMenuProfileMenuList = document.getElementById('contextMenuProfileMenuList');
- if(contextMenuProfileMenuList) {
- // The first 3 items are "All profiles", "Active profile" and a menuseparator:
- while(contextMenuProfileMenuList.firstChild.childNodes[3]) {
- // The more convenient getItemAtIndex does not seem to work with Firefox versions < 3,
- // so we use DOM methods on the menupopup child node of the menu node instead:
- contextMenuProfileMenuList.firstChild.removeChild(
- contextMenuProfileMenuList.firstChild.childNodes[3]
- );
- }
- for(var i=0; i < this.getProfileLabels().length; i++) {
- contextMenuProfileMenuList.appendItem(
- this.getProfileLabel(i)
- );
- }
- contextMenuProfileMenuList.selectedIndex
- = this.getFormFieldsContextMenuProfileIndex()+3;
- }
-
- // The profile site rule textbox:
- this.initProfileSiteRuleTextBox();
- },
-
- updateProfilesLists: function() {
- // The more convenient getItemAtIndex does not seem to work with Firefox versions < 3,
- // so we use DOM methods on the menupopup child node of the menu nodes instead:
-
- // Editable profiles menu list:
- var profilesMenuList = document.getElementById('profilesMenuList');
- if(profilesMenuList) {
- profilesMenuList
- .firstChild.childNodes[this.getProfileIndex()].label
- = this.getProfileLabel(this.getProfileIndex());
- }
- // Simple interface profiles menu list:
- var simpleInterfaceProfileMenuList = document.getElementById('simpleInterfaceProfileMenuList');
- if(simpleInterfaceProfileMenuList) {
- simpleInterfaceProfileMenuList
- .firstChild.childNodes[this.getProfileIndex()].label
- = this.getProfileLabel(this.getProfileIndex());
- }
- // Global profile selection:
- var globalProfileMenuList = document.getElementById('globalProfileMenuList');
- if(globalProfileMenuList) {
- globalProfileMenuList
- .firstChild.childNodes[this.getProfileIndex()].label
- = this.getProfileLabel(this.getProfileIndex());
- }
- // Form fields context menu selection:
- var contextMenuProfileMenuList = document.getElementById('contextMenuProfileMenuList');
- if(contextMenuProfileMenuList) {
- // The first 3 items are "All profiles", "Active profile" and a menuseparator:
- contextMenuProfileMenuList
- .firstChild.childNodes[this.getProfileIndex()+3].label
- = this.getProfileLabel(this.getProfileIndex());
- }
- // The profiles tree:
- if(this.profilesTreeBox) {
- this.profilesTreeBox.invalidateRow(this.getProfileIndex());
- }
- },
-
- getProfileIndex: function() {
- if(this.profileIndex == null)
- this.profileIndex = this.autofillFormsPrefs.getIntPref('profileIndex');
- return this.profileIndex;
- },
-
- setProfileIndex: function(index) {
- if(this.profileIndex == index)
- return;
-
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- this.autofillFormsPrefs.setIntPref('profileIndex',parseInt(index));
- // Update the tree view if present:
- if(this.tree) {
- // The settings page doesn't observe preferences changes - set the profileIndex manually:
- this.profileIndex = index;
- // Re-init the tree:
- this.initTree();
- // Re-initialize the simple interface:
- this.initSimpleInterface();
- }
- // Update the profiles tree selection if present and not already updated:
- if(this.profilesTree && this.profilesSelection.currentIndex != index) {
- // Select the current profile:
- this.profilesSelection.select(index);
-
- // Ensure row is visible (scrolls if not):
- this.profilesTreeBox.ensureRowIsVisible(index);
- }
- // Editable profiles menu list:
- var profilesMenuList = document.getElementById('profilesMenuList');
- if(profilesMenuList) {
- profilesMenuList.selectedIndex = this.getProfileIndex();
- }
- // Simple interface profiles menu list:
- var simpleInterfaceProfileMenuList = document.getElementById('simpleInterfaceProfileMenuList');
- if(simpleInterfaceProfileMenuList) {
- simpleInterfaceProfileMenuList.selectedIndex = this.getProfileIndex();
- }
-
- // The profile site rule textbox:
- this.initProfileSiteRuleTextBox();
- },
-
- getGlobalProfileIndex: function() {
- if(this.globalProfileIndex == null) {
- this.globalProfileIndex = this.autofillFormsPrefs.getIntPref('globalProfileIndex');
- }
- return this.globalProfileIndex;
- },
-
- setGlobalProfileIndex: function(index) {
- if(this.globalProfileIndex == index) {
- return;
- }
- this.autofillFormsPrefs.setIntPref('globalProfileIndex',parseInt(index));
- // The settings page doesn't observe preferences changes - set the profileIndex manually:
- this.globalProfileIndex = index;
- },
-
- getFormFieldsContextMenuProfileIndex: function() {
- if(this.formFieldsContextMenuProfileIndex == null) {
- this.formFieldsContextMenuProfileIndex
- = this.autofillFormsPrefs.getIntPref('formFieldsContextMenuProfileIndex');
- }
- return this.formFieldsContextMenuProfileIndex;
- },
-
- setFormFieldsContextMenuProfileIndex: function(index) {
- if(this.formFieldsContextMenuProfileIndex == index) {
- return;
- }
- this.autofillFormsPrefs.setIntPref('formFieldsContextMenuProfileIndex',parseInt(index));
- // The settings page doesn't observe preferences changes - set the profileIndex manually:
- this.formFieldsContextMenuProfileIndex = index;
- },
-
- getProfileLabelsFile: function() {
- var file = this.getConfigDirectory();
- file.append('profileLabels.txt');
- if(!file.exists()) {
- file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
- }
- return file;
- },
-
- exportProfileLabelsToConfigDirectory: function() {
- var prefString;
- // Get the profileLabels string from the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('profileLabels',Components.interfaces.nsIPrefLocalizedString)
- .data;
- if(prefString) {
- this.setFileContent(this.getProfileLabelsFile(), prefString);
- }
- },
-
- importProfileLabelsFromConfigDirectory: function() {
- var prefString;
- prefString = this.getFileContent(this.getProfileLabelsFile());
- if(prefString) {
- // Store the profileLabels as unicode string in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'profileLabels',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getProfileLabels: function() {
- if(this.profileLabels == null) {
- var prefString;
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Get the profileLabels string from the profileLabels file in the configDirectory:
- prefString = this.getFileContent(this.getProfileLabelsFile());
- }
- if(!prefString) {
- prefString = this.autofillFormsPrefs
- .getComplexValue('profileLabels',Components.interfaces.nsIPrefLocalizedString)
- .data;
- }
- // The profile labels are stored as a string with tabs as separators:
- this.profileLabels = prefString.split('\t');
- }
- return this.profileLabels;
- },
-
- setProfileLabels: function(profileLabels) {
- // Save the profile labels separated by tabs:
- var prefString = profileLabels.join('\t');
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- this.setFileContent(this.getProfileLabelsFile(), prefString);
- } else {
- this.autofillFormsPrefs.setComplexValue(
- 'profileLabels',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getProfileLabel: function(index) {
- while(this.getProfileLabels().length <= index) {
- this.getProfileLabels().push(this.getUniqueProfileLabel());
- }
- return this.getProfileLabels()[index];
- },
-
- setProfileLabel: function(index, label) {
- while(this.getProfileLabels().length <= index) {
- this.getProfileLabels().push(this.getUniqueProfileLabel());
- }
- this.getProfileLabels()[index] = label;
- // Save the profileLabels list in the preferences:
- this.setProfileLabels(this.getProfileLabels());
- },
-
- getUniqueProfileLabel: function(profileLabel) {
- if(!profileLabel) {
- profileLabel = 'Profile';
- }
-
- // Make sure the profile label is unique:
- if(!this.inArray(this.getProfileLabels(), profileLabel)) {
- return profileLabel;
- }
- var i = profileLabel.lastIndexOf(' ');
- var n = parseInt(profileLabel.substr(i+2));
- if(isNaN(n)) {
- return this.getUniqueProfileLabel(profileLabel+' (2)');
- }
- n++;
- profileLabel = profileLabel.substr(0, i)+' ('+n+')';
- return this.getUniqueProfileLabel(profileLabel);
- },
-
- changeProfileLabel: function(newProfileLabel) {
- var profilesMenuList = document.getElementById('profilesMenuList');
- if(profilesMenuList) {
- // Make sure the new profile label is safe and unique:
- newProfileLabel = this.getUniqueProfileLabel(this.makeSafe(newProfileLabel));
- // Update the label of the selected profile:
- this.setProfileLabel(this.getProfileIndex(), newProfileLabel);
- // Update the profiles textbox contents:
- profilesMenuList.inputField.value = newProfileLabel;
- document.getElementById('profileLabelTextBox').value = newProfileLabel;
- // Update the profiles lists:
- this.updateProfilesLists();
- }
- },
-
- initProfileSiteRuleTextBox: function(event) {
- var profileSiteRuleTextBox = document.getElementById('profileSiteRuleTextBox');
- if(profileSiteRuleTextBox) {
- profileSiteRuleTextBox.value = this.getProfileSiteRule(this.getProfileIndex());
- }
- },
-
- changeProfileSiteRule: function(siteRule) {
- var profileSiteRuleTextBox = document.getElementById('profileSiteRuleTextBox');
- if(profileSiteRuleTextBox) {
- // Check the regular expression before updating the profile site rules:
- try {
- siteRule = this.getRegExpStr(
- this.makeSafe(siteRule)
- );
- profileSiteRuleTextBox.value = siteRule;
- document.getElementById('profileSiteRuleTextBox2').value = siteRule;
-
- var newProfileSiteRules = this.getProfileSiteRules();
- newProfileSiteRules[this.getProfileIndex()] = siteRule;
- this.setProfileSiteRules(newProfileSiteRules);
-
- // Update the profiles tree:
- if(this.profilesTreeBox) {
- this.profilesTreeBox.invalidateRow(this.getProfileIndex());
- }
- } catch(e) {
- this.invalidRegExpAlert(e);
- }
- }
- },
-
- getProfileSiteRulesFile: function() {
- var file = this.getConfigDirectory();
- file.append('profileSiteRules.txt');
- if(!file.exists()) {
- file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
- }
- return file;
- },
-
- exportProfileSiteRulesToConfigDirectory: function() {
- var prefString;
- // Get the profileSiteRules string from the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('profileSiteRules',Components.interfaces.nsISupportsString)
- .data;
- if(prefString) {
- this.setFileContent(this.getProfileSiteRulesFile(), prefString);
- }
- },
-
- importProfileSiteRulesFromConfigDirectory: function() {
- var prefString;
- prefString = this.getFileContent(this.getProfileSiteRulesFile());
- if(prefString) {
- // Store the profileSiteRules as unicode string in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'profileSiteRules',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getProfileSiteRules: function() {
- if(this.profileSiteRules == null) {
- var prefString;
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Get the profileSiteRules string from the profileSiteRules file in the configDirectory:
- prefString = this.getFileContent(this.getProfileSiteRulesFile());
- }
- if(!prefString) {
- prefString = this.autofillFormsPrefs
- .getComplexValue('profileSiteRules',Components.interfaces.nsISupportsString)
- .data;
- }
- // The profile SiteRules are stored as a string with tabs as separators:
- this.profileSiteRules = prefString.split('\t');
- }
- return this.profileSiteRules;
- },
-
- setProfileSiteRules: function(profileSiteRules) {
- // Save the profile SiteRules separated by tabs:
- var prefString = profileSiteRules.join('\t');
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- this.setFileContent(this.getProfileSiteRulesFile(), prefString);
- } else {
- this.autofillFormsPrefs.setComplexValue(
- 'profileSiteRules',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getProfileSiteRule: function(index) {
- while(this.getProfileSiteRules().length <= index) {
- this.getProfileSiteRules().push('(?:)');
- }
- return this.getProfileSiteRules()[index];
- },
-
- setProfileSiteRule: function(index, siteRule) {
- while(this.getProfileSiteRules().length <= index) {
- this.getProfileSiteRules().push('(?:)');
- }
- this.getProfileSiteRules()[index] = siteRule;
- // Save the profileSiteRules in the preferences:
- this.setProfileSiteRules(this.getProfileSiteRules());
- },
-
- addFormAsProfile: function(event) {
- if(this.targetFormField && this.targetFormField.form) {
- var elements = this.targetFormField.form.elements;
- var doc = this.targetFormField.form.ownerDocument;
-
- var newProfile = new Array();
-
- // Go through the form elements:
- for(var i=0; i<elements.length; i++) {
- // Only use valid form fields:
- if(this.isValidFormField(elements[i])) {
- var value;
- var overwrite = true;
-
- // Create the fieldRule (from name, label or id):
- var fieldRule = this.getFieldRuleForElement(elements[i]);
-
- switch(elements[i].type) {
- case 'checkbox':
- // Add a rule to uncheck the checkbox if it is unchecked:
- if(!elements[i].checked) {
- overwrite = false;
- }
- value = this.getRegExpStrForValue(elements[i].value);
- break;
- case 'radio':
- // Only add checked radio buttons:
- if(!elements[i].checked) {
- continue;
- }
- value = this.getRegExpStrForValue(elements[i].value);
- break;
- case 'select-one':
- value = this.getRegExpStrForValue(elements[i].value);
- break;
- case 'select-multiple':
- var fieldRuleLabel = this.makeSafe(this.getFieldRuleNameForElement(elements[i]));
- // Add all options as fieldRules, set "overwrite" to true if selected:
- for(var j = 0; j < elements[i].options.length; j++) {
- newProfile.push(
- this.createFieldRule(
- fieldRuleLabel+' ('+j+')',
- this.getRegExpStrForValue(elements[i].options[j].value),
- fieldRule,
- '(?:)',
- elements[i].options[j].selected,
- true
- )
- );
- }
- continue;
- default:
- value = this.makeSafe(this.replaceControlCharacters(elements[i].value));
- break;
- }
-
- // Add the current element as new rule to the profile list:
- newProfile.push(
- this.createFieldRule(
- this.makeSafe(this.getFieldRuleNameForElement(elements[i])),
- value,
- fieldRule,
- '(?:)',
- overwrite,
- true
- )
- );
- }
- }
-
- // Initialize the fieldRules:
- this.getFieldRules();
-
- // Add the new profile to the fieldRules:
- this.fieldRules.push(newProfile);
- // Save the profiles in the preferences:
- this.setFieldRules();
-
- // Add a label for default empty profile:
- if(this.getProfileLabels().length == 0) {
- this.getProfileLabels().push(this.getUniqueProfileLabel());
- }
- // Use the documents hostname as profile label and add it to the profile labels list:
- this.getProfileLabels().push(this.getUniqueProfileLabel(this.makeSafe(doc.location.host)));
- // Save the profileLabels list in the preferences:
- this.setProfileLabels(this.getProfileLabels());
-
- // Use the protocol and domain of the web form as profile siteRule:
- this.getProfileSiteRules().push(this.getSiteRuleForURL(doc.location.protocol+'//'+doc.location.host));
- // Save the profileSiteRules in the preferences:
- this.setProfileSiteRules(this.getProfileSiteRules());
-
- // Save the the new profile index as selected profileIndex:
- this.setProfileIndex(this.getProfileLabels().length-1);
-
- // Reset the target form field:
- this.targetFormField = null;
-
- // Create parameters for the settings page:
- var params = new Object();
- params.newProfileFromForm = true;
-
- // Open up the settings page:
- this.showDialog('chrome://autofillForms/content/autofillFormsOptions.xul', params);
- }
- },
-
- addProfile: function(newProfileLabel) {
- // Duplicate the selected profile (do a deep copy):
- this.fieldRules.push(
- this.copyFieldRules(this.getFieldRules())
- );
- // Save the profiles in the preferences:
- this.setFieldRules();
- // Add profile label for default empty profile:
- if(this.getProfileLabels().length == 0) {
- this.getProfileLabels().push(this.getUniqueProfileLabel());
- }
- // Add the (unique) newProfileLabel to the profileLabels list:
- this.getProfileLabels().push(this.getUniqueProfileLabel(this.makeSafe(newProfileLabel)));
- // Save the profileLabels list in the preferences:
- this.setProfileLabels(this.getProfileLabels());
- // Add a new empty profileSiteRule:
- this.getProfileSiteRules().push('(?:)');
- // Save the profileSiteRules in the preferences:
- this.setProfileSiteRules(this.getProfileSiteRules());
- // Save the the new profile index as selected profileIndex:
- this.setProfileIndex(this.getProfileLabels().length-1);
- // Update the profiles lists:
- this.initProfilesLists();
- // Re-init the fieldRules tree:
- this.initTree();
- // Re-initialize the simple interface:
- this.initSimpleInterface();
- },
-
- removeProfile: function(event) {
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- // Confirmation dialog:
- if(!this.getPrompts().confirm(
- null,
- this.getStringBundle().getString('removeProfileTitle'),
- this.getStringBundle().getString('removeProfileText')
- )
- ) {
- return;
- }
- }
-
- // Remove the selected profile from the list:
- this.fieldRules.splice(this.getProfileIndex(),1);
- // Save the profiles in the preferences:
- this.setFieldRules();
- // Remove the selected profile from the profileLabels list:
- this.getProfileLabels().splice(this.getProfileIndex(),1);
- // Save the profileLabels list in the preferences:
- this.setProfileLabels(this.getProfileLabels());
- // Remove the selected profile's siteRule:
- this.getProfileSiteRules().splice(this.getProfileIndex(),1);
- // Save the profileSiteRules in the preferences:
- this.setProfileSiteRules(this.getProfileSiteRules());
- // Adjust the profileIndex if the last profile on the list has been deleted:
- if(this.getProfileIndex()+1 > this.fieldRules.length) {
- var newIndex = this.fieldRules.length>0 ? this.fieldRules.length-1 : 0;
- this.setProfileIndex(newIndex);
- }
- // Update the profiles lists:
- this.initProfilesLists();
- // Re-init the tree:
- this.initTree();
- // Re-initialize the simple interface:
- this.initSimpleInterface();
- },
-
- createFieldRule: function(name,value,fieldRule,siteRule,overwrite,enabled) {
- var rule = new Object();
- rule['fieldRuleName'] = name;
- rule['fieldRuleValue'] = value;
- rule['fieldRuleFieldRule'] = fieldRule;
- rule['fieldRuleSiteRule'] = siteRule;
- rule['fieldRuleOverwrite'] = overwrite;
- rule['fieldRuleEnabled'] = enabled;
- return rule;
- },
-
- getRegExpPasswordLabel: function() {
- if(!arguments.callee.regExpPass) {
- arguments.callee.regExpPass = new RegExp(
- this.autofillFormsPrefs
- .getComplexValue('regExpPasswordLabel',Components.interfaces.nsIPrefLocalizedString)
- .data,
- 'i');
- }
- return arguments.callee.regExpPass;
- },
-
- initTree: function() {
- // Get the tree:
- this.tree = document.getElementById('fieldRulesTree');
-
- if(this.tree) {
-
- // Implement the TreeView interface:
- this.treeView = {
- rowCount: 0,
- setTree: function(tree){},
- getImageSrc: function(row,column) {},
- getProgressMode: function(row,column) {},
- getCellValue: function(row,column) {
- var rowObj = this.parent.getFieldRules()[row];
- if(rowObj) {
- return rowObj[column.id];
- }
- },
- getCellText: function(row,column){
- var rowObj = this.parent.getFieldRules()[row];
- if(rowObj) {
- if(column.id=='fieldRuleValue' &&
- this.parent.getRegExpPasswordLabel().test(rowObj['fieldRuleName'])) {
- // Show passwords as asterisks:
- return rowObj[column.id].replace(/./g, '*');
- } else {
- return rowObj[column.id];
- }
- }
- return '';
- },
- isEditable: function(row,column){
- // Only checkbox columns are editable:
- if(column.id=='fieldRuleOverwrite' || column.id=='fieldRuleEnabled')
- return true;
- else
- return false;
- },
- setCellValue: function(row,column,value){
- var rowObj = this.parent.getFieldRules()[row];
- if(rowObj) {
- rowObj[column.id] = value;
- // Notify the tree:
- this.parent.treeBox.invalidateRow(row);
- // Update the preferences:
- this.parent.setFieldRules();
- // Update the simple interface (add/remove enabled/disabled rules):
- if(column.id=='fieldRuleEnabled') {
- if(value == 'true') {
- this.parent.addSimpleInterfaceRow(row);
- } else {
- this.parent.removeSimpleInterfaceRow(row);
- }
- }
- }
- },
- isSeparator: function(index) {return false;},
- isSorted: function() {return false;},
- isContainer: function(index) {return false;},
- cycleHeader: function(column) {},
- getRowProperties: function(row,prop){},
- getColumnProperties: function(column,prop){},
- getCellProperties: function(row,column,prop){},
- getParentIndex: function(index) {return -1}
- };
- // Set the autofillForms object as parent:
- this.treeView.parent = this;
-
- // Set the tree length using the fieldRules list length:
- this.treeView.rowCount = this.getFieldRules().length;
-
- // Assign the treeview:
- this.tree.view = this.treeView;
-
- // The TreeSelection object:
- this.selection = this.tree.view.selection;
-
- // The TreeBox object:
- this.treeBox = this.tree.treeBoxObject;
- }
- },
-
- sortFieldRules: function(event) {
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- // Confirmation dialog:
- if(!this.getPrompts().confirm(
- null,
- this.getStringBundle().getString('sortFieldRulesTitle'),
- this.getStringBundle().getString('sortFieldRulesText')
- )
- ) {
- return;
- }
- }
-
- // Get the id of the column:
- var id = event.target.id;
-
- // Helper function to sort the fieldRules objects:
- function customSort(a,b) {
- // This enables comparison of boolean true and false:
- var x = a[id].toString();
- var y = b[id].toString();
-
- if(x > y) return 1;
- if(x < y) return -1;
- return 0;
- }
-
- // Sort the form field rules using the helper function:
- this.getFieldRules().sort(customSort);
-
- // Change sort direction for next click:
- if(this.ascending) {
- this.ascending = false;
- } else {
- this.getFieldRules().reverse();
- this.ascending = true;
- }
-
- // Notify the tree:
- this.treeBox.invalidate();
-
- // Clear out selections
- this.selection.select(-1);
-
- // Update the preferences:
- this.setFieldRules();
-
- // Re-initialize the simple interface:
- this.initSimpleInterface();
- },
-
- selectedFieldRule: function(event) {
- if(this.selection.currentIndex == -1) {
- // Disable buttons:
- document.getElementById('buttonRemoveFieldRule').setAttribute('disabled', 'true');
- document.getElementById('buttonMoveUpFieldRule').setAttribute('disabled', 'true');
- document.getElementById('buttonMoveDownFieldRule').setAttribute('disabled', 'true');
-
- this.lastSelectedIndex = null;
- } else if(this.selection.count == 1) {
- // The onchange event (as well as onblur, etc.) of the textboxes seems to be ignored if a new item is selected,
- // so we try and apply the field rules of the last element (if changed):
- if(this.lastSelectedIndex !== null) {
- this.applyFieldRuleOnIndex(this.lastSelectedIndex);
- }
-
- // Update the textboxes with the selected fieldRule:
- var index = this.selection.currentIndex;
- document.getElementById('fieldRuleNameTextBox').value = this.getFieldRules()[index]['fieldRuleName'];
- document.getElementById('fieldRuleValueTextBox').value = this.getFieldRules()[index]['fieldRuleValue'];
- document.getElementById('fieldRuleFieldRuleTextBox').value = this.getFieldRules()[index]['fieldRuleFieldRule'];
- document.getElementById('fieldRuleSiteRuleTextBox').value = this.getFieldRules()[index]['fieldRuleSiteRule'];
-
- // Enable/Disable buttons:
- document.getElementById('buttonRemoveFieldRule').setAttribute('disabled', 'false');
- document.getElementById('buttonMoveUpFieldRule').setAttribute(
- 'disabled',
- (index == 0)
- );
- document.getElementById('buttonMoveDownFieldRule').setAttribute(
- 'disabled',
- (index == this.getFieldRules().length-1)
- );
-
- // Save the last selected index and reset it to null for any other action than just a single selection:
- this.lastSelectedIndex = index;
- } else if(this.selection.count > 1) {
- // Enable/Disable buttons:
- document.getElementById('buttonRemoveFieldRule').setAttribute('disabled', 'false');
- document.getElementById('buttonMoveUpFieldRule').setAttribute('disabled', 'true');
- document.getElementById('buttonMoveDownFieldRule').setAttribute('disabled', 'true');
-
- this.lastSelectedIndex = null;
- }
- },
-
- initProfilesTree: function() {
- this.profilesTree = document.getElementById('profilesTree');
- if(this.profilesTree) {
-
- // Implement the profiles TreeView interface:
- this.profilesTreeView = {
- rowCount: 0,
- setTree: function(tree){},
- getImageSrc: function(row,column) {},
- getProgressMode: function(row,column) {},
- getCellValue: function(row,column) {
- if(column.id=='profilesTreeColName') {
- return this.parent.getProfileLabel(row);
- } else {
- return this.parent.getProfileSiteRule(row);
- }
- },
- getCellText: function(row,column){
- if(column.id=='profilesTreeColName') {
- return this.parent.getProfileLabel(row);
- } else {
- return this.parent.getProfileSiteRule(row);
- }
- },
- isEditable: function(row,column){return false;},
- setCellValue: function(row,column,value){},
- isSeparator: function(index) {return false;},
- isSorted: function() {return false;},
- isContainer: function(index) {return false;},
- cycleHeader: function(column) {},
- getRowProperties: function(row,prop){},
- getColumnProperties: function(column,prop){},
- getCellProperties: function(row,column,prop){},
- getParentIndex: function(index) {return -1}
- };
- // Set the autofillForms object as parent:
- this.profilesTreeView.parent = this;
-
- // Seems like we need to reset these arrays to have a consistens UI:
- this.profileLabels = null;
- this.profileSiteRules = null;
-
- // Set the tree length using the profiles labels list length:
- this.profilesTreeView.rowCount = this.getProfileLabels().length;
-
- // Assign the treeview:
- this.profilesTree.view = this.profilesTreeView;
-
- // The TreeSelection object:
- this.profilesSelection = this.profilesTree.view.selection;
-
- // The TreeBox object:
- this.profilesTreeBox = this.profilesTree.treeBoxObject;
-
- // Select the current profile:
- this.profilesSelection.select(this.getProfileIndex());
-
- // Ensure row is visible (scrolls if not):
- this.profilesTreeBox.ensureRowIsVisible(this.getProfileIndex());
- }
- },
-
- selectedProfile: function(event) {
- var index = this.profilesSelection.currentIndex;
- if(index != -1) {
- this.setProfileIndex(index);
-
- if(index > 0) {
- document.getElementById('buttonMoveUpProfile').disabled = false;
- } else {
- document.getElementById('buttonMoveUpProfile').disabled = true;
- }
- if(index+1 < this.getProfileLabels().length) {
- document.getElementById('buttonMoveDownProfile').disabled = false;
- } else {
- document.getElementById('buttonMoveDownProfile').disabled = true;
- }
-
- if(document.getElementById('profileLabelTextBox')) {
- document.getElementById('profileLabelTextBox').value = this.getProfileLabel(this.getProfileIndex());
- }
- if(document.getElementById('profileSiteRuleTextBox2')) {
- document.getElementById('profileSiteRuleTextBox2').value = this.getProfileSiteRule(this.getProfileIndex());
- }
- } else {
- document.getElementById('buttonMoveUpProfile').disabled = true;
- document.getElementById('buttonMoveDownProfile').disabled = true;
- }
- },
-
- moveUpProfile: function(event) {
- var tmpProfile = this.getFieldRules(this.getProfileIndex()-1);
- this.fieldRules[this.getProfileIndex()-1] = this.getFieldRules(this.getProfileIndex());
- this.fieldRules[this.getProfileIndex()] = tmpProfile;
- this.setFieldRules();
-
- var tmpProfileLabel = this.getProfileLabel(this.getProfileIndex()-1);
- this.getProfileLabels()[this.getProfileIndex()-1] = this.getProfileLabel(this.getProfileIndex());
- this.getProfileLabels()[this.getProfileIndex()] = tmpProfileLabel;
- this.setProfileLabels(this.getProfileLabels());
-
- var tmpProfileSiteRule = this.getProfileSiteRule(this.getProfileIndex()-1);
- this.getProfileSiteRules()[this.getProfileIndex()-1] = this.getProfileSiteRule(this.getProfileIndex());
- this.getProfileSiteRules()[this.getProfileIndex()] = tmpProfileSiteRule;
- this.setProfileSiteRules(this.getProfileSiteRules());
-
- this.setProfileIndex(this.getProfileIndex()-1);
-
- this.initProfilesLists();
- },
-
- moveDownProfile: function(event) {
- var tmpProfile = this.getFieldRules(this.getProfileIndex()+1);
- this.fieldRules[this.getProfileIndex()+1] = this.getFieldRules(this.getProfileIndex());
- this.fieldRules[this.getProfileIndex()] = tmpProfile;
- this.setFieldRules();
-
- var tmpProfileLabel = this.getProfileLabel(this.getProfileIndex()+1);
- this.getProfileLabels()[this.getProfileIndex()+1] = this.getProfileLabel(this.getProfileIndex());
- this.getProfileLabels()[this.getProfileIndex()] = tmpProfileLabel;
- this.setProfileLabels(this.getProfileLabels());
-
- var tmpProfileSiteRule = this.getProfileSiteRule(this.getProfileIndex()+1);
- this.getProfileSiteRules()[this.getProfileIndex()+1] = this.getProfileSiteRule(this.getProfileIndex());
- this.getProfileSiteRules()[this.getProfileIndex()] = tmpProfileSiteRule;
- this.setProfileSiteRules(this.getProfileSiteRules());
-
- this.setProfileIndex(this.getProfileIndex()+1);
-
- this.initProfilesLists();
- },
-
- sortProfiles: function(event) {
- var newSelectedIndex = this.getProfileIndex();
- var fieldArray = this.getFieldsArray();
- var oldIndex;
-
- switch(event.target.id) {
- case 'profilesTreeColName':
- //Sort by Profile Label
- fieldArray.sort(function (a, b) {
- if (a[1] == b[1]) {
- return 0;
- }
- if (a[1] < b[1]) {
- return -1;
- }
- return 1;
- });
- if (!this.profilesAscending) {
- fieldArray.reverse();
- }
- for(var i=0; i<this.getProfileLabels().length; i++) {
- oldIndex = fieldArray[i][0];
- if(oldIndex == this.getProfileIndex()) {
- newSelectedIndex = i;
- }
- this.getProfileLabels()[i] = fieldArray[i][1];
- this.getProfileSiteRules()[i] = fieldArray[i][2];
- this.fieldRules[i] = fieldArray[i][3];
- }
- break;
-
- case 'profilesTreeColSiteRule':
- //Sort by Profile Site Rule
- fieldArray.sort(function (a, b) {
- if (a[2] == b[2]) {
- return 0;
- }
- if (a[2] < b[2]) {
- return -1;
- }
- return 1;
- });
- if (!this.profilesAscending) {
- fieldArray.reverse();
- }
- for(var i=0; i<this.getProfileLabels().length; i++) {
- oldIndex = fieldArray[i][0];
- if(oldIndex == this.getProfileIndex()) {
- newSelectedIndex = i;
- }
- this.getProfileLabels()[i] = fieldArray[i][1];
- this.getProfileSiteRules()[i] = fieldArray[i][2];
- this.fieldRules[i] = fieldArray[i][3];
- }
- break;
- }
- // Change sort direction for next click:
- this.profilesAscending = !this.profilesAscending;
-
- this.setFieldRules();
- this.setProfileLabels(this.getProfileLabels());
- this.setProfileSiteRules(this.getProfileSiteRules());
-
- this.setProfileIndex(newSelectedIndex);
-
- this.initProfilesLists();
- },
- getFieldsArray: function() {
- // This creates an array of [i, ProfileLabel, ProfileSiteRule, fieldRules] rows
- // we can then sort by rows[1] or rows[2] and store the row elements back in
- // their respective arrays.
- var row;
- var fieldArray = new Array();
- var tmpProfileLabels = this.getProfileLabels().slice(0);
- var tmpProfileSiteRules = this.getProfileSiteRules().slice(0);
-
- for(var i=0; i<this.getProfileSiteRules().length; i++) {
- row = new Array();
- row.push(i);
- row.push(tmpProfileLabels[i]);
- row.push(tmpProfileSiteRules[i]);
- row.push(this.getFieldRules(i));
- fieldArray.push(row);
- }
- return fieldArray;
- },
- profilesTreeHandleKeyPress: function(event) {
- if(event.keyCode == 46) {
- this.removeProfile();
- }
- },
-
- invalidRegExpAlert: function(error) {
- // Invalid regular expression alert:
- this.getPrompts().alert(
- null,
- this.getStringBundle().getString('invalidRegExpTitle'),
- this.getStringBundle().getString('invalidRegExpText') + "\n\n" + error
- );
- },
-
- makeSafe: function(str) {
- // Remove all tabs and linefeeds from the given string
- // (these are used as separators):
- return str.replace(/\t|\n/g, '');
- },
-
- replaceControlCharacters: function(str) {
- return str.replace(
- /\n|\t/g,
- this.replaceControlCharactersCallback
- );
- },
-
- replaceControlCharactersCallback: function(str) {
- switch(str) {
- case "\n":
- return autofillForms.autofillFormsPrefs.getCharPref('placeholderLineBreak');
- case "\t":
- return ' ';
- default:
- return str;
- }
- },
-
- replaceControlCharacterPlaceholders: function(str) {
- try {
- var regExpObj = new RegExp(
- '('
- +this.autofillFormsPrefs.getCharPref('placeholderLineBreak')
- +')|('
- +this.autofillFormsPrefs.getCharPref('placeholderTab')
- +')',
- 'g'
- );
- return str.replace(
- regExpObj,
- this.replaceControlCharacterPlaceholdersCallback
- );
- } catch(e) {
- return str;
- }
- },
-
- replaceControlCharacterPlaceholdersCallback: function(str) {
- switch(str) {
- case autofillForms.autofillFormsPrefs.getCharPref('placeholderLineBreak'):
- return "\n";
- case autofillForms.autofillFormsPrefs.getCharPref('placeholderTab'):
- return "\t";
- default:
- return str;
- }
- },
-
- applyFieldRuleOnIndex: function(index) {
- // Check the regular expressions:
- try {
- var fieldRule = this.getRegExpStr(
- this.makeSafe(document.getElementById('fieldRuleFieldRuleTextBox').value)
- );
- document.getElementById('fieldRuleFieldRuleTextBox').value = fieldRule;
-
- var siteRule = this.getRegExpStr(
- this.makeSafe(document.getElementById('fieldRuleSiteRuleTextBox').value)
- );
- document.getElementById('fieldRuleSiteRuleTextBox').value = siteRule;
- } catch(e) {
- this.invalidRegExpAlert(e);
- return;
- }
-
- var ruleName = this.makeSafe(document.getElementById('fieldRuleNameTextBox').value);
- var ruleValue = this.makeSafe(document.getElementById('fieldRuleValueTextBox').value);
-
- if( this.getFieldRules()[index] && (
- this.getFieldRules()[index]['fieldRuleName'] != ruleName ||
- this.getFieldRules()[index]['fieldRuleValue'] != ruleValue ||
- this.getFieldRules()[index]['fieldRuleFieldRule'] != fieldRule ||
- this.getFieldRules()[index]['fieldRuleSiteRule'] != siteRule)) {
- // Update the formFieldRule on the given index:
- this.getFieldRules()[index]['fieldRuleName'] = ruleName;
- this.getFieldRules()[index]['fieldRuleValue'] = ruleValue;
- this.getFieldRules()[index]['fieldRuleFieldRule'] = fieldRule;
- this.getFieldRules()[index]['fieldRuleSiteRule'] = siteRule;
-
- // Notify the tree:
- this.treeBox.invalidateRow(index);
-
- // Update the preferences:
- this.setFieldRules();
-
- // Update the related row of the simple interface:
- this.updateSimpleInterfaceRow(index);
- }
- },
-
- applyFieldRule: function(event) {
- // Only apply changes if one item is selected:
- if(this.selection.count == 1) {
- // Update the selected formFieldRule:
- this.applyFieldRuleOnIndex(this.selection.currentIndex);
- }
- },
-
- addFieldRule: function(event) {
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- // Check the regular expressions:
- try {
- var fieldRuleFieldRuleTextBox = document.getElementById('fieldRuleFieldRuleTextBox');
- var fieldRule = this.getRegExpStr(
- this.makeSafe(fieldRuleFieldRuleTextBox.value)
- );
- fieldRuleFieldRuleTextBox.value = fieldRule;
-
- var fieldRuleSiteRuleTextBox = document.getElementById('fieldRuleSiteRuleTextBox');
- var siteRule = this.getRegExpStr(
- this.makeSafe(fieldRuleSiteRuleTextBox.value)
- );
- fieldRuleSiteRuleTextBox.value = siteRule;
- } catch(e) {
- this.invalidRegExpAlert(e);
- return;
- }
-
- var newFieldRule = this.createFieldRule(
- this.makeSafe(document.getElementById('fieldRuleNameTextBox').value),
- this.makeSafe(document.getElementById('fieldRuleValueTextBox').value),
- fieldRule,
- siteRule,
- true,
- true
- )
-
- var newFieldRuleIndex;
-
- // Add the new formFieldRule right after the selected position or to the start of the list:
- if(this.selection.currentIndex == -1 || this.selection.currentIndex == this.treeView.rowCount) {
- this.getFieldRules().unshift(newFieldRule);
- newFieldRuleIndex = 0;
- } else {
- newFieldRuleIndex = this.selection.currentIndex+1;
- this.getFieldRules().splice(
- newFieldRuleIndex,
- 0,
- newFieldRule
- );
- }
-
- // Update the tree count and notify the tree:
- this.treeView.rowCount++;
- this.treeBox.rowCountChanged(this.treeView.rowCount, +1);
- this.treeBox.invalidate();
-
- // Select the new item:
- this.selection.select(newFieldRuleIndex);
-
- // Ensure row is visible (scrolls if not):
- this.treeBox.ensureRowIsVisible(newFieldRuleIndex);
-
- // Update the preferences:
- this.setFieldRules();
-
- // Re-initialize the simple interface:
- this.initSimpleInterface();
- },
-
- removeFieldRule: function(event) {
- this.removeSelectedFieldRules();
- },
-
- moveUpFieldRule: function(event) {
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- var index = this.selection.currentIndex;
-
- // Change place with the next upper item:
- var sibling = this.getFieldRules()[index-1];
- this.getFieldRules()[index-1] = this.getFieldRules()[index];
- this.getFieldRules()[index] = sibling;
-
- // Keep moved item selected:
- this.selection.select(index-1);
-
- // Notify the tree:
- this.treeBox.invalidate();
-
- // Ensure row is visible (scrolls if not):
- this.treeBox.ensureRowIsVisible(index-1);
-
- // Update the preferences:
- this.setFieldRules();
-
- // Update the related rows of the simple interface:
- this.updateSimpleInterfaceRow(index-1);
- this.updateSimpleInterfaceRow(index);
- },
-
- moveDownFieldRule: function(event) {
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- var index = this.selection.currentIndex;
-
- // Change place with the next lower item:
- var sibling = this.getFieldRules()[index+1];
- this.getFieldRules()[index+1] = this.getFieldRules()[index];
- this.getFieldRules()[index] = sibling;
-
- // Keep moved item selected:
- this.selection.select(index+1);
-
- // Notify the tree:
- this.treeBox.invalidate();
-
- // Ensure row is visible (scrolls if not):
- this.treeBox.ensureRowIsVisible(index+1);
-
- // Update the preferences:
- this.setFieldRules();
-
- // Update the related rows of the simple interface:
- this.updateSimpleInterfaceRow(index+1);
- this.updateSimpleInterfaceRow(index);
- },
-
- removeSelectedFieldRules: function(event) {
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- // Confirmation dialog:
- if(!this.getPrompts().confirm(
- null,
- this.getStringBundle().getString('removeFieldRulesTitle'),
- this.getStringBundle().getString('removeFieldRulesText')
- )
- ) {
- return;
- }
- }
-
- // Start of update batch:
- this.treeBox.beginUpdateBatch();
-
- // Helper object to store a range:
- function Range(start, end) {
- this.start = start.value;
- this.end = end.value;
- }
-
- // List of ranges:
- var ranges = new Array();
-
- // Get the number of ranges:
- var numRanges = this.selection.getRangeCount();
-
- // Helper vars to store the range end points:
- var start = new Object();
- var end = new Object();
-
- // We store the list of ranges first, as calling
- // this.treeBox.rowCountChanged()
- // seems to invalidate the current selection
-
- for(var i=0; i < numRanges; i++) {
- // Get the current range end points:
- this.selection.getRangeAt(i,start,end);
- // Store them as a Range object in the ranges list:
- ranges[i] = new Range(start, end);
- }
-
- for(var i=0; i < numRanges; i++) {
- // Go through the stored ranges:
- for(var j = ranges[i].start; j <= ranges[i].end; j++) {
- // Set the selected fieldRules to null:
- this.getFieldRules()[j] = null;
- }
-
- // Calculate the new tree count:
- var count = ranges[i].end - ranges[i].start + 1;
-
- // Update the tree count and notify the tree:
- this.treeView.rowCount -= count;
- this.treeBox.rowCountChanged(ranges[i].start, -count);
- }
-
- // Collapse list by removing all the null entries
- for (var i=0; i < this.getFieldRules().length; i++) {
- if (!this.getFieldRules()[i]) {
- var j = i;
- while (j < this.getFieldRules().length && !this.getFieldRules()[j])
- j++;
- this.getFieldRules().splice(i, j-i);
- }
- }
-
- // Clear out selections
- this.selection.select(-1);
-
- // End of update batch:
- this.treeBox.endUpdateBatch();
-
- // Update the preferences:
- this.setFieldRules();
-
- // Re-initialize the simple interface:
- this.initSimpleInterface();
- },
-
- handleKeyPress: function(event) {
- if(event.keyCode == 46) {
- this.removeSelectedFieldRules();
- } else if(event.ctrlKey && event.which == 97) {
- if(this.tree && this.selection) {
- try {
- // Select all rows:
- this.selection.selectAll();
- } catch(e) {
- this.log(e);
- }
- }
- }
- },
-
- getGlobalFieldRules: function() {
- // Return the fieldRules for the selected global profile if globalProfileIndex is not out of range:
- if(this.getGlobalProfileIndex() >= 0 && this.getGlobalProfileIndex() < this.getProfileLabels().length) {
- return this.getFieldRules(this.getGlobalProfileIndex());
- } else {
- this.globalProfileIndex = 0;
- return this.getFieldRules(0);
- }
- },
-
- getFileContent: function(file) {
- var fileContent = null;
- try {
- var fis = Components.classes['@mozilla.org/network/file-input-stream;1']
- .createInstance(Components.interfaces.nsIFileInputStream);
- fis.init(file, -1, 0, 0);
- var is = Components.classes['@mozilla.org/intl/converter-input-stream;1']
- .createInstance(Components.interfaces.nsIConverterInputStream);
- is.init(fis, 'UTF-8', 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
- if(is instanceof Components.interfaces.nsIUnicharLineInputStream) {
- var line = {};
- var cont;
- do {
- cont = is.readLine(line);
- if(fileContent == null) {
- fileContent = line.value;
- } else {
- fileContent += '\n'+line.value;
- }
- } while (cont);
- }
- is.close();
- fis.close();
- } catch(e) {
- this.log(e);
- }
- return fileContent;
- },
-
- setFileContent: function(file, str) {
- try {
- var fos = Components.classes['@mozilla.org/network/file-output-stream;1']
- .createInstance(Components.interfaces.nsIFileOutputStream);
- fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0);
- var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
- .createInstance(Components.interfaces.nsIConverterOutputStream);
- os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
- os.writeString(str);
- os.close();
- fos.close();
- } catch(e) {
- this.log(e);
- }
- },
-
- getFieldRulesFile: function() {
- var file = this.getConfigDirectory();
- file.append('fieldRules.txt');
- if(!file.exists()) {
- file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
- }
- return file;
- },
-
- getConfigDirectory: function() {
- var configDirectory;
- if(this.autofillFormsPrefs.prefHasUserValue('configDirectory')) {
- try {
- configDirectory = this.autofillFormsPrefs.getComplexValue(
- 'configDirectory',
- Components.interfaces.nsILocalFile
- );
- } catch(e) {
- this.autofillFormsPrefs.clearUserPref('configDirectory');
- }
- }
- if(!configDirectory) {
- configDirectory = this.getDefaultConfigDirectory();
- }
- return configDirectory;
- },
-
- getDefaultConfigDirectory: function() {
- // Use a directory "autofillForms at blueimp.net" inside Firefox profile directory as default:
- var configDirectory = Components.classes['@mozilla.org/file/directory_service;1']
- .getService(Components.interfaces.nsIProperties)
- .get('ProfD', Components.interfaces.nsILocalFile);
- configDirectory.append('autofillForms at blueimp.net');
- if(!configDirectory.exists()) {
- configDirectory.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0770);
- }
- return configDirectory;
- },
-
- setConfigDirectory: function(textBox) {
- try {
- // Create a file picker instance:
- var fp = Components.classes['@mozilla.org/filepicker;1']
- .createInstance(Components.interfaces.nsIFilePicker);
-
- // Initialize the file picker window:
- fp.init(
- window,
- this.getStringBundle().getString('selectConfigDirectory'),
- Components.interfaces.nsIFilePicker.modeGetFolder
- );
-
- // Show the file picker window:
- var rv = fp.show();
-
- if (rv == Components.interfaces.nsIFilePicker.returnOK) {
- var newDir = fp.file;
- if(newDir.path == this.getConfigDirectory().path) {
- return;
- }
- this.moveConfigFiles(newDir);
- // Save the selected directory in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'configDirectory',
- Components.interfaces.nsILocalFile, newDir
- );
- if(textBox) {
- // Set the textbox value to the directory path:
- textBox.value = newDir.path;
- }
- }
- } catch(e) {
- this.log(e);
- }
- },
-
- resetConfigDirectory: function(textBox) {
- if(this.autofillFormsPrefs.prefHasUserValue('configDirectory')) {
- var newDir = this.getDefaultConfigDirectory();
- this.moveConfigFiles(newDir);
- this.autofillFormsPrefs.clearUserPref('configDirectory');
- if(textBox) {
- // Set the textbox value to an empty string:
- textBox.value = '';
- }
- }
- },
-
- openConfigDirectory: function() {
- var configDirectory = this.getConfigDirectory();
- if(configDirectory) {
- try {
- // Open the config directory in the operating system file manager:
- configDirectory.reveal();
- } catch(e) {
- // reveal method may not be supported on some platforms,
- // use nsIExternalProtocolService instead:
- var uri = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService)
- .newFileURI(configDirectory);
- var protocolSvc =
- Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
- .getService(Components.interfaces.nsIExternalProtocolService);
- protocolSvc.loadUrl(uri);
- }
- }
- },
-
- moveConfigFiles: function(newDir) {
- if(this.checkConfigDirectoryOverwrite(newDir)) {
- this.moveFile(this.getFieldRulesFile(), newDir);
- this.moveFile(this.getDynamicTagsFile(), newDir);
- this.moveFile(this.getDynamicTagCodesFile(), newDir);
- this.moveFile(this.getProfileLabelsFile(), newDir);
- this.moveFile(this.getProfileSiteRulesFile(), newDir);
- return true;
- }
- return false;
- },
-
- importFromConfigDirectory: function() {
- var ok = true;
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- ok = this.getPrompts().confirm(
- window,
- this.getStringBundle().getString('importFromConfigDirectoryTitle'),
- this.getStringBundle().getString('importFromConfigDirectoryText')
- );
- }
- if(ok) {
- this.importFieldRulesFromConfigDirectory();
- this.importDynamicTagsFromConfigDirectory();
- this.importDynamicTagCodesFromConfigDirectory();
- this.importProfileLabelsFromConfigDirectory();
- this.importProfileSiteRulesFromConfigDirectory();
- }
- },
-
- exportToConfigDirectory: function() {
- if(this.checkConfigDirectoryOverwrite(this.getConfigDirectory())) {
- this.exportFieldRulesToConfigDirectory();
- this.exportDynamicTagsToConfigDirectory();
- this.exportDynamicTagCodesToConfigDirectory();
- this.exportProfileLabelsToConfigDirectory();
- this.exportProfileSiteRulesToConfigDirectory();
- return true;
- }
- return false;
- },
-
- moveFile: function(file, newDir, newFileName) {
- try {
- // The new fileName - uses the current fileName if empty:
- newFileName = (typeof newFileName == 'string') ? newFileName : null;
-
- file.moveTo(newDir, newFileName);
- return true;
- } catch(e) {
- this.log(e);
- return false;
- }
- },
-
- checkConfigDirectoryOverwrite: function(newDir) {
- var ok = true;
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- if(newDir.directoryEntries.hasMoreElements()) {
- ok = this.getPrompts().confirm(
- window,
- this.getStringBundle().getString('newConfigDirectoryNotEmptyTitle'),
- this.getStringBundle().getString('newConfigDirectoryNotEmptyText')
- );
- }
- }
- return ok;
- },
-
- exportFieldRulesToConfigDirectory: function() {
- var prefString;
- // Get the fieldRules string from the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('fieldRules',Components.interfaces.nsIPrefLocalizedString)
- .data;
- if(prefString) {
- this.setFileContent(this.getFieldRulesFile(), prefString);
- }
- },
-
- importFieldRulesFromConfigDirectory: function() {
- var prefString;
- prefString = this.getFileContent(this.getFieldRulesFile());
- if(prefString) {
- // Store the fieldRules as unicode string in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'fieldRules',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getFieldRules: function(profileIndex) {
- if(this.fieldRules == null) {
- this.fieldRules = new Array();
-
- var prefString;
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Get the fieldRules string from the fieldRules file in the configDirectory:
- prefString = this.getFileContent(this.getFieldRulesFile());
- }
- if(!prefString) {
- // Get the fieldRules string from the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('fieldRules',Components.interfaces.nsIPrefLocalizedString)
- .data;
- }
-
- // On change of the "storeEncrypted" setting, we must decrypt or may not decrypt
- // the prefString in opposition to the setting - the "invertedSetting" helper var
- // helps to identify this situation:
- var boolTest = this.invertedSetting ? false : true;
-
- // If the fieldRules are stored encrypted, decrypt the prefString:
- if(this.autofillFormsPrefs.getBoolPref('storeEncrypted') == boolTest) {
- try {
- // nsISecretDecoderRing fails to handle characters above ISO-8859-1 charset
- // The usage of encodeURI/decodeURI on the fieldRule properties bypasses this problem
- prefString = this.getCryptoService().decryptString(prefString);
- } catch(e) {
- // Decrypting failed - return an empty default profile:
- this.fieldRules.push(new Array());
- this.profileIndex = 0;
- return this.fieldRules[0];
- }
- }
-
- // Get the profiles (separated by \n\n):
- var profiles = prefString.split('\n\n');
-
- for(var i=0; i<profiles.length; i++) {
- // Create an array for each profile:
- this.fieldRules.push(new Array());
-
- // Get the fieldRules rows (separated by \n):
- var rows = profiles[i].split('\n');
- if(rows[0]) {
- for(var j=0; j<rows.length; j++) {
- if(!rows[j])
- continue;
-
- // Get the fieldRules column items (separated by \t):
- var cols = rows[j].split('\t');
-
- // Create fieldRules objects and save them in the current fieldRules Array:
- if(cols.length && cols.length == 6) {
-
- // Decode the fieldRule properties:
- for(var k=0; k<cols.length; k++) {
- cols[k] = decodeURI(cols[k]);
- }
-
- this.fieldRules[i].push(
- this.createFieldRule(
- cols[0],cols[1],cols[2],cols[3],
- (cols[4] != 'false'),
- (cols[5] != 'false')
- )
- );
- }
- }
- } else
- this.fieldRules[i] = new Array();
- }
- }
-
- profileIndex = (typeof profileIndex != 'undefined') ? profileIndex : this.getProfileIndex();
-
- // Return the fieldRules for the selected profile if profileIndex is not out of range:
- if(profileIndex >= 0 && profileIndex < this.fieldRules.length)
- return this.fieldRules[profileIndex];
- else {
- this.profileIndex = 0;
- if(this.fieldRules[0] == null)
- this.fieldRules[0] = new Array();
- return this.fieldRules[0];
- }
- },
-
- setFieldRules: function() {
- if(this.fieldRules == null) {
- // Initialize the field rules:
- this.getFieldRules();
- }
-
- var profiles = '';
- var rows, cols;
- for(var i=0; i < this.fieldRules.length; i++) {
- rows = '';
- for(var j=0; j<this.fieldRules[i].length; j++) {
- cols = null;
- for(var property in this.fieldRules[i][j]) {
- if(cols == null)
- cols = '';
- else
- cols += '\t';
- // Encode the fieldRule property before adding it to the string:
- cols += encodeURI(this.fieldRules[i][j][property]);
- }
- if(j!=0)
- rows += '\n';
- rows += cols;
- }
- if(i!=0)
- profiles += '\n\n';
- profiles += rows;
- }
-
- // If the fieldRules are to be stored encrypted, encrypt the prefString:
- if(this.autofillFormsPrefs.getBoolPref('storeEncrypted')) {
- try {
- // nsISecretDecoderRing fails to handle characters above ISO-8859-1 charset
- // The usage of encodeURI/decodeURI on the fieldRule properties bypasses this problem
- profiles = this.getCryptoService().encryptString(profiles);
- } catch(e) {
- // Decrypting failed - return:
- return;
- }
- }
-
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- this.setFileContent(this.getFieldRulesFile(), profiles);
- } else {
- // Store the fieldRules objects as unicode string in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'fieldRules',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(profiles)
- );
- }
- },
-
- copyFieldRules: function(origin) {
- var copy = new Array();
- for(var i=0; i<origin.length; i++) {
- copy.push(
- this.createFieldRule(
- origin[i]['fieldRuleName'],
- origin[i]['fieldRuleValue'],
- origin[i]['fieldRuleFieldRule'],
- origin[i]['fieldRuleSiteRule'],
- origin[i]['fieldRuleOverwrite'],
- origin[i]['fieldRuleEnabled']
- )
- )
- }
- return copy;
- },
- importDynamicTagsFromSettings: function() {
- //Here the tags are added directly
- var prefString = null;
-
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
- .data;
- var dynamicTags = prefString.split('\t');
-
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
- .data;
- var dynamicTagCodes = prefString.split('\t');
-
- this.importDynamicTags(dynamicTags, dynamicTagCodes);
- this.setDynamicTags(dynamicTags);
- this.setDynamicTagCodes(dynamicTagCodes);
- },
- importDynamicTagsFromTagEditor: function() {
- //Here the tags are added to the editor window, can be cancelled if necessary
- var richlistbox = document.getElementById('tagList');
- if(richlistbox) {
- var richlistitems = richlistbox.getElementsByTagName('richlistitem');
- var textboxes;
-
- var dynamicTags = new Array();
- var dynamicTagCodes = new Array();
-
- // Go through the richlistbox items:
- for(var i=0; i<richlistitems.length; i++) {
- textboxes = richlistitems[i].getElementsByTagName('textbox');
-
- // Add the dynamic tags and their associated tag codes to the lists:
- if (textboxes[0].value != '' && textboxes[1].value != '') {
- dynamicTags.push(this.makeSafe(textboxes[0].value));
- dynamicTagCodes.push(this.makeSafe(textboxes[1].value));
- }
- }
- this.importDynamicTags(dynamicTags, dynamicTagCodes);
- }
- },
- importDynamicTags: function(dynamicTags, dynamicTagCodes) {
- try {
- var file = this.filePicker('modeOpen', this.getStringBundle().getString('importDynamicTags'));
- if(file) {
- var fis = Components.classes['@mozilla.org/network/file-input-stream;1']
- .createInstance(Components.interfaces.nsIFileInputStream);
- fis.init(file, -1, 0, 0);
-
- var is = Components.classes['@mozilla.org/intl/converter-input-stream;1']
- .createInstance(Components.interfaces.nsIConverterInputStream);
- is.init(fis, 'UTF-8', 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-
- if (is instanceof Components.interfaces.nsIUnicharLineInputStream) {
- var line = {};
- var cont;
- var firstLine = true;
- var i;
-
- do {
- cont = is.readLine(line);
-
- // Get the dynamicTags column items (separated by \t) from the file:
- var cols = line.value.split('\t');
-
- if (firstLine == true) {
- // The first row has the following syntax (added in version 0.9.5):
- // autofillForms at blueimp.net Version dynamictags
- if(cols.length && cols.length != 3)
- cont = false;
- else if (cols[0] != 'autofillForms at blueimp.net')
- cont = false;
- else if (cols[2] != 'dynamictags')
- cont = false;
- firstLine = false;
- }
- else if (cols.length && cols.length == 2) {
- //Check the imported pair isn't already defined or empty.
- i = dynamicTags.indexOf(cols[0]);
- if ((i >= 0 && dynamicTagCodes[i] == cols[1])||(cols[0]=='' && cols[1]=='')) {
- continue;
- } else {
- dynamicTags.push(cols[0]);
- dynamicTagCodes.push(cols[1]);
- this.tagEditorAdd(cols[0],cols[1])
- }
- }
- } while (cont);
-
- }
- is.close();
- fis.close();
- }
- } catch(e) {
- this.log(e);
- }
- },
- exportDynamicTagsFromSettings: function() {
- var prefString = null;
-
- // Write the tags to file analog to storing them in the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
- .data;
- var dynamicTagCodes = prefString.split('\t');
-
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
- .data;
- var dynamicTags = prefString.split('\t');
- this.exportDynamicTags(dynamicTags, dynamicTagCodes);
- },
- exportDynamicTagsFromTagEditor: function() {
- var richlistbox = document.getElementById('tagList');
- if(richlistbox) {
- var richlistitems = richlistbox.getElementsByTagName('richlistitem');
- var textboxes;
-
- var dynamicTags = new Array();
- var dynamicTagCodes = new Array();
-
- // Go through the richlistbox items:
- for(var i=0; i<richlistitems.length; i++) {
- textboxes = richlistitems[i].getElementsByTagName('textbox');
-
- // Add the dynamic tags and their associated tag codes to the lists:
- if (textboxes[0].value != '' && textboxes[1].value != '') {
- dynamicTags.push(this.makeSafe(textboxes[0].value));
- dynamicTagCodes.push(this.makeSafe(textboxes[1].value));
- }
- }
- this.exportDynamicTags(dynamicTags, dynamicTagCodes);
- }
- },
- exportDynamicTags: function(dynamicTags, dynamicTagCodes) {
- try {
- var file = this.filePicker(
- 'modeSave',
- this.getStringBundle().getString('exportDynamicTags'),
- this.getProfileLabel(this.getProfileIndex())+'.txt'
- );
- if(file) {
- var fos = Components.classes['@mozilla.org/network/file-output-stream;1'].
- createInstance(Components.interfaces.nsIFileOutputStream);
- fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
-
- var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
- .createInstance(Components.interfaces.nsIConverterOutputStream);
- os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-
-
- var header = 'autofillForms at blueimp.net' + '\t'
- + this.version + '\t'
- + 'dynamictags\n';
- os.writeString(header);
-
- var cols;
- for(var i=0; i<dynamicTags.length; i++) {
- cols = dynamicTags[i]+'\t'+dynamicTagCodes[i];
- os.writeString('\n' + cols);
- }
- os.close();
- fos.close();
- }
- } catch(e) {
- this.log(e);
- }
- },
- importProfile: function() {
- try {
- var file = this.filePicker('modeOpen', this.getStringBundle().getString('importProfile'));
- if(file) {
- var fis = Components.classes['@mozilla.org/network/file-input-stream;1']
- .createInstance(Components.interfaces.nsIFileInputStream);
- fis.init(file, -1, 0, 0);
-
- var is = Components.classes['@mozilla.org/intl/converter-input-stream;1']
- .createInstance(Components.interfaces.nsIConverterInputStream);
- is.init(fis, 'UTF-8', 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-
- if(this.fieldRules == null) {
- // Initialize the field rules:
- this.getFieldRules();
- }
-
- // Create a new fieldRule profile (index is incremented when a valid header is found):
- var newProfileLabel = '';
- var newProfileSiteRule = '(?:)';
- var newProfileIndex = this.fieldRules.length-1;
- var validProfile = false;
-
- if (is instanceof Components.interfaces.nsIUnicharLineInputStream) {
- var line = {};
- var cont;
- do {
- cont = is.readLine(line);
-
- // Get the fieldRules column items (separated by \t) from the file:
- var cols = line.value.split('\t');
-
- if(cols.length && cols.length < 6 && cols[0] == 'autofillForms at blueimp.net') {
- // The first row has the following syntax (added SiteRule for version 0.9.1):
- // autofillForms at blueimp.net Version Label SiteRule
- // Every time such a row is encountered, a new profile is generated.
- if(cols.length >= 3) {
- newProfileLabel = cols[2];
- // Add profile label for default empty profile:
- if(this.getProfileLabels().length == 0) {
- this.getProfileLabels().push(this.getUniqueProfileLabel());
- }
- // Add the newProfileLabel to the profileLabels list (make sure it is unique):
- this.getProfileLabels().push(this.getUniqueProfileLabel(newProfileLabel));
- }
- if(cols.length >= 4) {
- try {
- newProfileSiteRule = this.getRegExpStr(cols[3]);
- // Add a new profileSiteRule:
- this.getProfileSiteRules().push(newProfileSiteRule);
- } catch(e) {
- // Catch missing or invalid site rule
- }
- }
- // Increment the ProfileIndex
- newProfileIndex += 1;
- this.fieldRules.push(new Array());
- validProfile = true;
- } else if(cols.length && cols.length == 6 && validProfile == true) {
- // Create fieldRules objects and save them in the fieldRules Array:
- this.fieldRules[newProfileIndex].push(
- this.createFieldRule(
- cols[0],cols[1],cols[2],cols[3],
- (cols[4] != 'false'),
- (cols[5] != 'false')
- )
- );
- }
-
- } while (cont);
- }
-
- // Save the profileLabels list in the preferences:
- this.setProfileLabels(this.getProfileLabels());
- // Save the profileSiteRules in the preferences:
- this.setProfileSiteRules(this.getProfileSiteRules());
- // Update the profiles lists:
- this.initProfilesLists();
-
- // Update the fieldRules:
- this.setFieldRules();
-
- is.close();
- fis.close();
- }
- } catch(e) {
- this.log(e);
- }
- },
- exportProfile: function() {
- try {
- var file = this.filePicker(
- 'modeSave',
- this.getStringBundle().getString('exportProfile'),
- this.getProfileLabel(this.getProfileIndex())+'.txt'
- );
- if(file) {
- var fos = Components.classes['@mozilla.org/network/file-output-stream;1'].
- createInstance(Components.interfaces.nsIFileOutputStream);
- fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
-
- var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
- .createInstance(Components.interfaces.nsIConverterOutputStream);
- os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-
- var profileIndex = this.getProfileIndex();
- this.writeProfile(os, profileIndex);
-
- os.close();
- fos.close();
- }
- } catch(e) {
- this.log(e);
- }
- },
- exportAllProfiles: function() {
- try {
- //use the first profile label as the filename
- var file = this.filePicker(
- 'modeSave',
- this.getStringBundle().getString('exportProfile'),
- this.getProfileLabel(0)+'.txt'
- );
- if(file) {
- var fos = Components.classes['@mozilla.org/network/file-output-stream;1'].
- createInstance(Components.interfaces.nsIFileOutputStream);
- fos.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
-
- var os = Components.classes['@mozilla.org/intl/converter-output-stream;1']
- .createInstance(Components.interfaces.nsIConverterOutputStream);
-
- os.init(fos, 'UTF-8', 4096, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-
- for(var i=0; i<this.getProfileLabels().length; i++) {
- this.writeProfile(os, i);
- os.writeString('\n\n');
- }
- os.close();
- fos.close();
- }
- } catch(e) {
- this.log(e);
- }
- },
- writeProfile: function(os, profileIndex) {
- try {
- var header = 'autofillForms at blueimp.net' + '\t'
- + this.version + '\t'
- + this.getProfileLabel(profileIndex) + '\t'
- + this.getProfileSiteRule(profileIndex) + '\n';
-
-
- os.writeString(header);
- // Write the rules to file analog to storing them in the preferences:
- var cols;
- for(var i=0; i<this.getFieldRules(profileIndex).length; i++) {
- cols = null;
- for(var property in this.getFieldRules(profileIndex)[i]) {
- if(cols == null)
- cols = '';
- else
- cols += '\t';
- cols += this.getFieldRules(profileIndex)[i][property];
- }
- os.writeString('\n' + cols);
- }
- } catch(e) {
- this.log(e);
- }
- },
- filePicker: function(mode, title, fileName) {
- try {
- // Create a file picker instance:
- var fp = Components.classes['@mozilla.org/filepicker;1']
- .createInstance(Components.interfaces.nsIFilePicker);
-
- // The filename suggested to the user as a default:
- if(fileName) {
- fp.defaultString = fileName;
- }
-
- // Initialize the file picker window:
- fp.init(
- window,
- title,
- Components.interfaces.nsIFilePicker[mode]
- );
-
- // Show the file picker window:
- var rv = fp.show();
-
- if(rv==Components.interfaces.nsIFilePicker.returnOK || rv==Components.interfaces.nsIFilePicker.returnReplace)
- return fp.file;
- else
- return null;
- } catch(e) {
- return null;
- }
- },
-
- getUnicodeString: function(stringData) {
- // Create an Unicode String:
- var str = Components.classes['@mozilla.org/supports-string;1']
- .createInstance(Components.interfaces.nsISupportsString);
- // Set the String value:
- str.data = stringData;
- // Return the Unicode String:
- return str;
- },
-
- getStringBundle: function() {
- return document.getElementById('autofillFormsStringBundle');
- },
-
- getDoc: function(win) {
- if(win)
- return win.document;
- else if(content)
- return content.document;
- else
- return this.getBrowser().contentDocument;
- },
-
- getWin: function() {
- if(content)
- return content;
- else
- return this.getBrowser().contentWindow;
- },
-
- getBrowser: function() {
- try {
- return gBrowser;
- } catch(e) {
- // gBrowser is not available, so make use of the WindowMediator service instead:
- return this.getWindowMediator().getMostRecentWindow('navigator:browser').getBrowser();
- }
- },
-
- getWindowMediator: function() {
- return Components.classes['@mozilla.org/appshell/window-mediator;1']
- .getService(Components.interfaces.nsIWindowMediator);
- },
-
- getRegExpStr: function(str) {
- // Create a RegExp object using the given String:
- var regExpStr = new RegExp(str).toString();
- // Return the String representation without the surrounding slashes:
- return regExpStr.substr(1,regExpStr.length-2);
- },
-
- getPrefManager: function() {
- return Components.classes['@mozilla.org/preferences-service;1']
- .getService(Components.interfaces.nsIPrefService);
- },
-
- getCryptoService: function() {
- return Components.classes['@mozilla.org/security/sdr;1']
- .createInstance(Components.interfaces.nsISecretDecoderRing);
- },
-
- getPrompts: function() {
- return Components.classes['@mozilla.org/embedcomp/prompt-service;1']
- .getService(Components.interfaces.nsIPromptService);
- },
-
- recognizeMouseButton: function(event) {
- var modifiers = new Array();
-
- // Get the modifiers:
- if(event.altKey) modifiers.push('alt');
- if(event.ctrlKey) modifiers.push('control');
- if(event.metaKey) modifiers.push('meta');
- if(event.shiftKey) modifiers.push('shift');
-
- // Return a mouseButtonObj:
- return this.mouseButtonFactory(modifiers, 'mousebutton'+event.button);
- },
-
- mouseButtonFactory: function(modifiers, mouseButton) {
- if(typeof arguments.callee.mouseButtonObj == 'undefined') {
- arguments.callee.mouseButtonObj = function(modifiers, mouseButton) {
- this.modifiers = modifiers ? modifiers : new Array();
- this.mouseButton = mouseButton;
- this.toString = function() {
- if(this.modifiers.length) {
- return this.modifiers.join('+')+'+'+this.mouseButton;
- } else {
- return this.mouseButton;
- }
- }
- this.equals = function(mouseButtonObj) {
- if(this.mouseButton != mouseButtonObj.mouseButton) {
- return false;
- }
- if(this.modifiers.length != mouseButtonObj.modifiers.length) {
- return false;
- }
- for(var i=0; i<this.modifiers.length; i++) {
- if(this.modifiers[i] != mouseButtonObj.modifiers[i]) {
- return false;
- }
- }
- return true;
- }
- return this;
- }
- }
- return new arguments.callee.mouseButtonObj(modifiers, mouseButton);
- },
-
- getFormattedMouseButton: function(mouseButtonObj) {
- var formattedMouseButton = '';
- if(!mouseButtonObj.mouseButton) {
- return formattedMouseButton;
- }
- // Add the modifiers:
- for(var i=0; i < mouseButtonObj.modifiers.length; i++) {
- try {
- formattedMouseButton += this.getStringBundle().getString(mouseButtonObj.modifiers[i])+'+';
- } catch(e) {
- this.log(e);
- // Error in shortcut string, return empty String:
- return '';
- }
- }
- try {
- formattedMouseButton += this.getStringBundle().getString(mouseButtonObj.mouseButton);
- } catch(e) {
- // No localization for this mouse button, add generic button string :
- formattedMouseButton += this.getStringBundle().getString('mousebutton');
- // Add the index of the given mouseButton:
- formattedMouseButton += ' '+mouseButtonObj.mouseButton.substr('mousebutton'.length);
- }
- return formattedMouseButton;
- },
-
- applyMouseButton: function(event, id) {
- // Recognize the mouse button event:
- var mouseButtonObj = this.recognizeMouseButton(event);
- if(!mouseButtonObj)
- return;
- // Ignore the right mouse button (mousebutton2), as this already invokes the context menu:
- if(mouseButtonObj.mouseButton == 'mousebutton2') {
- return;
- }
- // Save the new mouse button object:
- this.setMouseButton(id, mouseButtonObj);
- // Update the mouse button textbox:
- if(event.view.document && event.view.document.getElementById(id)) {
- event.view.document.getElementById(id).value = this.getFormattedMouseButton(mouseButtonObj);
- }
- },
-
- disableMouseButton: function(event, id) {
- // Disable the mouse button:
- this.setMouseButton(id, null);
- // Update the mouse button textbox:
- if(event.view.document && event.view.document.getElementById(id)) {
- event.view.document.getElementById(id).value = '';
- }
- },
-
- getMouseButton: function(id) {
- if(this.mouseButton == null) {
- // Create a new mouseButton container object:
- this.mouseButton = new Object();
- }
- if(this.mouseButton[id] == null) {
- var mouseButtonItems = this.autofillFormsPrefs.getCharPref(id).split('+');
- var mouseButton;
- if(mouseButtonItems.length == 0) {
- mouseButton = '';
- } else {
- // Remove the last element and save it as mouseButton
- // the remaining mouseButtonItems are the modifiers:
- mouseButton = mouseButtonItems.pop();
- }
- // Create a new mouseButton object:
- this.mouseButton[id] = this.mouseButtonFactory(mouseButtonItems, mouseButton);
- }
- return this.mouseButton[id];
- },
-
- setMouseButton: function(id, mouseButtonObj) {
- var stringData;
- if(mouseButtonObj) {
- stringData = mouseButtonObj.toString();
- } else {
- stringData = '';
- }
- // Save the mouseButtonObj as Unicode String in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- id,
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(stringData)
- );
- },
-
- recognizeKeys: function(event) {
- var modifiers = new Array();
- var key = '';
- var keycode = '';
-
- // Get the modifiers:
- if(event.altKey) modifiers.push('alt');
- if(event.ctrlKey) modifiers.push('control');
- if(event.metaKey) modifiers.push('meta');
- if(event.shiftKey) modifiers.push('shift');
-
- // Get the key or keycode:
- if(event.charCode) {
- key = String.fromCharCode(event.charCode).toUpperCase();
- } else {
- // Get the keycode from the keycodes list:
- keycode = this.getKeyCodes()[event.keyCode];
- if(!keycode) {
- return null;
- }
- }
-
- // Shortcut may be anything, but not 'VK_TAB' alone (without modifiers),
- // as this button is used to change focus to the 'Apply' button:
- if(modifiers.length > 0 || keycode != 'VK_TAB') {
- return this.shortcutFactory(modifiers, key, keycode);
- }
- return null;
- },
-
- shortcutFactory: function(modifiers, key, keycode) {
- if(typeof arguments.callee.shortcut == 'undefined') {
- arguments.callee.shortcut = function(modifiers, key, keycode) {
- this.modifiers = modifiers ? modifiers : new Array();
- this.key = key;
- this.keycode = keycode;
- this.toString = function() {
- if(this.modifiers.length) {
- return this.modifiers.join('+')+'+'+this.key+this.keycode;
- } else {
- return this.key+this.keycode;
- }
- }
- this.equals = function(shortcut) {
- if(this.key != shortcut.key) {
- return false;
- }
- if(this.keycode != shortcut.keycode) {
- return false;
- }
- if(this.modifiers.length != shortcut.modifiers.length) {
- return false;
- }
- for(var i=0; i<this.modifiers.length; i++) {
- if(this.modifiers[i] != shortcut.modifiers[i]) {
- return false;
- }
- }
- return true;
- }
- return this;
- }
- }
- return new arguments.callee.shortcut(modifiers, key, keycode);
- },
-
- getKeyCodes: function() {
- var keycodes = new Array();
- // Get the list of keycodes from the KeyEvent object:
- for(var property in KeyEvent) {
- keycodes[KeyEvent[property]] = property.replace('DOM_','');
- }
- // VK_BACK_SPACE (index 8) must be VK_BACK:
- keycodes[8] = 'VK_BACK';
- return keycodes;
- },
-
- applyShortcut: function(event, id) {
- // Recognize the pressed keys:
- var shortcut = this.recognizeKeys(event)
- if(!shortcut)
- return;
- // Save the new shortcut:
- this.setShortcut(id, shortcut);
- // Update the shortcut textbox:
- if(event.view.document && event.view.document.getElementById(id)) {
- event.view.document.getElementById(id).value = this.getFormattedShortcut(shortcut);
- }
- },
-
- disableShortcut: function(event, id) {
- // Disable the shortcut:
- this.setShortcut(id, null);
- // Update the shortcut textbox:
- if(event.view.document && event.view.document.getElementById(id)) {
- event.view.document.getElementById(id).value = '';
- }
- },
-
- getShortcut: function(id) {
- if(this.shortcut == null) {
- // Create a new shortcut container object:
- this.shortcut = new Object();
- }
- if(this.shortcut[id] == null) {
- var key = null;
- var keycode = null;
- var shortcutItems = this.autofillFormsPrefs
- .getComplexValue(id,Components.interfaces.nsIPrefLocalizedString)
- .data.split('+');
- if(shortcutItems.length > 0) {
- // Remove the last element and save it as key
- // the remaining shortcutItems are the modifiers:
- key = shortcutItems.pop();
- // Check if the key is a keycode:
- if(key.indexOf('VK') == 0) {
- keycode = key;
- key = null;
- }
- }
- // Create a new shortcut object:
- this.shortcut[id] = this.shortcutFactory(shortcutItems, key, keycode);
- }
- return this.shortcut[id];
- },
-
- setShortcut: function(id, shortcut) {
- var stringData;
- if(shortcut) {
- stringData = shortcut.toString();
- } else {
- stringData = '';
- }
- // Save the shortcut as Unicode String in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- id,
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(stringData)
- );
- },
-
- updateShortcut: function(id) {
- if(this.shortcut == null) {
- this.shortcut = new Object();
- }
- // Setting the shortcut object to "null" will update it on the next getShortcut() call:
- this.shortcut[id] = null;
-
- // Get the keyboard shortcut elements:
- var modifiers = this.getShortcut(id).modifiers.join(' ');
- var key = this.getShortcut(id).key;
- var keycode = this.getShortcut(id).keycode;
-
- var domId = 'autofillForms' + id.replace(/shortcut/, 'Shortcut');
- var command = 'autofillForms' + id.replace(/shortcut/i, '');
-
- // Remove current key if existing:
- if(document.getElementById(domId)) {
- document.getElementById('mainKeyset').removeChild(
- document.getElementById(domId)
- );
- }
-
- // Check if keyboard shortcut is enabled:
- if(key || keycode) {
- // Create a key element:
- var keyNode = document.createElement('key');
-
- keyNode.setAttribute('id', domId);
- keyNode.setAttribute('command', command);
-
- // Set the key attributes from saved shortcut:
- keyNode.setAttribute('modifiers', modifiers);
- if(key) {
- keyNode.setAttribute('key', key);
- } else {
- keyNode.setAttribute('keycode', keycode);
- }
-
- // Add the key to the mainKeyset:
- document.getElementById('mainKeyset').appendChild(keyNode);
- }
- },
-
- getFormattedShortcut: function(shortcut) {
- var formattedShortcut = '';
- // Add the modifiers:
- for(var i=0; i < shortcut.modifiers.length; i++) {
- try {
- formattedShortcut += this.getStringBundle().getString(shortcut.modifiers[i]) + '+';
- } catch(e) {
- // Error in shortcut string, return empty String;
- return '';
- }
- }
- if(shortcut.key) {
- // Add the key:
- if(shortcut.key == ' ') {
- formattedShortcut += this.getStringBundle().getString('VK_SPACE');
- } else {
- formattedShortcut += shortcut.key;
- }
- } else if(shortcut.keycode) {
- // Add the keycode (instead of the key):
- try {
- formattedShortcut += this.getStringBundle().getString(shortcut.keycode);
- } catch(e) {
- formattedShortcut += shortcut.keycode.replace('VK_', '');
- }
- }
- return formattedShortcut;
- },
-
- replaceDynamicTags: function(fieldRuleValue) {
- // Replace all dynamic tags with the return values of their associated tag codes:
- for(var j=0; j<this.getDynamicTags().length; j++) {
- // Catch if the number of tags doesn't match the number of tag codes or if the tag code is invalid:
- try {
- var regExpObj = new RegExp(this.getDynamicTags()[j],'g');
- // We use eval() here without restrictions - the given tagCode must be trusted:
- fieldRuleValue = fieldRuleValue.replace(regExpObj, eval(this.getDynamicTagCodes()[j]));
- } catch(e) {
- this.log(e);
- }
- }
- return fieldRuleValue;
- },
-
- getDynamicTagsFile: function() {
- var file = this.getConfigDirectory();
- file.append('dynamicTags.txt');
- if(!file.exists()) {
- file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
- }
- return file;
- },
-
- exportDynamicTagsToConfigDirectory: function() {
- var prefString;
- // Get the dynamicTags string from the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
- .data;
- if(prefString) {
- this.setFileContent(this.getDynamicTagsFile(), prefString);
- }
- },
-
- importDynamicTagsFromConfigDirectory: function() {
- var prefString;
- prefString = this.getFileContent(this.getDynamicTagsFile());
- if(prefString) {
- // Store the dynamicTags as unicode string in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'dynamicTags',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getDynamicTags: function() {
- if(this.dynamicTags == null) {
- var prefString;
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Get the dynamicTags string from the dynamicTags file in the configDirectory:
- prefString = this.getFileContent(this.getDynamicTagsFile());
- }
- if(!prefString) {
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTags',Components.interfaces.nsIPrefLocalizedString)
- .data;
- }
- this.dynamicTags = prefString.split('\t');
- }
- return this.dynamicTags;
- },
-
- setDynamicTags: function(dynamicTags) {
- // Save the dynamic tags separated by tabs:
- var prefString = dynamicTags.join('\t');
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- this.setFileContent(this.getDynamicTagsFile(), prefString);
- } else {
- this.autofillFormsPrefs.setComplexValue(
- 'dynamicTags',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getDynamicTagCodesFile: function() {
- var file = this.getConfigDirectory();
- file.append('dynamicTagCodes.txt');
- if(!file.exists()) {
- file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0660);
- }
- return file;
- },
-
- exportDynamicTagCodesToConfigDirectory: function() {
- var prefString;
- // Get the dynamicTagCodes string from the preferences:
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
- .data;
- if(prefString) {
- this.setFileContent(this.getDynamicTagCodesFile(), prefString);
- }
- },
-
- importDynamicTagCodesFromConfigDirectory: function() {
- var prefString;
- prefString = this.getFileContent(this.getDynamicTagCodesFile());
- if(prefString) {
- // Store the dynamicTagCodes as unicode string in the preferences:
- this.autofillFormsPrefs.setComplexValue(
- 'dynamicTagCodes',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- getDynamicTagCodes: function() {
- if(this.dynamicTagCodes == null) {
- var prefString;
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Get the dynamicTagCodes string from the dynamicTagCodes file in the configDirectory:
- prefString = this.getFileContent(this.getDynamicTagCodesFile());
- }
- if(!prefString) {
- prefString = this.autofillFormsPrefs
- .getComplexValue('dynamicTagCodes',Components.interfaces.nsIPrefLocalizedString)
- .data;
- }
- this.dynamicTagCodes = prefString.split('\t');
- }
- return this.dynamicTagCodes;
- },
-
- setDynamicTagCodes: function(dynamicTagCodes) {
- // Save the dynamic tag codes separated by tabs:
- var prefString = dynamicTagCodes.join('\t');
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- this.setFileContent(this.getDynamicTagCodesFile(), prefString);
- } else {
- this.autofillFormsPrefs.setComplexValue(
- 'dynamicTagCodes',
- Components.interfaces.nsISupportsString,
- this.getUnicodeString(prefString)
- );
- }
- },
-
- optionsInitialize: function() {
- // Save the reference to the Autofill Forms preferences branch:
- this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
-
- // Initialize the profile lists:
- this.initProfilesLists();
- // Initialize the fieldRules tree:
- this.initTree();
- // Initialize the simple interface:
- this.initSimpleInterface();
-
- // Sort is to be ascending if clicked first:
- this.ascending = true;
- this.profilesAscending = true;
-
- var configDirectoryTextbox = document.getElementById('configDirectoryTextBox');
- if(configDirectoryTextbox && this.autofillFormsPrefs.prefHasUserValue('configDirectory')) {
- var configDirectory = this.getConfigDirectory();
- if(configDirectory) {
- configDirectoryTextbox.value = configDirectory.path;
- }
- }
-
- // Initialize the keyboard shortcut objects:
- this.shortcut = new Object();
- this.shortcut['shortcut'] = null;
- this.shortcut['shortcutSubmit'] = null;
- this.shortcut['shortcutAllTabs'] = null;
- this.shortcut['shortcutFromProfileSelection'] = null;
- this.shortcut['shortcutProfile'] = null;
- this.shortcut['shortcutSettings'] = null;
- this.shortcut['shortcutDisplayFormDetails'] = null;
-
- // Display the shortcut combinations:
- for(var property in this.shortcut) {
- if(document.getElementById(property)) {
- document.getElementById(property).value = this.getFormattedShortcut(this.getShortcut(property));
- }
- }
-
- // Initialize the mouse button objects:
- this.mouseButton = new Object();
- this.mouseButton['mouseShortcut'] = null;
- this.mouseButton['mouseShortcutSubmit'] = null;
- this.mouseButton['mouseShortcutAllTabs'] = null;
- this.mouseButton['mouseShortcutFromProfileSelection'] = null;
- this.mouseButton['mouseShortcutProfile'] = null;
- this.mouseButton['mouseShortcutSettings'] = null;
- this.mouseButton['mouseShortcutDisplayFormDetails'] = null;
-
- // Display the mouse button combinations:
- for(var property in this.mouseButton) {
- if(document.getElementById(property)) {
- document.getElementById(property).value = this.getFormattedMouseButton(this.getMouseButton(property));
- }
- }
-
- // Parse the window params (e.g. initializing the target form field values):
- this.parseOptionsWindowParams();
- },
-
- initSimpleInterface: function() {
- var rows = document.getElementById('simpleInterfaceRows');
- if(rows) {
- while(rows.hasChildNodes()) {
- rows.removeChild(rows.firstChild);
- }
- for(var i=0; i<this.getFieldRules().length; i++) {
- // Only show enabled fieldRules:
- if(!this.getFieldRules()[i]['fieldRuleEnabled']) {
- continue;
- }
- rows.appendChild(
- this.getSimpleInterfaceRow(
- i,
- this.getFieldRules()[i]['fieldRuleName'],
- this.getFieldRules()[i]['fieldRuleValue']
- )
- );
- }
- }
- },
-
- addSimpleInterfaceRow: function(index) {
- var row = this.getSimpleInterfaceRow(
- index,
- this.getFieldRules()[index]['fieldRuleName'],
- this.getFieldRules()[index]['fieldRuleValue']
- )
- var rows = document.getElementById('simpleInterfaceRows');
- if(rows) {
- var nextSibling;
- if(rows.childNodes) {
- for(var i=index+1; i<rows.childNodes.length; i++) {
- nextSibling = document.getElementById('simpleInterfaceRow_'+i);
- if(nextSibling) {
- rows.insertBefore(row, nextSibling);
- break;
- }
- }
- }
- if(!nextSibling) {
- rows.appendChild(row);
- }
- }
- },
-
- removeSimpleInterfaceRow: function(index) {
- var row = document.getElementById('simpleInterfaceRow_'+index);
- if(row) {
- row.parentNode.removeChild(row);
- }
- },
-
- getSimpleInterfaceRow: function(index, name, value) {
- if(!arguments.callee.row) {
- arguments.callee.row = document.createElement('row');
- arguments.callee.row.setAttribute('align', 'center');
- var label = document.createElement('label');
- var textbox = document.createElement('textbox');
- textbox.setAttribute(
- 'onchange',
- 'autofillForms.applySimpleInterfaceValue(this)'
- );
- textbox.setAttribute(
- 'oninput',
- 'this.value=autofillForms.replaceControlCharacters(this.value)'
- );
- textbox.setAttribute('newlines', 'pasteintact');
- arguments.callee.row.appendChild(label);
- arguments.callee.row.appendChild(textbox);
- }
- var row = arguments.callee.row.cloneNode(true);
- row.setAttribute('id', 'simpleInterfaceRow_'+index);
- row.firstChild.setAttribute('value', name+':');
- row.firstChild.setAttribute('id', 'simpleInterfaceLabel_'+index);
- row.firstChild.setAttribute('control', 'simpleInterfaceTextbox_'+index);
- row.lastChild.setAttribute('id', 'simpleInterfaceTextbox_'+index);
- row.lastChild.setAttribute('value', value);
- // Is textbox a password field?
- if(this.getRegExpPasswordLabel().test(name)) {
- row.lastChild.setAttribute('type', 'password');
- }
- return row;
- },
-
- applySimpleInterfaceValue: function(textBox) {
- // See method selectedFieldRule() why this has to be set to null:
- this.lastSelectedIndex = null;
-
- var index = parseInt(textBox.getAttribute('id').split('_')[1]);
- this.getFieldRules()[index]['fieldRuleValue'] = this.makeSafe(textBox.value);
-
- // Notify the tree (of the advanced interface):
- try {
- this.treeBox.invalidateRow(index);
- } catch(e) {
- }
-
- // Update the preferences:
- this.setFieldRules();
- },
-
- updateSimpleInterfaceRow: function(index) {
- var row = document.getElementById('simpleInterfaceRow_'+index);
- if(row) {
- row.firstChild.value = this.getFieldRules()[index]['fieldRuleName']+':';
- row.lastChild.value = this.getFieldRules()[index]['fieldRuleValue'];
- // Is textbox a password field?
- if(this.getRegExpPasswordLabel().test(this.getFieldRules()[index]['fieldRuleName'])) {
- row.lastChild.setAttribute('type', 'password');
- } else {
- row.lastChild.removeAttribute('type');
- }
- }
- },
-
- getFieldRuleNameForElement: function(element) {
- // Use the form field label as name if available:
- var labelValue = this.getLabelForElement(element);
- // Remove the colon, if present:
- if(labelValue && labelValue.charAt(labelValue.length-1) == ':') {
- labelValue = labelValue.substr(0, labelValue.length-1);
- }
- // If no label could be found, use the name or the id with the first character in upper case:
- if(!labelValue) {
- labelValue = element.name;
- if(!labelValue) {
- labelValue = element.id;
- }
- if(labelValue) {
- labelValue = labelValue.charAt(0).toUpperCase() + labelValue.substr(1);
- }
- }
- return labelValue;
- },
-
- getRegExpStrForValue: function(value) {
- try {
- // Remove unsave characters, escape regexp characters and return the regexp string:
- return this.getRegExpStr('(?:^'+this.escapeRegExp(this.makeSafe(value))+'$)');
- } catch(e) {
- // If an error occurs, return the safe value string.
- // If using it as regular expression fails a simple string comparison is used:
- return this.makeSafe(value);
- }
- },
-
- getFieldRuleForElement: function(element) {
- var name = element.name;
- // If no name is available use the label as fallback:
- if(!name) {
- name = this.getLabelForElement(element);
- }
- // If no name and no label is available use the id as fallback:
- if(!name) {
- name = element.id;
- }
- try {
- // Remove unsave characters, escape regexp characters and return the regexp string:
- return this.getRegExpStr('(?:^'+this.escapeRegExp(this.makeSafe(name))+'$)');
- } catch(e) {
- // If an error occurs, return an always matching regexp string:
- return '(?:)';
- }
- },
-
- getSiteRuleForURL: function(url) {
- try {
- // Remove unsave characters, escape regexp characters and return the regexp string:
- return this.getRegExpStr('(?:^'+this.escapeRegExp(this.makeSafe(url))+')');
- } catch(e) {
- // If an error occurs, return an always matching regexp string:
- return '(?:)';
- }
- },
-
- parseOptionsWindowParams: function() {
- // Check the windows arguments:
- if(window.arguments && window.arguments[0]) {
- if(window.arguments[0].targetFormField) {
- var formFieldObject = window.arguments[0].targetFormField;
-
- var value;
- switch(formFieldObject.type) {
- case 'checkbox':
- case 'radio':
- case 'select-one':
- case 'select-multiple':
- value = this.getRegExpStrForValue(formFieldObject.value);
- break;
- default:
- value = this.replaceControlCharacters(formFieldObject.value);
- break;
- }
-
- var location = this.getDoc().location;
-
- // Reset the targetFormField of the autofillForms object referenced by window.arguments[0]:
- window.arguments[0].targetFormField = null;
-
- // Set the textbox values using the form field properties and the current document location:
- document.getElementById('fieldRuleNameTextBox').value
- = this.getFieldRuleNameForElement(formFieldObject)
- + (location.hostname ? ' - ' + location.hostname : '');
- document.getElementById('fieldRuleValueTextBox').value = value;
- document.getElementById('fieldRuleFieldRuleTextBox').value
- = this.getFieldRuleForElement(formFieldObject);
- document.getElementById('fieldRuleSiteRuleTextBox').value
- = this.getSiteRuleForURL(location.protocol + '//' + location.host);
-
- // Make sure the main pane is selected:
- document.getElementById('autofillFormsPrefs').showPane(
- document.getElementById('autofillFormsPrefPaneMain')
- );
-
- // Set the focus to the name field:
- document.getElementById('fieldRuleNameTextBox').focus();
- } else if(window.arguments[0].newProfileFromForm) {
- // Make sure the main pane is selected:
- document.getElementById('autofillFormsPrefs').showPane(
- document.getElementById('autofillFormsPrefPaneMain')
- );
- }
- }
- },
-
- optionsFinalize: function() {
- },
-
- showProfileSwitcher: function() {
- if(this.autofillFormsPrefs.getBoolPref('useConfigDirectory')) {
- // Always retrieve the profile labels from file if useConfigDirectory is enabled:
- this.profileLabels = null;
- }
- // The nsIPromptService select() method doesn't offer to set a preselection,
- // so we switch the current profile label with the first item (which is selected by default):
- var list;
- var currentIndex = this.getProfileIndex();
- if(currentIndex != 0) {
- // Copy the profilLabels array (so we don't change the original):
- list = new Array().concat(this.getProfileLabels());
- // Switch the current profile label with the first item:
- var tmp = list[0];
- list[0] = list[currentIndex];
- list[currentIndex] = tmp;
- } else {
- // Set the list to the profilLabels reference if it is not to be changed:
- list = this.getProfileLabels();
- }
- var selected = {};
- // Show the selection prompt:
- var ok = this.getPrompts().select(
- window,
- this.getStringBundle().getString('profileSelectionWindowTitle'),
- this.getStringBundle().getString('profileSelectionPrompt'),
- list.length,
- list,
- selected
- );
- if(ok) {
- // If nothing changed, return:
- if(selected.value == 0)
- return;
- // If the currentIndex has been selected and is not 0, it is in fact the index 0:
- if(currentIndex != 0 && selected.value == currentIndex)
- selected.value = 0;
- // Set the profile index to the selected one:
- this.setProfileIndex(selected.value)
- }
- },
-
- showDialog: function(url, params) {
- if (this.currentDialogs == null) {
- this.currentDialogs = new Object();
- }
-
- // Is the window already
- var win = this.currentDialogs[url];
- if (win == null || win.closed)
- {
- var paramObject = params ? params : this;
- win = window.openDialog(
- url,
- '',
- 'chrome=yes,resizable=yes,toolbar=yes,centerscreen=yes,modal=no,dependent=no,dialog=no',
- paramObject
- );
- this.currentDialogs[url] = win;
- return win;
- } else {
- win.focus();
- }
- },
-
- inArray: function(array, item) {
- var i = array.length;
- while(i--)
- if(array[i] === item)
- return true;
- return false;
- },
-
- displayFormDetails: function() {
- this.searchAndDisplayFormDetails(this.getWin());
- },
-
- searchAndDisplayFormDetails: function(win) {
- win = win ? win : this.getWin();
-
- var doc = this.getDoc(win);
-
- // Check if any web forms are available on the current window:
- if(doc && doc.forms && doc.forms.length > 0) {
-
- // Go through the forms:
- for(var i = 0; i < doc.forms.length; i++) {
-
- // The form elements list:
- var elements = doc.forms[i].elements;
-
- // Go through the form elements:
- for(var j = 0; j < elements.length; j++) {
- this.displayFormElementDetails(elements[j], j, i, doc);
- }
- }
- }
-
- // Recursive call for all subframes:
- for(var f=0; f < win.frames.length; f++) {
- this.searchAndDisplayFormDetails(win.frames[f]);
- }
- },
-
- isValidFormField: function(element) {
- // ignore disabled (and return false) only if 'ignore disabled fields' is ticked
- if(element.disabled && this.autofillFormsPrefs.getBoolPref('ignoreDisabledFields')) {
- return false;
- }
- if(!arguments.callee.regExpFormFieldType) {
- arguments.callee.regExpFormFieldType = new RegExp(
- this.autofillFormsPrefs.getCharPref('regExpFormFieldTypes')
- );
- }
- return arguments.callee.regExpFormFieldType.test(element.type);
- },
-
- displayFormElementDetails: function(element, elementNumber, formNumber, doc) {
- // Create a unique id for the form element:
- var id = 'autofillForms-f' + formNumber + '-e' + elementNumber;
-
- // Remove the form details node if already present
- // (nodeType 1 is an element node):
- if(element.nextSibling && element.nextSibling.nodeType == 1 && element.nextSibling.getAttribute('id') == id) {
- element.parentNode.removeChild(element.nextSibling);
- return;
- }
-
- // Only display valid form fields:
- if(this.isValidFormField(element)) {
- // Create a "span" node with element details:
- var text;
- // Display the element name if available, else the element id if available, else an empty name:
- if(element.name || !element.id) {
- text = 'name="' + element.name;
- } else {
- text = 'id="' + element.id;
- }
- // Display the element value:
- text += '" value="' + element.value + '"';
- var span = doc.createElement('span');
- span.setAttribute('id', id);
- span.setAttribute('style', this.autofillFormsPrefs.getCharPref('formDetailsStyle'));
- span.setAttribute('title', text);
- span.appendChild(doc.createTextNode(text));
-
- // Insert the form details node after the element:
- if(element.nextSibling)
- element.parentNode.insertBefore(span, element.nextSibling);
- else
- element.parentNode.appendChild(span);
- }
- },
-
- ruleEditorInitialize: function() {
- // Save the reference to the Autofill Forms preferences branch:
- this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
-
- if(window.arguments && window.arguments[0] && window.arguments[0].attributes) {
- this.currentRuleField = window.arguments[0];
- }
-
- // Initialize the ruleElementTypes:
- this.ruleElementTypes = new Array();
- this.ruleElementTypes.push('contains');
- this.ruleElementTypes.push('beginsWith');
- this.ruleElementTypes.push('endsWith');
- this.ruleElementTypes.push('equals');
-
- // If the rule editor is used to edit the site rule, add two predefined protocol rules:
- if(this.currentRuleField && this.currentRuleField.id && this.currentRuleField.id.indexOf('SiteRule') != -1) {
- this.ruleEditorAdd('beginsWith', 'http:\/\/');
- this.ruleEditorAdd('beginsWith', 'https:\/\/');
- } else {
- this.ruleEditorAdd();
- }
- },
-
- ruleEditorSave: function() {
- if(document.getElementById('ruleElementsList')) {
- var str = '';
- var richlistbox = document.getElementById('ruleElementsList');
- var richlistitems = richlistbox.getElementsByTagName('richlistitem');
- var menulists,textboxes;
-
- // Go through the richlistbox items:
- for(var i=0; i<richlistitems.length; i++) {
- // Link the conditions as disjunctions (OR-Relations);
- if(str.length != 0)
- str += '|';
- menulists = richlistitems[i].getElementsByTagName('menulist');
- textboxes = richlistitems[i].getElementsByTagName('textbox');
-
- // Add the current condition to the string:
- switch(menulists[0].selectedItem.value) {
- case 'contains':
- str += '(?:' + textboxes[0].value + ')';
- break;
- case 'beginsWith':
- str += '(?:^' + textboxes[0].value + ')';
- break;
- case 'endsWith':
- str += '(?:' + textboxes[0].value + '$)';
- break;
- case 'equals':
- str += '(?:^' + textboxes[0].value + '$)';
- break;
- }
- }
- if(this.currentRuleField) {
- // Set the current field value to the created string:
- this.currentRuleField.value = str;
- // Call the onchange handler:
- if(this.currentRuleField.onchange) {
- this.currentRuleField.onchange();
- }
- // Call the focus handler:
- if(this.currentRuleField.focus) {
- this.currentRuleField.focus();
- }
- }
- }
- return true;
- },
-
- ruleEditorAdd: function(type, ruleElement) {
- if(document.getElementById('ruleElementsList')) {
- var richlistbox = document.getElementById('ruleElementsList');
-
- var richlistitem,menulist,menupopup,menuitem,textbox,label;
-
- richlistitem = document.createElement('richlistitem');
-
- // Create the condition type menu:
- menulist = document.createElement('menulist');
- menupopup = document.createElement('menupopup');
-
- var selectedIndex = 0;
-
- // Create the menu of ruleElementTypes:
- for(var i=0; i<this.ruleElementTypes.length; i++) {
- menuitem = document.createElement('menuitem');
- menuitem.setAttribute(
- 'value',
- this.ruleElementTypes[i]
- );
- menuitem.setAttribute(
- 'label',
- this.getStringBundle().getString(this.ruleElementTypes[i] + 'RuleType')
- );
- menupopup.appendChild(menuitem);
-
- // Set the selectedIndex:
- if(type != null && type == this.ruleElementTypes[i])
- selectedIndex = i;
- }
-
- menulist.appendChild(menupopup);
- richlistitem.appendChild(menulist);
-
- // Create the textbox:
- textbox = document.createElement('textbox');
- if(ruleElement != null)
- textbox.setAttribute('value',ruleElement);
- textbox.setAttribute('flex','1');
- richlistitem.appendChild(textbox);
-
- richlistbox.appendChild(richlistitem);
-
- // Select the menuitem:
- menulist.selectedIndex = selectedIndex;
- }
- },
-
- ruleEditorRemove: function(index) {
- var ruleElementsList = document.getElementById('ruleElementsList');
- if(ruleElementsList) {
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- // Confirmation dialog:
- if(!this.getPrompts().confirm(
- null,
- this.getStringBundle().getString('removeRuleConditionTitle'),
- this.getStringBundle().getString('removeRuleConditionText')
- )
- ) {
- return;
- }
- }
-
- var richlistbox = ruleElementsList;
- if(index)
- richlistbox.selectedIndex = index;
- if(richlistbox.selectedItem && richlistbox.selectedIndex != -1)
- richlistbox.removeChild(richlistbox.selectedItem);
- }
- },
-
- ruleEditorIsTextBoxFocused: function() {
- return this.ruleEditorTextBoxFocused;
- },
-
- ruleEditorFocus: function() {
- var focusedElement = document.commandDispatcher.focusedElement;
-
- // Monitor if a textbox is focused:
- if(!this.ruleEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'html:input') {
- this.ruleEditorTextBoxFocused = true;
- } else if(this.ruleEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'richlistbox') {
- this.ruleEditorTextBoxFocused = false;
- }
- },
-
- ruleEditorHandleKeyPress: function(event) {
- // Only remove a dynamic tag on delete key press if no textbox is focused:
- if(event.keyCode == 46 && !this.ruleEditorIsTextBoxFocused()) {
- this.ruleEditorRemove();
- }
- },
-
- ruleEditorFinalize: function() {
- this.currentRuleField = null;
- },
-
- tagEditorInitialize: function() {
- // Save the reference to the Autofill Forms preferences branch:
- this.autofillFormsPrefs = this.getPrefManager().getBranch('extensions.autofillForms at blueimp.net.');
-
- // Add existing tags to the list:
- for(var i=0; i<this.getDynamicTags().length; i++) {
- // Catch if the number of tags doesn't match the number of tag codes:
- try {
- this.tagEditorAdd(this.getDynamicTags()[i],this.getDynamicTagCodes()[i])
- } catch(e) {
- this.log(e);
- }
- }
- },
-
- tagEditorSave: function() {
- var richlistbox = document.getElementById('tagList');
- if(richlistbox) {
- var richlistitems = richlistbox.getElementsByTagName('richlistitem');
- var textboxes;
-
- var dynamicTags = new Array();
- var dynamicTagCodes = new Array();
-
- // Go through the richlistbox items:
- for(var i=0; i<richlistitems.length; i++) {
- textboxes = richlistitems[i].getElementsByTagName('textbox');
-
- // Add the dynamic tags and their associated tag codes to the lists:
- if (textboxes[0].value != '' && textboxes[1].value != '') {
- dynamicTags.push(this.makeSafe(textboxes[0].value));
- dynamicTagCodes.push(this.makeSafe(textboxes[1].value));
- }
- }
- // Save the lists in the preferences:
- this.setDynamicTags(dynamicTags);
- this.setDynamicTagCodes(dynamicTagCodes);
- }
- return true;
- },
-
- tagEditorAdd: function(tag, tagCode) {
- var richlistbox = document.getElementById('tagList');
- if(richlistbox) {
- var richlistitem,textbox;
-
- richlistitem = document.createElement('richlistitem');
-
- // Create the tag textbox:
- textbox = document.createElement('textbox');
- textbox.setAttribute('class','tag');
- if(tag != null)
- textbox.setAttribute('value',tag);
- richlistitem.appendChild(textbox);
-
- // Create the tagCode textbox:
- textbox = document.createElement('textbox');
- textbox.setAttribute('class','tagCode');
- textbox.setAttribute('flex','1');
- if(tagCode != null)
- textbox.setAttribute('value',tagCode);
- richlistitem.appendChild(textbox);
-
- richlistbox.appendChild(richlistitem);
- }
- },
-
- tagEditorRemove: function(index) {
- var richlistbox = document.getElementById('tagList');
- if(richlistbox) {
- if(this.autofillFormsPrefs.getBoolPref('enableConfirmationDialogs')) {
- // Confirmation dialog:
- if(!this.getPrompts().confirm(
- null,
- this.getStringBundle().getString('removeDynamicTagTitle'),
- this.getStringBundle().getString('removeDynamicTagText')
- )
- ) {
- return;
- }
- }
- if(index)
- richlistbox.selectedIndex = index;
- if(richlistbox.selectedItem && richlistbox.selectedIndex != -1)
- {
- richlistbox.removeChild(richlistbox.selectedItem);
- }
- }
- },
-
- tagEditorValidate: function(index) {
- var richlistbox = document.getElementById('tagList');
- if(richlistbox) {
- if(index)
- richlistbox.selectedIndex = index;
- if(richlistbox.selectedItem) {
- var tagCode = richlistbox.selectedItem.lastChild.value;
- var validationResultTextBox = document.getElementById('validationResultTextBox');
- try {
- validationResultTextBox.removeAttribute('style');
- // We use eval() here without restrictions - the given tagCode must be trusted:
- validationResultTextBox.value = eval(tagCode);
- } catch(e) {
- validationResultTextBox.setAttribute('style', 'color:red;');
- validationResultTextBox.value = e;
- }
- }
- }
- },
-
- tagEditorIsTextBoxFocused: function() {
- return this.tagEditorTextBoxFocused;
- },
-
- tagEditorFocus: function() {
- var focusedElement = document.commandDispatcher.focusedElement;
-
- // Monitor if a textbox is focused:
- if(!this.tagEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'html:input') {
- this.tagEditorTextBoxFocused = true;
- } else if(this.tagEditorTextBoxFocused && focusedElement && focusedElement.tagName == 'richlistbox') {
- this.tagEditorTextBoxFocused = false;
- }
- },
-
- tagEditorHandleKeyPress: function(event) {
- // Only remove a dynamic tag on delete key press if no textbox is focused:
- if(event.keyCode == 46 && !this.tagEditorIsTextBoxFocused()) {
- this.tagEditorRemove();
- }
- },
-
- tagEditorFinalize: function() {
- },
-
- openHelp: function(topic) {
- if(!topic) {
- topic = '';
- }
- var url = this.autofillFormsPrefs.getCharPref('helpURL').replace(/\[TOPIC\]$/, topic);
- this.openNewTab(url, true);
- },
-
- openNewTab: function(url, focus) {
- var helpTab = this.getBrowser().addTab(url);
- if(focus) {
- this.getBrowser().selectedTab = helpTab;
- this.getWindowMediator().getMostRecentWindow('navigator:browser').focus();
- }
- },
-
- addLeadingZeros: function(number, length) {
- number = number.toString();
- while(number.length < length) {
- number = '0'+number;
- }
- return number;
- },
-
- escapeRegExp: function(str) {
- if (!arguments.callee.regExp) {
- var specials = new Array(
- '^', '$', '*', '+', '?', '.', '|', '/',
- '(', ')', '[', ']', '{', '}', '\\'
- );
- arguments.callee.regExp = new RegExp(
- '(\\' + specials.join('|\\') + ')', 'g'
- );
- }
- return str.replace(arguments.callee.regExp, '\\$1');
- },
-
- getClipboardText: function() {
- var clipboardText = null;
- var clip = Components.classes['@mozilla.org/widget/clipboard;1']
- .getService(Components.interfaces.nsIClipboard);
- if(!clip) {
- return null;
- }
-
- var trans = Components.classes['@mozilla.org/widget/transferable;1']
- .createInstance(Components.interfaces.nsITransferable);
- if(!trans) {
- return null;
- }
-
- trans.addDataFlavor('text/unicode');
-
- clip.getData(trans, clip.kGlobalClipboard);
-
- var str = new Object();
- var strLength = new Object();
-
- trans.getTransferData('text/unicode', str, strLength);
-
- if(str) {
- str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
- }
- if(str) {
- clipboardText = str.data.substring(0, strLength.value / 2);
- }
-
- return clipboardText
- },
-
- getMasterSecurityDevice: function() {
- return Components.classes['@mozilla.org/security/pk11tokendb;1']
- .getService(Components.interfaces.nsIPK11TokenDB);
- },
-
- log: function(aMessage, aSourceName, aSourceLine, aLineNumber, aColumnNumber, aFlags, aCategory) {
- var consoleService = Components.classes['@mozilla.org/consoleservice;1']
- .getService(Components.interfaces.nsIConsoleService);
- if(aSourceName != 'undefined') {
- var scriptError = Components.classes["@mozilla.org/scripterror;1"]
- .createInstance(Components.interfaces.nsIScriptError);
- scriptError.init(
- aMessage,
- aSourceName,
- aSourceLine,
- aLineNumber,
- aColumnNumber,
- aFlags,
- aCategory
- );
- consoleService.logMessage(scriptError);
- } else {
- consoleService.logStringMessage(aMessage);
- }
- },
-
- finalizeToolbarButtonStatus: function() {
- var autofillFormsButton = document.getElementById('autofillFormsButton');
- var hideToolbarButton = this.autofillFormsPrefs.getBoolPref('hideToolbarButton');
- if(!autofillFormsButton && !hideToolbarButton) {
- // If the toolbar button icon has been removed from the toolbar by drag&drop
- // enable the hideToolbarButton setting:
- this.autofillFormsPrefs.setBoolPref('hideToolbarButton', true);
- } else if(autofillFormsButton && !autofillFormsButton.getAttribute('hidden')) {
- // If the toolbar button icon has been added to the toolbar by drag&drop
- // disable the hideToolbarButton setting:
- this.autofillFormsPrefs.setBoolPref('hideToolbarButton', false);
- }
- },
-
- finalize: function() {
- this.finalizeToolbarButtonStatus();
-
- // Remove the content area context menu listener:
- var contentAreaContextMenu = document.getElementById('contentAreaContextMenu');
- if(contentAreaContextMenu) {
- contentAreaContextMenu.removeEventListener(
- 'popupshowing',
- this.contentAreaContextMenuEventListener,
- false
- );
- }
-
- // Remove the preferences Observer:
- this.autofillFormsPrefs.removeObserver('', this);
- }
-
-}
diff --git a/src/chrome/skin/autofillForms.css b/src/chrome/skin/autofillForms.css
deleted file mode 100644
index efb7dec..0000000
--- a/src/chrome/skin/autofillForms.css
+++ /dev/null
@@ -1,46 +0,0 @@
-#autofillFormsButton,
-.autofillFormsButton {
- list-style-image: url("pencil.png");
-}
-toolbar[iconsize="small"] #autofillFormsButton,
-toolbar[iconsize="small"] .autofillFormsButton,
-.autofillFormsIcon {
- list-style-image: url("pencil-small.png");
-}
-
-.autofillFormsProfileIcon {
- list-style-image: url("profile-small.png");
-}
-.autofillFormsSettingsIcon {
- list-style-image: url("settings-small.png");
-}
-.autofillFormsHelpIcon {
- list-style-image: url("help-small.png");
-}
-
-statusbarpanel.autofillFormsIcon {
- cursor: pointer;
-}
-
-#autofillFormsTooltipCurrentProfile {
- margin-bottom:10px;
-}
-#autofillFormsTooltipCurrentProfileCaption {
-}
-#autofillFormsTooltipCurrentProfileLabel {
- font-weight: bold;
-}
-#autofillFormsTooltipGrid {
-}
-.autofillFormsTooltipGridHeader {
- font-weight:bold;
- margin-bottom:5px;
-}
-.autofillFormsTooltipGridCommand {
-}
-.autofillFormsTooltipGridMouseButton {
- font-style:italic;
-}
-.autofillFormsTooltipGridKeyboardShortcut {
- font-family:monospace;
-}
diff --git a/src/install.rdf b/src/install.rdf
deleted file mode 100644
index 57fcffb..0000000
--- a/src/install.rdf
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
- <Description about="urn:mozilla:install-manifest">
- <em:id>autofillForms at blueimp.net</em:id>
- <em:name>Autofill Forms</em:name>
- <em:creator>Sebastian Tschan</em:creator>
- <em:description>Fill out web forms automatically</em:description>
- <em:iconURL>chrome://autofillForms/skin/icon.png</em:iconURL>
- <em:optionsURL>chrome://autofillForms/content/autofillFormsOptions.xul</em:optionsURL>
- <em:homepageURL>https://blueimp.net/mozilla/</em:homepageURL>
- <em:version>0.9.9.0</em:version>
- <em:targetApplication>
- <Description>
- <!-- Firefox -->
- <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
- <em:minVersion>17.0</em:minVersion>
- <em:maxVersion>19.*</em:maxVersion>
- </Description>
- </em:targetApplication>
- <em:targetApplication>
- <Description>
- <!-- Midbrowser -->
- <em:id>{aa5ca914-c309-495d-91cf-3141bbb04115}</em:id>
- <em:minVersion>0.2</em:minVersion>
- <em:maxVersion>2.0.0.6</em:maxVersion>
- </Description>
- </em:targetApplication>
- <em:translator>PetrTwo (Czech)</em:translator>
- <em:translator>Oliver Roth (German)</em:translator>
- <em:translator>Koumen (Greek)</em:translator>
- <em:translator>jesuspportillo (Spanish)</em:translator>
- <em:translator>Unknown (Finnish)</em:translator>
- <em:translator>myahoo (French)</em:translator>
- <em:translator>YuvalSht (Hebrew)</em:translator>
- <em:translator>Mikes Kaszmán István (Hungarian)</em:translator>
- <em:translator>Underpass (Italian)</em:translator>
- <em:translator>gonzalopirobutirro (Italian)</em:translator>
- <em:translator>Godai71 (Italian)</em:translator>
- <em:translator>markh (Dutch)</em:translator>
- <em:translator>teo (Polish)</em:translator>
- <em:translator>Alberto Eidh (Portuguese - Brazilian)</em:translator>
- <em:translator>x10firefox (Romanian)</em:translator>
- <em:translator>Unknown (Russian)</em:translator>
- <em:translator>Umut (Swedish)</em:translator>
- <em:translator>ch0ze (Slovak)</em:translator>
- <em:translator>KenanBalamir (Turkish)</em:translator>
- <em:translator>simophin (Chinese - Simplified)</em:translator>
- <em:translator>Lu Ming-Tse (呂明澤) (Chinese - Traditional)</em:translator>
- </Description>
-</RDF>
diff --git a/www/bugs.html b/www/bugs.html
deleted file mode 100644
index 994ff01..0000000
--- a/www/bugs.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<h5 class="page-header">Bugs</h5>
-
-<ul>
-<li>Enter a <a href="http://bugzilla.mozdev.org/enter_bug.cgi?product=autofillforms">new bug</a> for Autofill Forms</li>
-<li>View <a href="http://bugzilla.mozdev.org/buglist.cgi?product=autofillforms">all bugs</a></li>
-<li>See all <a href="http://bugzilla.mozdev.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&emailtype1=substring&emailassigned_to1=1&emailtype2=substring&emailreporter2=1&bugidtype=include&chfieldto=Now&product=autofillforms&short_desc_type=allwordssubstr&long_desc_type=allwordssubstr&bug_file_loc_type=allwordssubstr&field0-0-0=noop&type0-0-0=noop&cmdtype=doit&order=Bug+Numbe [...]
-<li>Search by Bug Number<br>
-<form action="http://bugzilla.mozdev.org/show_bug.cgi" method="get">
-<p><input type="submit" value="Find"><input size="6" name="id"></p>
-</form>
-</li>
-</ul>
diff --git a/www/changelog.html b/www/changelog.html
deleted file mode 100644
index 924ff72..0000000
--- a/www/changelog.html
+++ /dev/null
@@ -1,545 +0,0 @@
-<h4 class="page-header">Changelog</h4>
-
-<h5 id="v0.1">Version 0.1</h5>
-<p>07.04.2007</p>
-<ul>
- <li>First release.</li>
-</ul>
-
-<h5 id="v0.2">Version 0.2</h5>
-<p>09.04.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added option to encrypt the stored form field rules - using Firefox nsISecretDecoderRing interface</li>
- <li>Improved method to set the form field value for non-text form elements - loop until "Value" matches</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.3">Version 0.3</h5>
-<p>10.05.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added profiles</li>
- <li>Added profile switcher</li>
- <li>Added shortcuts for profile switcher and settings page</li>
- <li>Extended toolbar button to include menu items for profile switcher and settings page</li>
- <li>Added 'Display Form Details' button on settings page to support creating form field rules</li>
- <li>Added Rule Editor to help creating custom rules without regular expression knowledge</li>
- <li>Improved settings page (using tabs, better structuring)</li>
- <li>Extended help page</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.4">Version 0.4</h5>
-<p>16.05.2007</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>When moving rules up or down or adding new rules, the view scrolls now to ensure visibility</li>
- <li>Added rules are inserted after the currently selected item instead of at the end of the list</li>
- </ul>
- </li>
- <li>New features:
- <ul>
- <li>If subsequent rules with the same fieldRule exist (Alternatives"), a prompt is displayed for selection</li>
- <li>A new option defines if the selected alternatives index is to be used for subsequent selections</li>
- <li>Extended help page to explain how the "Alternatives" work</li>
- </ul>
- <li>
-</ul>
-
-<h5 id="v0.5">Version 0.5</h5>
-<p>16.05.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added support for textareas</li>
- <li>A new option defines a placeholder to create line breaks in textareas</li>
- <li>Extended help page to explain how to use placeholders for line breaks</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.6">Version 0.6</h5>
-<p>19.05.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added Import/Export feature for profiles</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.6.1">Version 0.6.1</h5>
-<p>06.06.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Improved default ruleset</li>
- <li>Dialog windows independent from parent window</li>
- <li>Highlight style using CSS declarations via about:config for matched and not matched form fields</li>
- <li>Added support for password fields - for password management please rather use the Secure Login extension</li>
- <li>Added french locale - Thanks to myahoo at babelzilla.org</li>
- <li>Added dutch locale - Thanks to markh at babelzilla.org</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.6.1.1">Version 0.6.1.1</h5>
-<p>21.06.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added czech locale - Thanks to PetrTwo at babelzilla.org</li>
- </ul>
-</li>
-</ul>
-
-<h5 id="v0.6.2">Version 0.6.2</h5>
-<p>05.07.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added support for file upload fields</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.6.2.1">Version 0.6.2.1</h5>
-<p>18.07.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added Chinese (Simplified) locale - Thanks to simophin at babelzilla.org</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.7">Version 0.7</h5>
-<p>31.07.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added possibility to deselect checkboxes/radio buttons by deactivating the "Overwrite" setting</li>
- <li>Added support for dynamic tags which can be used to insert dynamic data in form fields, e.g. the current date</li>
- <li>Added possibility to fill out forms on all open tabs via about:config setting "fillAllTabs"</li>
- <li>Added confirmation dialog before deleting a profile</li>
- <li>Removed "Apply" button for field rules - field rules are now updated as soon as the textboxes lose focus</li>
- <li>Updated documentation</li>
- <li>Added Hungarian locale - Thanks to Mikes Kaszmán István (Cashman) at babelzilla.org</li>
- <li>Added Italian locale - Thanks to Underpass, gonzalopirobutirro and Godai71 at babelzilla.org</li>
- <li>Added Polish locale - Thanks to teo at babelzilla.org</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.7.0.1">Version 0.7.0.1</h5>
-<p>09.08.2007</p>
-<ul>
- <li>User Interface improvements:
- <ul>
- <li>FieldRule list now takes up the free space when resizing the settings window</li>
- <li>Rule editor list now takes up the free space when resizing the rule editor window</li>
- <li>Rule editor textboxes now take up the free space when resizing the rule editor window</li>
- <li>Tag editor list now takes up the free space when resizing the tag editor window</li>
- <li>Tag editor tag code textboxes now take up the free space when resizing the tag editor window</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.7.0.2">Version 0.7.0.2</h5>
-<p>21.08.2007</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>If browser.preferences.animateFadeIn is set to true (which is the default on a Mac) the rule list had been hidden - fixed.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.7.0.3">Version 0.7.0.3</h5>
-<p>11.09.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added Chinese (Traditional) locale - Thanks to Lu Ming-Tse (呂明澤).</li>
- <li>Added Midbrowser (Firefox for Mobile Internet Devices) GUID to target applications (BETA) - see http://www.moblin.org.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8">Version 0.8</h5>
-<p>26.11.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Adding the possibility to define a Global Profile, which is applied on form fields that cannot be filled out using the current profile.</li>
- <li>Applying the siteRule on the whole url, not just on protocol and hostname.</li>
- <li>Adding a validate button and result textbox to the dynamic tag editor.</li>
- <li>Added confirmation dialogs to removal methods (can be disabled via about:config setting "enableConfirmationDialogs").</li>
- <li>New hidden feature "matchAgainstLabels".
- <br />Can be enabled via about:config by setting extensions.autofillForms at blueimp.net.matchAgainstLabels to true.
- <br />If enabled, matches the fieldRules against the textual content of label tags assigned to the current element if the element name does not match.</li>
- <li>Added a new help section: "Hidden settings".</li>
- <li>The focus is now set on the last form element match - this allows to submit autofilled forms by hitting the enter key.</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Pressing the delete key (keyCode 46) doesn't call the remove method anymore if a textbox is focused.</li>
- <li>The nsISecretDecoderRing methods encryptString/decryptString cannot handle characters above the Latin-1 (ISO-8859-1) charset.
- <br />The usage of encodeURI/decodeURI on the fieldRule properties bypasses this problem as a workaround.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.0.1">Version 0.8.0.1</h5>
-<p>27.11.2007</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>Selecting an item right after changing a textbox value does not fire any onchange/onblur events which resulted in the changes not being saved.
- <br />Applying the changes on the last selected item on a new selection as workaround.</li>
- <li>Changes applied if more than one item has been selected could result in the wrong item being updated.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.0.2">Version 0.8.0.2</h5>
-<p>29.11.2007</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>The settings page didn't allow to enable the global profile - the enableGlobalProfile preference tag was missing inside the XUL document.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.0.3">Version 0.8.0.3</h5>
-<p>30.11.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added (hidden) statusbar icon - can be made visible via about:config setting extensions.autofillForms at blueimp.net.hideStatusbarIcon.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.1">Version 0.8.1</h5>
-<p>17.12.2007</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added context menu item for form fields, allowing easier creation of Autofill Forms rules.</li>
- <li>Updated help section.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.1.1">Version 0.8.1.1</h5>
-<p>17.12.2007</p>
-<ul>
- <li>Changes:
- <ul>
- <li>Updated french locale - thanks to myahoo.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.1.2">Version 0.8.1.2</h5>
-<p>20.12.2007</p>
-<ul>
- <li>Changes:
- <ul>
- <li>Updated italian locale - thanks to gonzalopirobutirro and Godai71.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.8.2">Version 0.8.2</h5>
-<p>31.01.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Improved alternatives code and added alternatives support for selections and radio buttons.</li>
- <li>Added "about:config" option "useConfigDirectory" which allows to store the fieldRules, dynamicTags and dynamicTagCodes as files.
- <br />The files are stored in the directory "autofillForms at blueimp.net" beneath the Firefox profile directory by default.
- <br />This can be changed using the "about:config" option "configDirectory" - it is recommended to keep the default.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9">Version 0.9</h5>
-<p>16.02.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added a more intuitive and much simpler interface to edit the field rules in addition to the main editing pane.</li>
- <li>Made several hidden features accessible on the settings page.</li>
- <li>Added button to reset all profiles to the simple interface pane.</li>
- <li>Made sure profiles always get a unique name (label change, import or adding of profiles).</li>
- <li>Slightly improved the default profile rules.</li>
- <li>Added a toolbar button without menu (but with context menu).</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Unsetting the fieldRules object after each fillForms call instead of keeping them in memory.</li>
- <li>Storing the profile labels as file if useConfigDirectory is enabled.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.1">Version 0.9.1</h5>
-<p>23.03.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added the possibility to restrict profiles to certain websites by setting a profile site rule.</li>
- <li>Added an option to automatically select the best matching profile dependent on the form url and the profile site rules.</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Editing a rule with the rule editor did not apply the changes automatically on confirmation.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.1.1">Version 0.9.1.1</h5>
-<p>25.03.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added a selection of the available profiles to the Autofill Forms menu popup.</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Fixed a bug preventing the proper selection of the best matching profile.</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>The option autoSelectBestProfile is now enabled by default.</li>
- <li>The current profile is now declared best match for equal match lengths instead of the first matching profile in the list.</li>
- <li>Resetting the profile to the manually selected one after using the best matching profile.
- <br />This can be disabled by setting the "about:config" option "resetProfileAfterAutoSelect" to false.</li>
- </ul>
- </li>
-</ul>
-
-
-<h5 id="v0.9.2">Version 0.9.2</h5>
-<p>06.04.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added the possibility to add a complete web form as Autofill Forms profile (by using the context menu of a form field).</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Added a workaround for the missing integrated help system which has been removed for Firefox 3.0b5 and later.</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Adding new rules to the start of the list (or right after the selection) instead of to the end.</li>
- <li>Added the regular expression for valid form field types as "about:config" option.</li>
- <li>Hiding passwords in the simple interface and in the rules list behind asterisks (*).
- <br />Passwords are defined by the label/name of a rule which is compared to a regular expression (regExpPasswordLabel in "about:config").</li>
- </ul>
- </li>
-</ul>
-
-
-<h5 id="v0.9.2.1">Version 0.9.2.1</h5>
-<p>10.04.2008</p>
-<ul>
- <li>Changes:
- <ul>
- <li>Updated french locale - thanks to myahoo.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.2.2">Version 0.9.2.2</h5>
-<p>11.04.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added new example dynamic tag <clipboard> to insert the current clipboard text content.
- <br />The dynamic tag code to access the clipboard text is this.getClipboardText().</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Updated czech locale - thanks to PetrTwo.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.2.3">Version 0.9.2.3</h5>
-<p>24.04.2008</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>Fixed a bug which caused form element labels not assigned to any form element to always match.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.3">Version 0.9.3</h5>
-<p>08.05.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added the possibility to manually fill out form fields via their context menu.
- <br />This allows to insert data from the profiles while ignoring the form field rules.</li>
- <li>Added support for element ids as fallback if a form element has no name or label assigned.</li>
- <li>Added support to match form fields by position.
- <br />This new feature is currently a hiddden option and has to be enabled via about:config (matchAgainstPositions).
- <br />Position rules are identified by the character "#" adjustable via about:config (positionsIdentifier).
- <br />A rule matching always the second form element would be "#2".
- <br />Another rule matching the third element on the second form would be "2#3".
- <br />You can also combine matching form field names with matching form field positions:
- <br />A rule matching the second form field or fields with the name "test" would be "(test)|(#2)".</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.4">Version 0.9.4</h5>
-<p>28.05.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Automatically installing the toolbar button.</li>
- <li>Added option to hide/display the toolbar button.</li>
- <li>Added option to hide/display the toolbar button menu.</li>
- <li>Middle mouse click on toolbar button or statusbar icon allows filling out forms by profile.</li>
- <li>New content area context menu item allows filling out forms by profile.</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Fixed a bug preventing shortcut key combinations with keycodes (e.g. VK_ENTER) to work on Firefox 3 RC1.</li>
- <li>Escaping special regexp characters in field names when adding them as new rules via the context menu.</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Removed the integrated help in favor of an online help.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.4.1">Version 0.9.4.1</h5>
-<p>03.06.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Making all icons completely customizable via user CSS (userChrome.css).</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Updating the help topics for the different settings dialogs.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.4.2">Version 0.9.4.2</h5>
-<p>03.06.2008</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>Fixing a bug related to the toolbar button style.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.5">Version 0.9.5</h5>
-<p>28.06.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added new settings tabs for profile management.</li>
- <li>Added the possibility to define keyboard shorcuts to autofill and submit forms, to autofill forms on all tabs and to fill forms from profile selection.</li>
- <li>Added the possibility to configure different actions for different mouse button clicks on toolbar button and statusbar icon.</li>
- <li>Adding access to all hidden preferences (except regExpFormFieldTypes and regExpPasswordLabel) to the settings dialog.</li>
- <li>Rule values are now matched as regular expressions against selection options, checkboxes and radio buttons.</li>
- <li>Improved performance by caching rules (and their regular expressions) within one form filling run.</li>
- <li>Added option to identify form field labels which are no strict HTML label elements - the default is to identify labels in strict mode.</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Adjusting the toolbar icons to the default theme on Firefox 3 for Mac.</li>
- <li>Added a fix to show only a selection between radio buttons if the alternative rules are placed next to each other or the rule is the same.</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Alternatives must be placed next to each other and match the field, but don't require the same field rule anymore.</li>
- <li>Replacing control characters with placeholders when adding a new rule or profile via the context menu of form fields.</li>
- <li>Replacing control characters with placeholders on text input for the rule values (Firefox >= 3).</li>
- <li>Adding a preference for the tabulator placeholder (by default four space characters).</li>
- <li>Adding version specific stylesheets instead of modifying the styles via JavaScript.</li>
- <li>Adding the global skin as CSS import rule instead of inside the XUL files.</li>
- <li>Suggesting the profile name as filename on profile export.</li>
- <li>Automatically applying new keyboard shortcuts on key input.</li>
- <li>Disabled rules are now moved to a submenu on the form fields context menu.</li>
- <li>Reorganized the settings tabs.</li>
- <li>Moved the "Display form details" command to the content area context menu.</li>
- <li>Replaced the former "Display form details" button with the "Reset all profiles button".</li>
- <li>Removed the unnecessary preference "resetProfileAfterAutoSelect".</li>
- <li>Allow to use Autofill Forms on other protocols than http(s)://; e.g. on file:// to test local HTML forms.</li>
- <li>Adding a default label for empty profile labels.</li>
- <li>Adding all options of selections of type multiple as rules when adding a form as profile.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.5.1">Version 0.9.5.1</h5>
-<p>13.07.2008</p>
-<ul>
- <li>New features:
- <ul>
- <li>Added the possibility to configure keyboard shortcut and mouse button for the "Display Form Details" feature.</li>
- <li>Added (incomplete) romanian locale - thanks to x10firefox at babelzilla.org.</li>
- </ul>
- </li>
- <li>Bugfixes:
- <ul>
- <li>Adjust the hideToolbarButton setting if the toolbar button has been removed/added by drag and drop.</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Code refactoring to improve performance and readability - thanks to Robert Stewart for the performance notions.</li>
- </ul>
- </li>
-</ul>
-
-<h5 id="v0.9.5.2">Version 0.9.5.2</h5>
-<p>30.08.2008</p>
-<ul>
- <li>Bugfixes:
- <ul>
- <li>Adjusting the "Add complete form as profile..." and "Add a rule for this field..." features to add the values of non-text fields as regular expressions.<br />
- Adding the special characters for the beginning and end of the string makes sure no unwanted alternatives prompts are shown.</li>
- </ul>
- </li>
- <li>Other changes:
- <ul>
- <li>Use gBrowser if it is available and the WindowMediator service only as fallback to access the browser object.</li>
- <li>Replaced multiple method calls to access the content document with local variables holding the document reference.</li>
- <li>Parsing child frames after parsing the parent window.</li>
- </ul>
- </li>
-</ul>
\ No newline at end of file
diff --git a/www/css/closelabel.gif b/www/css/closelabel.gif
deleted file mode 100644
index af0cab2..0000000
Binary files a/www/css/closelabel.gif and /dev/null differ
diff --git a/www/css/loading.gif b/www/css/loading.gif
deleted file mode 100644
index e552f29..0000000
Binary files a/www/css/loading.gif and /dev/null differ
diff --git a/www/css/nextlabel.gif b/www/css/nextlabel.gif
deleted file mode 100644
index 7c66121..0000000
Binary files a/www/css/nextlabel.gif and /dev/null differ
diff --git a/www/css/prevlabel.gif b/www/css/prevlabel.gif
deleted file mode 100644
index 0641876..0000000
Binary files a/www/css/prevlabel.gif and /dev/null differ
diff --git a/www/css/slimbox.css b/www/css/slimbox.css
deleted file mode 100644
index 905b528..0000000
--- a/www/css/slimbox.css
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SLIMBOX */
-
-#lbOverlay {
- position: absolute;
- z-index: 9999;
- left: 0;
- width: 100%;
- background-color: #000;
- cursor: pointer;
-}
-
-#lbCenter, #lbBottomContainer {
- position: absolute;
- z-index: 9999;
- left: 50%;
- overflow: hidden;
- background-color: #fff;
-}
-
-.lbLoading {
- background: #fff url(loading.gif) no-repeat center;
-}
-
-#lbImage {
- position: absolute;
- left: 0;
- top: 0;
- border: 10px solid #fff;
- background-repeat: no-repeat;
-}
-
-#lbPrevLink, #lbNextLink {
- display: block;
- position: absolute;
- top: 0;
- width: 50%;
- outline: none;
-}
-
-#lbPrevLink {
- left: 0;
-}
-
-#lbPrevLink:hover {
- background: transparent url(prevlabel.gif) no-repeat 0% 15%;
-}
-
-#lbNextLink {
- right: 0;
-}
-
-#lbNextLink:hover {
- background: transparent url(nextlabel.gif) no-repeat 100% 15%;
-}
-
-#lbBottom {
- font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
- font-size: 10px;
- color: #666;
- line-height: 1.4em;
- text-align: left;
- border: 10px solid #fff;
- border-top-style: none;
-}
-
-#lbCloseLink {
- display: block;
- float: right;
- width: 66px;
- height: 22px;
- background: transparent url(closelabel.gif) no-repeat center;
- margin: 5px 0;
- outline: none;
-}
-
-#lbCaption, #lbNumber {
- margin-right: 71px;
-}
-
-#lbCaption {
- font-weight: bold;
-}
diff --git a/www/donation.html b/www/donation.html
deleted file mode 100644
index 83bc4ba..0000000
--- a/www/donation.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<h4 class="page-header">Donation</h4>
-
-<h5>Thanks to the Donators:</h5>
-<table id="donators">
- <thead>
- <tr><th>Date</th><th>Name</th><th>Amount</th></tr>
- </thead>
- <tbody>
- <tr><td>2009/02/21</td><td>James Ricks</td><td class="amount">3.00 €</td></tr>
- <tr><td>2009/08/07</td><td>Jay Kridner</td><td class="amount">5.55 €</td></tr>
- <tr><td>2008/12/28</td><td>Noelle Gillies</td><td class="amount">10.00 €</td></tr>
- <tr><td>2008/10/24</td><td>Günter Müller</td><td class="amount">10.00 €</td></tr>
- <tr><td>2008/07/10</td><td>mikeWorks</td><td class="amount">5.00 €</td></tr>
- <tr><td>2008/07/10</td><td>Dragomir Iulian</td><td class="amount">25.00 €</td></tr>
- <tr><td>2007/11/30</td><td>Marcus Schommler</td><td class="amount">5.00 €</td></tr>
- <tr><td>2007/10/20</td><td>Steve Buss</td><td class="amount">5.00 €</td></tr>
- </tbody>
-</table>
\ No newline at end of file
diff --git a/www/download.html b/www/download.html
deleted file mode 100644
index 2753b56..0000000
--- a/www/download.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<h4 class="page-header">Download and Installation</h4>
-<h5>addons.mozilla.org</h5>
-<p>It is recommended to download and install Autofill Forms from the official Mozilla Firefox Add-ons website:<br />
-<ul>
-<li><a href="https://addons.mozilla.org/firefox/addon/4775">Autofill Forms on addons.mozilla.org</a></li>
-</ul></p>
-<h5>downloads.mozdev.org</h5>
-<p>As an alternative, you may also download Autofill Forms from mozdev.org:
-<ul>
-<li><a href="http://downloads.mozdev.org/autofillforms/">Autofill Forms on downloads.mozdev.org</a></li>
-</ul></p>
\ No newline at end of file
diff --git a/www/error/404.html b/www/error/404.html
deleted file mode 100644
index cf87357..0000000
--- a/www/error/404.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-// $Id: 404.html,v 1.1 2008/05/16 16:12:04 petejc Exp $
-
-// r 1.11 look/www/org/helm/common/template/404.tem
-
-//<font color="#990000" face="helvetica"><B>Page Not Found</B></font>
-//<img src="http://www.mozdev.org/sharedimages/boxes.gif"><br><br>
-
-// clashs with project_nav.html
-
-?><!-- testing for admin section -->
-
-<p>The page <font color="#990000"><b><?php PRINT PAGE; ?></b></font> was not found on this site.
-
-<p>To find the desired link, try checking the <?php print $project; ?> project's
-<?php print "<a href=\"http://$project.mozdev.org/index.html\">"; ?>main page</a>.
-
-<p>If that doesn't have the link you were looking for, you could also check out the following links:
-
-<ul>
-<li><a href="http://www.mozdev.org/projects.html">List of announced projects</a>
-<li><a href="http://www.mozdev.org/categories/unannounced.html">List of unannounced projects</a>
-<li><a href="http://www.mozdev.org/faq.html">Frequently Asked Questions page</a>
-<li>Search query page (coming soon)
-</ul>
-
-<p>If those don't help, you could also try sending mail to a project's mailing list, to one of the project owners, or to the general
-site feedback address:
-
-<ul>
-<li><a href="http://www.mozdev.org/mailing-lists.html">Mailing Lists</a>
-<li><a href="http://www.mozdev.org/contact.html">Project Owners</a>
-<li><a href="http://www.mozdev.org/feedback.html">Feedback</a>
-</ul>
diff --git a/www/favicon.ico b/www/favicon.ico
deleted file mode 100644
index ea61fc5..0000000
Binary files a/www/favicon.ico and /dev/null differ
diff --git a/www/footer.html b/www/footer.html
deleted file mode 100644
index afbf211..0000000
--- a/www/footer.html
+++ /dev/null
@@ -1,19 +0,0 @@
- </div>
-
- <p id="mozdev-feedback">
- For questions or comments about Autofill Forms, please use the provided
- <a href="http://autofillforms.mozdev.org/support.html">support options</a>.
- <br />
- <br />
- <a href="http://www.mozdev.org" title="mozdev.org - free project hosting for the mozilla community">
- <img src="http://www.mozdev.org/sharedimages/mozdev_tiny.png" width="80" height="15" alt="mozdev.org" border="0">
- </a>
- <a href="https://blueimp.net/" title="blueimp.net - Free software and open source web applications">
- <img src="https://blueimp.net/img/logo-tiny.png" width="80" height="15" alt="blueimp.net" border="0">
- </a>
- <br />
- <a href="http://www.mozdev.org/copyright.html">Copyright</a> © 2004. All rights reserved.
- <a href="http://www.mozdev.org/community/terms.html">Terms of Use</a>.
- </p>
-</body>
-</html>
diff --git a/www/graphics/Firefox-3-Mac-Toolbar-Button-Template.png b/www/graphics/Firefox-3-Mac-Toolbar-Button-Template.png
deleted file mode 100644
index c4fd86a..0000000
Binary files a/www/graphics/Firefox-3-Mac-Toolbar-Button-Template.png and /dev/null differ
diff --git a/www/graphics/logo.png b/www/graphics/logo.png
deleted file mode 100644
index 7597028..0000000
Binary files a/www/graphics/logo.png and /dev/null differ
diff --git a/www/graphics/paypal-donate.gif b/www/graphics/paypal-donate.gif
deleted file mode 100644
index b5cda14..0000000
Binary files a/www/graphics/paypal-donate.gif and /dev/null differ
diff --git a/www/graphics/pencil.png b/www/graphics/pencil.png
deleted file mode 100644
index d0ec488..0000000
Binary files a/www/graphics/pencil.png and /dev/null differ
diff --git a/www/graphics/pencil.svg b/www/graphics/pencil.svg
deleted file mode 100644
index 6ab4ac0..0000000
--- a/www/graphics/pencil.svg
+++ /dev/null
@@ -1,610 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="309.8573"
- height="309.86777"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docbase="/home/madblueimp"
- sodipodi:docname="pencil.svg"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- inkscape:export-xdpi="9.2946014"
- inkscape:export-ydpi="9.2946014"
- version="1.0"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <defs
- id="defs4">
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 194.43752 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="388.742 : 194.43752 : 1"
- inkscape:persp3d-origin="194.371 : 129.62501 : 1"
- id="perspective80" />
- <linearGradient
- id="linearGradient3401">
- <stop
- id="stop3403"
- offset="0"
- style="stop-color:#ff9191;stop-opacity:1;" />
- <stop
- id="stop3405"
- offset="1"
- style="stop-color:#ff9191;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient3316">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop3318" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop3320" />
- </linearGradient>
- <linearGradient
- id="linearGradient3706">
- <stop
- style="stop-color:#ffffff;stop-opacity:0.82653064;"
- offset="0"
- id="stop3708" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop3710" />
- </linearGradient>
- <linearGradient
- id="linearGradient4497">
- <stop
- style="stop-color:#ffae2c;stop-opacity:1;"
- offset="0"
- id="stop4499" />
- <stop
- style="stop-color:#ff9e00;stop-opacity:1;"
- offset="1"
- id="stop4501" />
- </linearGradient>
- <linearGradient
- id="linearGradient4254">
- <stop
- style="stop-color:#ff9191;stop-opacity:1;"
- offset="0"
- id="stop4256" />
- <stop
- style="stop-color:#b55858;stop-opacity:1;"
- offset="1"
- id="stop4258" />
- </linearGradient>
- <linearGradient
- id="linearGradient3800">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop3802" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop3804" />
- </linearGradient>
- <linearGradient
- id="linearGradient3707">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop3687" />
- <stop
- style="stop-color:#ffdd7c;stop-opacity:1;"
- offset="1"
- id="stop3711" />
- </linearGradient>
- <linearGradient
- id="linearGradient3692">
- <stop
- style="stop-color:#ff9e00;stop-opacity:1;"
- offset="0"
- id="stop3694" />
- <stop
- id="stop3705"
- offset="0.5"
- style="stop-color:#ffffff;stop-opacity:1;" />
- <stop
- style="stop-color:#ff9e00;stop-opacity:1;"
- offset="1"
- id="stop3696" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3800"
- id="linearGradient3806"
- x1="167.15625"
- y1="298.17941"
- x2="167.15625"
- y2="311.57703"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4260"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4396"
- gradientUnits="userSpaceOnUse"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668"
- gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4399"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(0,-1.7382813e-5)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4465"
- gradientUnits="userSpaceOnUse"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4481"
- gradientUnits="userSpaceOnUse"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668"
- gradientTransform="matrix(0.6504406,0,0,0.6504406,239.12347,164.45229)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient4495"
- x1="335.91367"
- y1="425.20453"
- x2="359.76996"
- y2="425.20453"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4497"
- id="linearGradient4503"
- x1="335.91718"
- y1="414.39426"
- x2="359.75989"
- y2="414.39426"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4569"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.6504406,0,0,0.6504406,239.12347,164.45229)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4590"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.6504406,0,0,0.6504406,239.12347,164.45229)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient4592"
- gradientUnits="userSpaceOnUse"
- x1="335.91367"
- y1="425.20453"
- x2="359.76996"
- y2="425.20453" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4497"
- id="linearGradient4594"
- gradientUnits="userSpaceOnUse"
- x1="335.91718"
- y1="414.39426"
- x2="359.75989"
- y2="414.39426" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient2322"
- gradientUnits="userSpaceOnUse"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-872.34737,-1020.0829)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient2332"
- gradientUnits="userSpaceOnUse"
- x1="331.71732"
- y1="437.79453"
- x2="365.74753"
- y2="437.79453"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-872.34737,-1020.0829)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient2339"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.3154492,-1.4454678e-3,-1.4454678e-3,3.3154492,-180.47767,-785.1168)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3316"
- id="linearGradient3322"
- x1="349.15182"
- y1="707.90222"
- x2="373.04395"
- y2="707.90222"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient3326"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-872.34737,-1100.0829)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient3386"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,1.5578977e-3,-1.5578977e-3,-3.5733281,-872.34737,2152.4451)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient3393"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-872.34737,-1100.0829)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient3430"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.3154492,-1.4454678e-3,-1.4454678e-3,3.3154492,-180.47767,-785.1168)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient3432"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-872.34737,-1020.0829)"
- x1="331.71732"
- y1="437.79453"
- x2="365.74753"
- y2="437.79453" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient3434"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-872.34737,-1020.0829)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3316"
- id="linearGradient3436"
- gradientUnits="userSpaceOnUse"
- x1="349.15182"
- y1="707.90222"
- x2="373.04395"
- y2="707.90222" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3316"
- id="linearGradient4267"
- gradientUnits="userSpaceOnUse"
- x1="349.15182"
- y1="707.90222"
- x2="373.04395"
- y2="707.90222"
- gradientTransform="translate(15.365248,6.2927944)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient4270"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-856.98212,-1013.7901)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient4279"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-856.98212,-1013.7901)"
- x1="331.71732"
- y1="437.79453"
- x2="365.74753"
- y2="437.79453" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4286"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.3154492,-1.4454678e-3,-1.4454678e-3,3.3154492,-165.11242,-778.82401)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4306"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.3154492,-1.4454678e-3,-1.4454678e-3,3.3154492,-165.11242,-778.82401)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient4308"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-856.98212,-1013.7901)"
- x1="331.71732"
- y1="437.79453"
- x2="365.74753"
- y2="437.79453" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient4310"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-856.98212,-1013.7901)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient4314"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-856.98212,-1013.7901)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient4323"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.5733281,-1.5578977e-3,-1.5578977e-3,3.5733281,-856.98212,-1013.7901)"
- x1="331.71732"
- y1="437.79453"
- x2="365.74753"
- y2="437.79453" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient4330"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.3154492,-1.4454678e-3,-1.4454678e-3,3.3154492,-165.11242,-778.82401)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3706"
- id="linearGradient7803"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.527826,2.525623,-2.527826,2.525623,1119.475,-1457.151)"
- x1="335.71875"
- y1="414.35938"
- x2="353.75"
- y2="414.35938" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3707"
- id="linearGradient7812"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.5278262,2.525623,-2.5278262,2.525623,565.91117,-1456.1414)"
- x1="331.71732"
- y1="437.79453"
- x2="365.74753"
- y2="437.79453" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4254"
- id="linearGradient7819"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.345399,2.343355,-2.345399,2.343355,808.1061,-719.7623)"
- x1="148.70325"
- y1="318.68668"
- x2="185.48425"
- y2="318.68668" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1"
- inkscape:cx="260.28083"
- inkscape:cy="165.25621"
- inkscape:document-units="px"
- inkscape:current-layer="g7826"
- inkscape:window-width="1272"
- inkscape:window-height="924"
- inkscape:window-x="4"
- inkscape:window-y="71"
- showguides="true"
- inkscape:guide-bbox="true"
- showgrid="false" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:source>https://blueimp.net</dc:source>
- <dc:creator>
- <cc:Agent>
- <dc:title>Sebastian Tschan</dc:title>
- </cc:Agent>
- </dc:creator>
- <cc:license
- rdf:resource="GNU Free Documentation license - http://www.gnu.org/licenses/fdl.html" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- style="display:inline"
- transform="translate(-208.33745,-352.78704)" />
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="layer2"
- style="display:inline"
- transform="translate(-208.33745,-352.78704)">
- <g
- id="g7826">
- <g
- id="g2273"
- style="opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- inkscape:export-xdpi="4.0700002"
- inkscape:export-ydpi="4.0700002">
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:url(#linearGradient7812);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 429.20661,356.02971 L 244.3069,540.76828 L 209.33745,661.6548 L 220.30359,658.48966 L 330.3294,626.71581 L 515.22912,441.97725 L 498.53641,425.29909 L 492.68789,419.45566 L 477.09173,403.87309 L 475.14215,401.9252 L 469.29362,396.08178 L 467.34405,394.13391 L 451.74805,378.5515 L 445.89934,372.7079 L 437.00475,363.82106 L 429.20661,356.02971 z"
- id="path4106" />
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:#ffc700;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 429.20661,356.02971 L 244.3069,540.76828 L 286.03514,542.05018 L 287.31817,583.74205 L 329.04638,585.02394 L 330.3294,626.71581 L 515.22912,441.97725 L 493.72349,420.49036 L 472.21788,399.00349 L 450.71225,377.5166 L 429.20661,356.02971 z"
- id="path3424"
- sodipodi:nodetypes="ccccccccccc" />
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:#ffda00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 429.20661,356.02971 L 244.3069,540.76828 L 286.03514,542.05018 L 450.71225,377.5166 L 429.20661,356.02971 z"
- id="path3426"
- sodipodi:nodetypes="ccccc" />
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:#ff8a00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 329.04638,585.02394 L 330.3294,626.71581 L 515.22912,441.97725 L 493.72349,420.49036 L 329.04638,585.02394 z"
- id="path3428"
- sodipodi:nodetypes="ccccc" />
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:#ffa100;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 287.31817,583.74205 L 329.04638,585.02394 L 493.72349,420.49036 L 472.21788,399.00349 L 287.31817,583.74205 z"
- id="path3430"
- sodipodi:nodetypes="ccccc" />
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:url(#linearGradient7819);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
- d="M 486.49403,384.44598 C 462.75184,360.72447 436.83161,348.11762 428.67868,356.26343 C 428.12537,356.81626 427.64194,357.4406 427.27733,358.15035 L 375.61513,409.76751 L 383.41327,417.55886 L 413.75257,447.87172 L 423.50025,457.6109 L 461.63764,495.71505 L 515.00577,442.39344 C 514.97622,442.29755 514.97518,442.18579 514.94495,442.0892 L 514.884,442.02831 C 514.90223,442.00869 514.92667,441.98735 514.9448,441.96757 C 522.62989,433.5672 510.01079,407.94222 486.49403,384.44598 z"
- id="path4217" />
- <path
- inkscape:export-ydpi="6.4299998"
- inkscape:export-xdpi="6.4299998"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
- d="M 467.48484,490.16915 L 381.46234,404.22161 L 377.56322,408.11734 L 375.61363,410.06522 L 461.63614,496.01276 L 463.58572,494.06487 L 467.48484,490.16915 z"
- id="path4147" />
- </g>
- <path
- sodipodi:nodetypes="ccccc"
- id="path3990"
- d="M 256.88237,647.92525 L 239.98074,631.03834 L 223.0791,614.15144 L 209.33745,661.6548 L 256.88237,647.92525 z"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.16400003;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- inkscape:export-xdpi="4.0700002"
- inkscape:export-ydpi="4.0700002" />
- <path
- sodipodi:nodetypes="cccc"
- id="path4288"
- d="M 239.98074,631.03834 L 228.73595,619.80829 L 209.33745,661.6548 L 239.98074,631.03834 z"
- style="opacity:0.8;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.16400003;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="/home/madblueimp/pencil.png"
- inkscape:export-xdpi="4.0700002"
- inkscape:export-ydpi="4.0700002" />
- </g>
- </g>
-</svg>
diff --git a/www/graphics/screenshots/autofill-forms-01.png b/www/graphics/screenshots/autofill-forms-01.png
deleted file mode 100644
index 1b1b890..0000000
Binary files a/www/graphics/screenshots/autofill-forms-01.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-02.png b/www/graphics/screenshots/autofill-forms-02.png
deleted file mode 100644
index a089544..0000000
Binary files a/www/graphics/screenshots/autofill-forms-02.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-03.png b/www/graphics/screenshots/autofill-forms-03.png
deleted file mode 100644
index bf96b63..0000000
Binary files a/www/graphics/screenshots/autofill-forms-03.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-04.png b/www/graphics/screenshots/autofill-forms-04.png
deleted file mode 100644
index f8860f1..0000000
Binary files a/www/graphics/screenshots/autofill-forms-04.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-05.png b/www/graphics/screenshots/autofill-forms-05.png
deleted file mode 100644
index 5a81981..0000000
Binary files a/www/graphics/screenshots/autofill-forms-05.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-06.png b/www/graphics/screenshots/autofill-forms-06.png
deleted file mode 100644
index 47da17c..0000000
Binary files a/www/graphics/screenshots/autofill-forms-06.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-07.png b/www/graphics/screenshots/autofill-forms-07.png
deleted file mode 100644
index 7ea856b..0000000
Binary files a/www/graphics/screenshots/autofill-forms-07.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-08.png b/www/graphics/screenshots/autofill-forms-08.png
deleted file mode 100644
index 07cc119..0000000
Binary files a/www/graphics/screenshots/autofill-forms-08.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-09.png b/www/graphics/screenshots/autofill-forms-09.png
deleted file mode 100644
index a9487a1..0000000
Binary files a/www/graphics/screenshots/autofill-forms-09.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-10.png b/www/graphics/screenshots/autofill-forms-10.png
deleted file mode 100644
index 60e3a0c..0000000
Binary files a/www/graphics/screenshots/autofill-forms-10.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-11.png b/www/graphics/screenshots/autofill-forms-11.png
deleted file mode 100644
index 415e92c..0000000
Binary files a/www/graphics/screenshots/autofill-forms-11.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-12.png b/www/graphics/screenshots/autofill-forms-12.png
deleted file mode 100644
index 38c1d06..0000000
Binary files a/www/graphics/screenshots/autofill-forms-12.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-13.png b/www/graphics/screenshots/autofill-forms-13.png
deleted file mode 100644
index c2c697d..0000000
Binary files a/www/graphics/screenshots/autofill-forms-13.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-14.png b/www/graphics/screenshots/autofill-forms-14.png
deleted file mode 100644
index 087a29e..0000000
Binary files a/www/graphics/screenshots/autofill-forms-14.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-15.png b/www/graphics/screenshots/autofill-forms-15.png
deleted file mode 100644
index 921e68d..0000000
Binary files a/www/graphics/screenshots/autofill-forms-15.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-16.png b/www/graphics/screenshots/autofill-forms-16.png
deleted file mode 100644
index cc0ec71..0000000
Binary files a/www/graphics/screenshots/autofill-forms-16.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-17.png b/www/graphics/screenshots/autofill-forms-17.png
deleted file mode 100644
index 426e975..0000000
Binary files a/www/graphics/screenshots/autofill-forms-17.png and /dev/null differ
diff --git a/www/graphics/screenshots/autofill-forms-18.png b/www/graphics/screenshots/autofill-forms-18.png
deleted file mode 100644
index 1930a50..0000000
Binary files a/www/graphics/screenshots/autofill-forms-18.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-01.png b/www/graphics/screenshots/preview/autofill-forms-01.png
deleted file mode 100644
index f1573ed..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-01.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-02.png b/www/graphics/screenshots/preview/autofill-forms-02.png
deleted file mode 100644
index e579dd7..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-02.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-03.png b/www/graphics/screenshots/preview/autofill-forms-03.png
deleted file mode 100644
index 2604567..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-03.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-04.png b/www/graphics/screenshots/preview/autofill-forms-04.png
deleted file mode 100644
index f503f9a..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-04.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-05.png b/www/graphics/screenshots/preview/autofill-forms-05.png
deleted file mode 100644
index b2c8877..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-05.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-06.png b/www/graphics/screenshots/preview/autofill-forms-06.png
deleted file mode 100644
index 4d5eeb6..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-06.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-07.png b/www/graphics/screenshots/preview/autofill-forms-07.png
deleted file mode 100644
index 448ad7d..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-07.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-08.png b/www/graphics/screenshots/preview/autofill-forms-08.png
deleted file mode 100644
index 22c3f8e..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-08.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-09.png b/www/graphics/screenshots/preview/autofill-forms-09.png
deleted file mode 100644
index 2c2be86..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-09.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-10.png b/www/graphics/screenshots/preview/autofill-forms-10.png
deleted file mode 100644
index 5ad22c7..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-10.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-11.png b/www/graphics/screenshots/preview/autofill-forms-11.png
deleted file mode 100644
index 75efe68..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-11.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-12.png b/www/graphics/screenshots/preview/autofill-forms-12.png
deleted file mode 100644
index 684eedf..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-12.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-13.png b/www/graphics/screenshots/preview/autofill-forms-13.png
deleted file mode 100644
index c1b9363..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-13.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-14.png b/www/graphics/screenshots/preview/autofill-forms-14.png
deleted file mode 100644
index ea4e8e6..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-14.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-15.png b/www/graphics/screenshots/preview/autofill-forms-15.png
deleted file mode 100644
index c95a776..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-15.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-16.png b/www/graphics/screenshots/preview/autofill-forms-16.png
deleted file mode 100644
index ff6f7b1..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-16.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-17.png b/www/graphics/screenshots/preview/autofill-forms-17.png
deleted file mode 100644
index e1a81e0..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-17.png and /dev/null differ
diff --git a/www/graphics/screenshots/preview/autofill-forms-18.png b/www/graphics/screenshots/preview/autofill-forms-18.png
deleted file mode 100644
index 08e990f..0000000
Binary files a/www/graphics/screenshots/preview/autofill-forms-18.png and /dev/null differ
diff --git a/www/head.txt b/www/head.txt
deleted file mode 100644
index 36ff85e..0000000
--- a/www/head.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-<link rel="stylesheet" href="/project.css" type="text/css" />
-<link rel="stylesheet" href="/css/slimbox.css" type="text/css" media="screen" />
-<link rel="shortcut icon" href="/favicon.ico" />
-<title>Autofill Forms - Mozilla Firefox Add-on</title>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<meta http-equiv="Content-Style-Type" content="text/css"/>
-<meta http-equiv="Content-Script-Type" content="text/javascript">
-<meta name="robots" content="index,follow" />
-<meta name="keywords" content="autofill, forms, mozilla, firefox, add-on" />
-<meta name="description" content="Autofill Forms - Mozilla Firefox Add-on to fill out web forms automatically." />
-<meta name="author" content="Sebastian Tschan" />
diff --git a/www/hide_from_ns4.css b/www/hide_from_ns4.css
deleted file mode 100644
index eb9a01a..0000000
--- a/www/hide_from_ns4.css
+++ /dev/null
@@ -1,15 +0,0 @@
-#project-navigation a {
- border-left: 1px solid black;
- padding-left: 6px;
- padding-right: 5px;
-}
-
-#project-navigation a.first-item {
- border-left: none;
-}
-
-#project-navigation th {
- margin-right: 3px;
-}
-
-
diff --git a/www/html_body.html b/www/html_body.html
deleted file mode 100644
index fe169e1..0000000
--- a/www/html_body.html
+++ /dev/null
@@ -1,84 +0,0 @@
- </head>
- <body>
-
- <!-- ################### BEGIN TOP ################## -->
- <h1 id="mozdev-logo"><a href="https://blueimp.net/mozilla/">Autofill Forms</a></h1>
- <div id="mozdev-date">
- <!--$mind-it-ignore$-->
-
- <ul id="community-links">
- <li class="mozdev-date"><?php print DATE;?></li>
- <li class="mozdev-fries">Fill out web forms automatically</li>
- </ul>
- <!--$/mind-it-ignore$-->
- </div>
-
-<!-- ########################## BEGIN LEFT NAV ########################### -->
- <div id="mozdev-navigation">
-
- <!-- skip navigation -->
- <p class="invisible"><a class="nav-link" href="#content" title="Skip Navigation Entirely">Skip to Content</a></p>
-
- <!--form action="https://www.paypal.com/cgi-bin/webscr" method="post">
- <div id="mozdev-donate">
- <a href="https://www.paypal.com/cgi-bin/webscr&cmd=_s-xclick&hosted_button_id=">
- <img src="./graphics/paypal-donate.gif" alt="Donate">
- </a>
- </div>
- </form-->
-
- <div id="mozdev-searchbox">
- <h4 id="search" title="Search">Search</h4>
- <!-- skip navigation -->
- <p class="invisible"><a accesskey="C" class="nav-link" href="#content" title="Skip to Content">Skip to Content</a></p>
- <!-- Google search form -->
- <form action="http://www.google.com/custom" method="get">
- <div>
- <label accesskey="S" class="invisible" for="inputField">Search For</label>
-
- <input class="mozdev-textbox" id="inputField" maxlength="255" name="q" size="15" type="text" value=""><button class="mozdev-searchbutton" type="submit" title="Google Search">Go</button>
- <input type="hidden" name="sitesearch" value="autofillforms.mozdev.org"/>
- <input type="hidden" name="cof" value="S:http://autofillforms.mozdev.org;L:http://www.mozdev.org/sharedimages/header.gif;LW:458;LH:69;AH:left;"/>
- </div>
- </form>
- <!-- /Google search form -->
- </div>
-
- <div id="mozdev-style"></div>
-
- <div class="menu" id="mozdev-projects">
- <h4 id="projects" title="Projects">Projects</h4>
- <ul id="prj-ul">
- <li><a href="http://securelogin.mozdev.org/">Secure Login</a></li>
- <li><a href="http://netnotes.mozdev.org/">Net Notes</a></li>
- </ul>
- </div>
-
- <div class="menu" id="mozdev-resources">
- <h4 id="nav-resources" title="Resources">Resources</h4>
-
- <ul id="res-ul">
- <li><a href="http://www.mozdev.org" title="mozdev.org - free project hosting for the mozilla community">Project Hosting</a></li>
- <li><a href="https://blueimp.net" title="blueimp.net - Free software and open source web applications">Development</a></li>
- </ul>
- </div>
-
- <div class="menu" id="mozdev-community">
- <h4 id="community" title="Community">Community</h4>
- <ul id="com-ul">
- <li><a href="http://forums.mozillazine.org/viewtopic.php?t=537839">Forum topic [en]</a></li>
- <li><a href="http://www.firefox-browser.de/forum/viewtopic.php?t=48988">Forum topic [de]</a></li>
- <li><a href="http://www.babelzilla.org/forum/index.php?showtopic=3068">Translations</a></li>
- <li><a href="https://addons.mozilla.org/firefox/addon/4775#reviews">Reviews</a></li>
- <li><a href="./donation.html">Donators</a></li>
- </ul>
- </div>
-
-
- </div>
-
- <div id="mozdev-fluff"><b></b></div>
-
- <div id="mozdev-fluff2"><i></i></div>
-
-<!-- ########################## END LEFT NAV ############################# -->
diff --git a/www/index.html b/www/index.html
deleted file mode 100644
index 12022d9..0000000
--- a/www/index.html
+++ /dev/null
@@ -1,60 +0,0 @@
-
-<!-- MAIN CONTENT -->
-<h4 class="page-header">Autofill Forms - Mozilla Firefox add-on</h4>
-<a style="float:right; margin-left:20px;" href="/screenshots.html">
- <img src="./graphics/screenshots/preview/autofill-forms-01.png" alt="screenshot-01"/>
-</a>
-<p>Autofill Forms enables you to fill out web forms with one click or a keyboard shortcut.</p>
-<h3>Features:</h3>
-<ul>
- <li>Easy installation through Mozilla Firefox add-ons system.</li>
- <li>Easy configuration with a simple interface.</li>
- <li>Fills out web forms with one click or a keyboard shortcut.</li>
- <li>Input fields not automatically matched can be filled out via the context menu.</li>
- <li>Features a completely customizable ruleset to determine the input for each form element.</li>
- <li>Provides a simple rule editor to define custom rules.</li>
- <li>Advanced users can customize the ruleset using JavaScript Regular Expressions.</li>
- <li>Allows to match form fields by name, label (in strict mode or by proximity) or by position.</li>
- <li>Works with input fields, textareas, selections, checkboxes, radio buttons and any valid form fields.</li>
- <li>Allows to use multiline input with line break tags.</li>
- <li>Allows dynamically created input data using special <em>Dynamic Tags</em>.</li>
- <li>Profiles can be used to switch betweeen several sets of rules.</li>
- <li>Possibility to define site specific profiles and rules.</li>
- <li>Automatically selects the best matching profile based on the assigned site.</li>
- <li>Possibility to define a global profile.</li>
- <li>Profiles can be exported and imported.</li>
- <li>Profiles can be stored in Firefox preferences system or in a custom config directory.</li>
- <li>Provides the possibility to define alternatives inside a profile.</li>
- <li>Allows to add new rules or complete forms as profiles via the context menu of form fields.</li>
- <li>Can be used with a toolbar button, a statusbar icon, a keyboard shortcut or via the context menu.</li>
- <li>Completely customizable interface (buttons, icons and menus can be enabled/disabled).</li>
- <li>Autofilled and not autofilled form fields can be highlighted using <acronym title="Cascading Style Sheets">CSS</acronym> declarations.</li>
- <li>Provides customizable keyboard shortcuts</li>
- <li>Makes use of additional mouse buttons to perform differenct actions on click of the toolbar button.</li>
- <li>Can fill out and automatically submit forms.</li>
- <li>Can fill out forms on all open browser tabs.</li>
- <li>Can fill out forms from a profile selection.</li>
- <li>Only active when filling out forms so it doesn't consume any system resources while surfing.</li>
- <li>Provides secure encryption for the stored form data using Firefox Master Password.</li>
- <li>Integrates with the <a href="http://securelogin.mozdev.org/">Secure Login</a> add-on.</li>
-</ul>
-
-<h3>TODO:</h3>
-<ul>
- <li>Create an improved default profile.</li>
- <li>Add option to disable "Alternatives" (always use first match).</li>
- <li>Append highlight styles instead of replacing them.</li>
- <li>Add a dynamic tag to input the value of other fields.</li>
- <li>Highlight the field for which the Alternatives selection prompts.</li>
- <li>Add option to call the onchange event after filling out fields.</li>
- <li>Add option to fill out and submit forms on all tabs</li>
- <li>Add option to select which profiles are shown for context menu autofill.</li>
- <li>Add option to give the Global Profile a higher priority.</li>
- <li>Add option to "add a rule for this field" at a specific position in the current rules list.</li>
- <li>Add option to fill out forms on page load.</li>
- <li>Add option to highlight form fields on page load.</li>
- <li>Add option to append to a field value instead of overwrite.</li>
- <li>Add option to keep autoselected profile as the selected profile.</li>
- <li>Add option to use next best matching profile if AF invoked repeatedly on the same site.</li>
- <li>Add support for rich text fields.</li>
-</ul>
diff --git a/www/local.conf b/www/local.conf
deleted file mode 100644
index 1e66c11..0000000
--- a/www/local.conf
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-$local_conf_commits=ON;
-$local_conf_nav_off=ON;
-$local_conf_use_local_header=ON;
-$local_conf_use_local_footer=ON;
-$local_conf_ignore_holidays = ON;
-$local_conf_style_2004=ON;
-$local_conf_download_file_feed=OFF;
-
- echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' . "\n";
-
-?>
diff --git a/www/project.css b/www/project.css
deleted file mode 100644
index a67c79b..0000000
--- a/www/project.css
+++ /dev/null
@@ -1,38 +0,0 @@
- at import url("http://www.mozdev.org/project.css");
-
-h1#mozdev-logo a
-{
- background-image:url(./graphics/logo.png);
- width: 250px;
-}
-
-h1#mozdev-logo
-{
- background-position: 250px 0pt;
-}
-
-#main-content-no-nav {
- margin: 2em 1em 1em 176px;
- text-align: justify;
-}
-
-#mozdev-donate {
- margin:10px;
-}
-
-li li {
- margin-left:18px;
-}
-
-#donators td.amount {
- text-align:right;
-}
-
-#donators td {
- padding-top:5px;
- padding-right:5px;
-}
-
-#screenshots-gallery {
- text-align:left;
-}
diff --git a/www/project_nav.html b/www/project_nav.html
deleted file mode 100644
index 527ec2e..0000000
--- a/www/project_nav.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<h1 class="project-name" id="content">Autofill Forms</h1>
-
-<table id="project-navigation">
-
- <tbody id="resources" class="project-navigations">
- <tr>
- <th scope="row">resources:</th>
- <td class="navigation-list">
- <a class="first-item" href="/">Home</a>
- <a href="/screenshots.html">Screenshots</a>
- <a href="/download.html">Download</a>
- <a href="/changelog.html">Changelog</a>
- <a href="/source.html">Source Code</a>
- <a href="/bugs.html">Bugs</a>
- <a href="/support.html">Support</a>
- <a href="/members.html">Members</a>
- <a href="/drupal/wiki">Wiki</a>
- </td>
- </tr>
- </tbody>
-</table>
diff --git a/www/screenshots.html b/www/screenshots.html
deleted file mode 100644
index 963adda..0000000
--- a/www/screenshots.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!-- MAIN CONTENT -->
-<h5 class="page-header">Screenshots</h5>
-
-<script type="text/javascript" src="./js/mootools.js"></script>
-<script type="text/javascript" src="./js/slimbox.js"></script>
-
-<p id="screenshots-gallery">
- <a href="./graphics/screenshots/autofill-forms-01.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-01.png" alt="screenshot-01"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-02.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-02.png" alt="screenshot-02"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-03.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-03.png" alt="screenshot-03"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-04.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-04.png" alt="screenshot-04"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-05.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-05.png" alt="screenshot-05"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-06.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-06.png" alt="screenshot-06"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-07.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-07.png" alt="screenshot-07"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-08.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-08.png" alt="screenshot-08"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-09.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-09.png" alt="screenshot-09"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-10.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-10.png" alt="screenshot-10"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-11.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-11.png" alt="screenshot-11"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-12.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-12.png" alt="screenshot-12"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-13.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-13.png" alt="screenshot-13"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-14.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-14.png" alt="screenshot-14"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-15.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-15.png" alt="screenshot-15"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-16.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-16.png" alt="screenshot-16"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-17.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-17.png" alt="screenshot-17"/>
- </a>
- <a href="./graphics/screenshots/autofill-forms-18.png" rel="lightbox[screenshots]">
- <img src="./graphics/screenshots/preview/autofill-forms-18.png" alt="screenshot-18"/>
- </a>
-</p>
diff --git a/www/source.html b/www/source.html
deleted file mode 100644
index 4f475b3..0000000
--- a/www/source.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- MAIN CONTENT -->
-<h5 class="page-header">Source Code</h5>
-
-<p id="src-intro">
- The Autofill Forms source code can be accessed in either of the following ways:
-</p>
-
-<ul id="get-the-src">
-<li>Extract the source code from the <a href="download.html">installation file</a> (e.g. with <a href="http://www.7-zip.org/">7-zip</a>)</li>
-<li>View the source using the <abbr title="Concurrent Versions System">CVS</abbr> <a href="http://www.mozdev.org/source/browse/autofillforms/">web interface</a></li>
-<li>Check out the source using anonymous CVS with the following commands (password is guest):
-<pre>
-cvs -d :pserver:guest at mozdev.org:/cvs login
-cvs -z3 -d :pserver:guest at mozdev.org:/cvs co autofillforms/src autofillforms/www
-</pre>
-</li>
-</ul>
\ No newline at end of file
diff --git a/www/support.html b/www/support.html
deleted file mode 100644
index 15118a6..0000000
--- a/www/support.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<h4 class="page-header">Support</h4>
-<p>Before requesting support please have a look at the available <a href="/drupal/wiki">documentation</a>.</p>
-<p>You have several options to post questions or comments about Autofill Forms:
-<ul>
- <li>
- <strong>Web forum</strong><br />
- Post a message to the <a href="http://forums.mozillazine.org/viewtopic.php?p=2831644">Autofill Forms forum topic</a> on the MozillaZine forums</a>.
- </li>
- <li>
- <strong>Mailing list</strong><br />
- Post a message to the <a href="http://autofillforms.mozdev.org/list.html">Autofill Forms mailing list</a>.
- <form action="http://groups.google.com/group/autofill-forms/search" method="get">
- <div>
- <input name="q" size="30" type="text" value="">
- <button type="submit">Search list archives</button>
- </div>
- </form>
- You may also post to the mailing list via <a href="http://groups.google.com/group/autofill-forms/post">Gougle Groups</a>.
- </li>
- <li>
- <strong>Newsgroup</strong><br />
- Post a message to the <a href="news://news.mozdev.org/public.mozdev.autofillforms">Autofill Forms newsgroup</a>.<br />
- You need a <a href="http://en.wikipedia.org/wiki/List_of_news_clients">news client</a> to be able to read and post on Newsgroups.<br />
- In order to access newsgroups on mozdev, you will need to provide a global userrname and password:
- <ul>
- <li>Username: mozdev</li>
- <li>Password: maduser</li>
- </ul>
- This authentication applies to every public mozdev newsgroup and is an effort to help reduce spam.
- </li>
-</ul>
-</p>
-<p><strong>Notes:</strong>
-<ul>
- <li>All support requests are available to the public. <strong>Do not post any confidential information in your support messages.</strong></li>
- <li>The mailing list is linked to the newsgroup. Postings to the mailing list also appear on the newsgroup and vice versa.</li>
- <li>All mailing list posts are archived on <a href="http://groups.google.com/group/autofill-forms">Gougle Groups</a>.</li>
-</ul>
-</p>
diff --git a/www/test.html b/www/test.html
deleted file mode 100644
index e944283..0000000
--- a/www/test.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<h4 class="page-header">Autofill Forms Test Page</h4>
-<form action="" method="post">
-<p>
- <fieldset>
- <legend>Textfields</legend>
- <table>
- <tr>
- <td><label for="user_name">Username:</label></td>
- <td><input type="text" id="user_name" name="user_name"/></td>
- </tr>
- <tr>
- <td><label for="email">E-Mail:</label></td>
- <td><input type="text" id="email" name="email"/></td>
- </tr>
- <tr>
- <td><label for="full_name">Full Name:</label></td>
- <td><input type="text" id="full_name" name="full_name" value="Tom Bombadil"/></td>
- </tr>
- <tr>
- <td><label for="street_1">Street Line 1:</label></td>
- <td><input type="text" id="street_1" name="street_1"/></td>
- </tr>
- <tr>
- <td><label for="street_2">Street Line 2:</label></td>
- <td><input type="text" id="street_2" name="street_2"/></td>
- </tr>
- <tr>
- <td><label for="city">City:</label></td>
- <td><input type="text" id="city" name="city"/></td>
- </tr>
- <tr>
- <td><label for="state">State:</label></td>
- <td><input type="text" id="state" name="state"/></td>
- </tr>
- <tr>
- <td><label for="zip">ZIP/Postal Code:</label></td>
- <td><input type="text" id="zip" name="zip"/></td>
- </tr>
- <tr>
- <td><label for="phone">Phone Number:</label></td>
- <td><input type="text" id="phone" name="phone"/></td>
- </tr>
- <tr>
- <td><label for="homepage">Homepage:</label></td>
- <td><input type="text" id="homepage" name="homepage"/></td>
- </tr>
- </table>
- </fieldset>
-</p>
-<p>
- <fieldset>
- <legend>Selections, Checkboxes and Radio Buttons</legend>
- <p>
- <label for="selection_single">Hitchhiker books:</label><br />
- <select id="selection_single" name="selection_single">
- <option>The Hitchhiker's Guide to the Galaxy </option>
- <option>The Restaurant at the End of the Universe</option>
- <option>Life, the Universe and Everything</option>
- <option>So Long, and Thanks For All the Fish</option>
- <option>Mostly Harmless</option>
- </select>
- </p>
- <p>
- <label for="selection_single">Star Wars episodes:</label><br />
- <select id="selection_multiple" name="selection_multiple[]" multiple="multiple">
- <option>Star Wars Episode IV: A New Hope</option>
- <option>Star Wars Episode V: The Empire Strikes Back</option>
- <option selected="selected">Star Wars Episode VI: Return of the Jedi</option>
- </select>
- </p>
- <p>
- <input type="checkbox" id="silmaril" value="silmaril" name="checkbox[]"/><label for="silmaril">The Silmarillion</label><br />
- <input type="checkbox" id="hobbit" value="hobbit" name="checkbox[]" checked="checked"/><label for="hobbit">The Hobbit</label><br />
- <input type="checkbox" id="lotr" value="lotr" name="checkbox[]"/><label for="lotr">The Lord of The Rings</label><br />
- </p>
- <p>
- <input type="radio" id="martin" value="martin" name="radio" checked="checked"/><label for="martin">Goerge R.R. Martin</label><br />
- <input type="radio" id="tolkien" value="tolkien" name="radio"/><label for="tolkien">J.R.R. Tolkien</label><br />
- <input type="radio" id="adams" value="adams" name="radio"/><label for="adams">Douglas Adams</label><br />
- <input type="radio" id="pratchett" value="pratchett" name="radio"/><label for="pratchett">Terry Pratchett</label><br />
- </p>
- </fieldset>
-</p>
-<p>
- <fieldset>
- <legend>Textarea</legend>
- <p>
- <label for="textarea">Multiline text:</label><br />
- <textarea id="textarea" name="textarea" cols="50" rows="5">"In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move."
- Douglas Adams</textarea>
- </p>
- </fieldset>
-</p>
-<p><input type="submit" value="Submit"/></p>
-</form>
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/autofill-forms.git
More information about the Pkg-mozext-commits
mailing list