tracker r1153 - in trunk: . extensions/firefox-extension extensions/firefox-extension/chrome extensions/firefox-extension/chrome/content extensions/firefox-extension/chrome/content/jslib extensions/firefox-extension/chrome/content/jslib/debug extensions/firefox-extension/chrome/content/jslib/io extensions/firefox-extension/chrome/locale extensions/firefox-extension/chrome/locale/en-US extensions/firefox-extension/chrome/skin extensions/firefox-extension/chrome/skin/classic



Author: jerrytan
Date: Mon Feb 25 09:45:19 2008
New Revision: 1153
URL: http://svn.gnome.org/viewvc/tracker?rev=1153&view=rev

Log:
add firefox extension for web history


Added:
   trunk/extensions/firefox-extension/
   trunk/extensions/firefox-extension/Makefile
   trunk/extensions/firefox-extension/README
   trunk/extensions/firefox-extension/chrome/
   trunk/extensions/firefox-extension/chrome.manifest
   trunk/extensions/firefox-extension/chrome/content/
   trunk/extensions/firefox-extension/chrome/content/beagleAddFilter.js   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/content/beagleAddFilter.xul   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/content/beagleOverlay.js
   trunk/extensions/firefox-extension/chrome/content/beagleOverlay.xul
   trunk/extensions/firefox-extension/chrome/content/beaglePrefs.js
   trunk/extensions/firefox-extension/chrome/content/beaglePrefs.xul
   trunk/extensions/firefox-extension/chrome/content/contents.rdf
   trunk/extensions/firefox-extension/chrome/content/i18n.js
   trunk/extensions/firefox-extension/chrome/content/indexBookmark.js
   trunk/extensions/firefox-extension/chrome/content/indexLink.js
   trunk/extensions/firefox-extension/chrome/content/indexLink.xul   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/content/jslib/
   trunk/extensions/firefox-extension/chrome/content/jslib/debug/
   trunk/extensions/firefox-extension/chrome/content/jslib/debug/debug.js
   trunk/extensions/firefox-extension/chrome/content/jslib/io/
   trunk/extensions/firefox-extension/chrome/content/jslib/io/dir.js
   trunk/extensions/firefox-extension/chrome/content/jslib/io/dirUtils.js
   trunk/extensions/firefox-extension/chrome/content/jslib/io/file.js
   trunk/extensions/firefox-extension/chrome/content/jslib/io/fileUtils.js
   trunk/extensions/firefox-extension/chrome/content/jslib/io/filesystem.js
   trunk/extensions/firefox-extension/chrome/content/jslib/jslib.js
   trunk/extensions/firefox-extension/chrome/content/jslib/modules.js
   trunk/extensions/firefox-extension/chrome/content/json.js
   trunk/extensions/firefox-extension/chrome/content/md5.js
   trunk/extensions/firefox-extension/chrome/content/utils.js   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/locale/
   trunk/extensions/firefox-extension/chrome/locale/en-US/
   trunk/extensions/firefox-extension/chrome/locale/en-US/beagle.dtd
   trunk/extensions/firefox-extension/chrome/locale/en-US/beagle.properties
   trunk/extensions/firefox-extension/chrome/locale/en-US/contents.rdf
   trunk/extensions/firefox-extension/chrome/skin/
   trunk/extensions/firefox-extension/chrome/skin/classic/
   trunk/extensions/firefox-extension/chrome/skin/classic/beagle-big.png   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/skin/classic/beagle-disabled.png   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/skin/classic/beagle-error.png   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/skin/classic/beagle.png   (contents, props changed)
   trunk/extensions/firefox-extension/chrome/skin/classic/contents.rdf
   trunk/extensions/firefox-extension/chrome/skin/classic/overlay.css   (contents, props changed)
   trunk/extensions/firefox-extension/firefox-extension-xesam.xpi   (contents, props changed)
   trunk/extensions/firefox-extension/install.rdf
Modified:
   trunk/ChangeLog

Added: trunk/extensions/firefox-extension/Makefile
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/Makefile	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,53 @@
+
+PROJECT = firefox-extension-xesam
+VERSION = 1.0.1
+
+all: $(PROJECT).xpi
+
+XPI_FILES = 			\
+	chrome.manifest		\
+	install.rdf		\
+	chrome/content/contents.rdf		\
+	chrome/content/beagleOverlay.js	\
+	chrome/content/beagleOverlay.xul	\
+	chrome/content/beaglePrefs.js		\
+	chrome/content/beaglePrefs.xul		\
+	chrome/content/beagleAddFilter.xul	\
+	chrome/content/beagleAddFilter.js	\
+	chrome/content/indexLink.xul	\
+	chrome/content/indexLink.js	\
+	chrome/content/indexBookmark.js	\
+	chrome/content/md5.js			\
+	chrome/content/utils.js	\
+	chrome/content/i18n.js	\
+	chrome/content/json.js	\
+	\
+	chrome/content/jslib/jslib.js		\
+	chrome/content/jslib/modules.js	\
+	chrome/content/jslib/debug/debug.js	\
+	chrome/content/jslib/io/dir.js		\
+	chrome/content/jslib/io/dirUtils.js	\
+	chrome/content/jslib/io/file.js	\
+	chrome/content/jslib/io/fileUtils.js	\
+	chrome/content/jslib/io/filesystem.js	\
+	\
+	chrome/locale/en-US/contents.rdf	\
+	chrome/locale/en-US/beagle.dtd		\
+	chrome/locale/en-US/beagle.properties	\
+	\
+	chrome/skin/classic/contents.rdf	\
+	chrome/skin/classic/beagle-big.png	\
+	chrome/skin/classic/beagle-disabled.png\
+	chrome/skin/classic/beagle-error.png	\
+	chrome/skin/classic/beagle.png\
+	chrome/skin/classic/overlay.css	
+
+$(PROJECT).xpi: $(XPI_FILES)
+	zip -q9 $@ $^
+
+
+EXTRA_DIST =			\
+	$(XPI_FILES)
+
+CLEANFILES =			\
+	$(PROJECT).xpi

Added: trunk/extensions/firefox-extension/README
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/README	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,34 @@
+
+Beagle Extension: Index webpages you visit using the Beagle Indexing Engine.
+An Extension for the Firefox Browser.  
+
+Installing:
+	Open the generated beagle.xpi in Firefox or Mozilla.  
+	This will fire the Extension Manager.
+
+Features:
+	Uses beagle's IndexingService backend to index data.
+	Using domain/wildcard/regular expression to exclude/include the urls 
+	Import/export preferences 
+	Auto index when browsing (just click the status icon for enable/disable auto-indexing) 
+	    - Index referrer URL while indexing web-pages 
+	On-demand indexing 
+	    - Index current page 
+	    - Index link (for all the different filetypes beagle filters) 
+	    - Index image , the alt text is indexed. 
+	    - Store the URL of the current page while indexing, which may be useful while searching 
+	Index firefox bookmarks
+	    - Name, url, shortcut url(keywords),description and the path (name of ancestor folders is saved. 
+	    - Menu item bookmarks->Index The Modified Bookmarks 
+	    - Index the bookmarks when the window close ( you can turn it on/off in preference window) 
+	    - Last-index-date is saved . So only new bookmarks will be indexed. 
+	
+Debug:
+	You can set browser.dom.window.dump.enabled to true, in about:config. Open firefox in terminal, then you can see the debug information. You should also check javascript error console.
+
+Localization:
+	Add your localization files to chrome/locale/your-language/ 
+
+Visit http://beagle-project.org/Browser_Extension for details.
+This extension was written as a part of Google Summer of Code project, 2007 by Tao Fei (filia tao gmail com).
+

Added: trunk/extensions/firefox-extension/chrome.manifest
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome.manifest	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,6 @@
+content beagle  chrome/content/
+locale beagle en-US chrome/locale/en-US/
+skin   beagle classic/1.0 chrome/skin/classic/
+overlay chrome://browser/content/browser.xul chrome://beagle/content/beagleOverlay.xul
+overlay chrome://navigator/content/navigator.xul chrome://beagle/content/beagleOverlay.xul
+

Added: trunk/extensions/firefox-extension/chrome/content/beagleAddFilter.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/beagleAddFilter.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,11 @@
+function beaglePrefsAddFilterClicked() {
+	var pattern = document.getElementById('beagle.add.filter.pattern').value;
+    var name = document.getElementById('beagle.add.filter.name').value;
+    var patternType = document.getElementById('beagle.add.filter.patterntype').selectedItem.value;
+	var type = window.arguments[0];
+	var elementId = 'beagle.'+type+'.list';
+	var listbox = window.opener.document.getElementById(elementId);
+    appendRow(listbox,name,pattern,patternType);
+}
+
+

Added: trunk/extensions/firefox-extension/chrome/content/beagleAddFilter.xul
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/beagleAddFilter.xul	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://beagle/locale/beagle.dtd">
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+
+<dialog id="beagle.addPattern"
+  buttons="accept,cancel"
+  title="&beagle.pref.filter.add.dlg.title;"
+  ondialogaccept="beaglePrefsAddFilterClicked();"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";>
+  
+<script type="application/x-javascript" 
+		src="chrome://beagle/content/utils.js" />
+<script type="application/x-javascript" 
+		src="chrome://beagle/content/beagleAddFilter.js" />
+
+<grid flex="1">
+	<columns>
+		<column/>
+		<column flex="1"/>
+	</columns>
+    <rows>
+		<row>
+            <label>&beagle.pref.filter.name.label;</label><textbox id="beagle.add.filter.name" />
+        </row>
+        <row>
+			<label>&beagle.pref.filter.patterntype.label;</label>
+            <menulist id="beagle.add.filter.patterntype">
+                <menupopup>
+                    <menuitem value="domain" label="domain" />
+                    <menuitem value="wildcard"  label="wildcard"/>
+                    <menuitem value="regular expression" label="regular expression"/>
+                </menupopup>
+            </menulist>
+        </row>
+		<row>
+			<label>&beagle.pref.filter.pattern.label;</label><textbox id="beagle.add.filter.pattern" />
+		</row>
+	</rows>
+</grid>
+
+</dialog> 
+

Added: trunk/extensions/firefox-extension/chrome/content/beagleOverlay.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/beagleOverlay.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,709 @@
+/*
+ * Beagle Extension: Index webpages you visit using the Beagle Indexing Engine.
+ * An Extension for the Firefox  Browser.
+ */
+
+var beagle = {
+    //some constant 
+    RUN_BEAGLE_NOT_FOUND:-1,
+    RUN_INITED: 0,
+    RUN_ENABLED : 1,
+    RUN_DISABLED : 2,
+    RUN_ERROR : 3,
+    
+    pref : beaglePref,
+
+    ENV:Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment),
+
+    FILE_UTILS:new FileUtils(),// js lib  file utils
+    
+    /**
+     * see http://www.xulplanet.com/references/xpcomref/comps/c_embeddingbrowsernsWebBrowserPersist1.html
+     */
+    get PersistMask(){
+        var comp = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Components.interfaces.nsIWebBrowserPersist);
+        return (comp.PERSIST_FLAGS_FROM_CACHE | 
+                comp.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
+                comp.PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS |
+                comp.PERSIST_FLAGS_DONT_FIXUP_LINKS |
+                comp.PERSIST_FLAGS_DONT_CHANGE_FILENAMES |
+                comp.PERSIST_FLAGS_CLEANUP_ON_FAILURE);
+    },
+
+    get EncodeMask(){
+        var comp = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Components.interfaces.nsIWebBrowserPersist);
+        return (comp.ENCODE_FLAGS_RAW | comp.ENCODE_FLAGS_ABSOLUTE_LINKS);
+    },
+
+    get STATUS_ICON(){ 
+        return document.getElementById('beagle-notifier-status');
+    },
+    /**
+     * beagle data path (should be ~/.beagle/ToIndex)
+     */
+    dataPath : null,
+    
+    
+    /**
+     * the path to beagle search ,it is used for search (for link/page/text)
+     */
+    get beagleSearchPath() { 
+        var path = this.ENV.get("PATH");
+        if (path) {
+            var split = path.split(':');
+            var idx = 0;
+            while (idx < split.length) 
+            {
+                var trypath = split[idx++] + '/' + "beagle-search";
+                if (this.FILE_UTILS.exists(trypath))
+                    return trypath;
+            }
+        }
+        return undefined;
+    },
+    
+    /**
+     * save the tasks for the purpose of extra meta data
+     */ 
+    tasks: [],
+   
+    /**
+     * always call this before any index work begins 
+     */
+    startTask : function(url,extrameta)
+    {
+        this.tasks[url] = {meta:extrameta};
+    },
+
+    /**
+     * get the content file path for a give url and type 
+     * type can be "web" or "bookmark"
+     */
+    getContentPath: function(url,type)
+    {
+        if(typeof type == "undefined")
+            type = "web";
+        var hash = hex_md5(url);
+        return this.dataPath + "/firefox-xesam-"+ type + "-" + hash;
+        
+    },
+
+    /**
+     * get the meta file path for a give url and type 
+     * type can be "web" or "bookmark"
+     */
+    getMetaPath: function(url,type)
+    {
+        if(typeof type == "undefined")
+            type = "web";
+        var hash = hex_md5(url);
+        return this.dataPath + "/.firefox-xesam-"+ type + "-" + hash;
+    },
+
+    /**
+     * init beagle
+     * check environment
+     * init state
+     * init some varible
+     * add event listeners 
+     * import pref from oldExtension (if beagle.first.run)
+     */
+    init : function()
+    {
+        log("init");
+        if(!this.checkEnv())
+        {
+            this.runStatus = this.RUN_BEAGLE_NOT_FOUND;
+            this.error(_("beagle_not_found"));
+        }
+        else
+        {
+            if(this.pref.get('beagle.autoindex.active'))
+            {
+                this.enable();
+            }
+            else
+            {
+                this.disable();
+            }
+            this.dataPath = this.ENV.get("HOME") + "/.xesam/Firefox/ToIndex";  
+            if(!this.FILE_UTILS.exists(this.dataPath))
+                ;// do something here ? is it safe to create the dir ?
+        }
+        this.addEventListener();
+        if (this.pref.get("beagle.first.run"))
+        {
+            this.pref.firstRunImport();
+            this.pref.set("beagle.first.run",false);
+        }
+    },
+    
+    /**
+     * add the event listeners
+     * 
+     */
+    addEventListener : function ()
+    {
+        // Add listener for page loads
+        if (this.runStatus != this.RUN_BEAGLE_NOT_FOUND && document.getElementById("appcontent"))
+        {
+            document.getElementById("appcontent").addEventListener(
+                "load",
+                Function.bind(this.onPageLoad,this),
+                true
+            );
+            document.getElementById("contentAreaContextMenu").addEventListener(
+                "popupshowing", 
+                Function.bind(this.initContextMenu,this), 
+                false
+            );
+        }
+        if(this.runStatus != this.RUN_BEAGLE_NOT_FOUND)
+        {
+            window.addEventListener(
+                "unload",
+                function(){
+                    if(beaglePref.get("beagle.bookmark.active"))
+                        bookmarkIndexer.indexModified(false);
+                },
+                false
+            );
+/*            var observerService =
+                 Components.classes["@mozilla.org/observer-service;1"]
+                    .getService(Components.interfaces.nsIObserverService)
+            var observer = {
+                observe: function(subject,topic,data){
+                    log("index bookmarks when exit");
+                    dump(bookmarkIndexer.indexModified());
+                    log(" done r");
+                }
+            };
+            observerService.addObserver(observer,"quit-application",false);
+*/
+        }
+        this.STATUS_ICON.addEventListener(
+            'click',
+            Function.bind(this.onIconClick,this),
+            false
+        );
+    },
+
+    /**
+     * show the beagle context menu
+     */
+    initContextMenu : function (e)
+    {
+        if(e.originalTarget.id != "contentAreaContextMenu")
+            return;
+        //log(" gContextMenu " + gContextMenu );
+        gContextMenu.showItem("beagle-context-index-this-link", gContextMenu.onLink && !gContextMenu.onMailtoLink); 
+        gContextMenu.showItem("beagle-context-index-this-image", gContextMenu.onImage && gContextMenu.onLoadedImage); 
+        gContextMenu.showItem("beagle-context-search-link", gContextMenu.onLink); 
+        gContextMenu.showItem("beagle-context-search-text", gContextMenu.isTextSelected);
+        document.getElementById("beagle-context-search-text").setAttribute("label",
+            _f("beagle_context_search_text",[getBrowserSelection(16)]));
+    },
+
+    /**
+     *  check enviroment 
+     */
+    checkEnv : function()
+    {
+        var index_dir = this.ENV.get("HOME") + "/.xesam/Firefox/ToIndex";
+        try {
+            // Check if destination directory exists
+            var dir = Components.classes ["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+            dir.initWithPath (index_dir);
+            if (dir.exists ()) {
+                if (!dir.isDirectory ()) {
+                    alert("Destination directory exists but is not a directory!");
+                    return false;
+                }
+            }
+            else {
+                 //alert("we need to create it");
+                 dir.create (Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
+            } 
+        }
+        catch (ex) {
+                 return false;
+        } 
+        return true;
+
+    },
+
+    /**
+     * Check the page, 
+     * 1. the protocal (We will NOT index about:* file:///* )
+     * 2. check is the page  itself 
+     * TODO: for file:/// chrome:// and so on Index OR NOT
+     */
+    checkPage : function(page)
+    {
+        if (!page)
+        {
+            log("[checkPage the page doesn't seems to be a page");
+            return false;
+        } 
+        if (!page.location ||
+            !page.location.href ||
+            page.location.href.indexOf("about:") == 0 ||
+            page.location.href.indexOf("file:") == 0 )
+        {
+            log("checkPage  strage page " + page );
+            return false;
+        }
+        return true;
+    },
+
+    /*
+     * check weather the url should index
+     * return true if it need to index
+     */
+    shouldIndex : function(page)
+    {
+
+        var prefObject = this.pref.load();
+        
+        //check https
+        if (page.location.protocol == "https:" && !prefObject['beagle.security.active'])
+        {
+            return false;
+        }
+        var lists = ['beagle.exclude.list','beagle.include.list'];
+        var flags = [false,false];
+        for(var j = 0; j < 2; j++)
+        {
+            var list = parseJSON(prefObject[lists[j]]);
+            var len = list.length;
+            var flag = false;
+            for(var i = 0; i < len && !flag; i++)
+            {
+                switch(list[i]['patternType'])
+                {
+                case 'domain':
+                    //what means a domain matches
+                    //www.google.com matches google.com and matches .com
+                    //www.agoogle.com NOT matches google.com but matches com
+                    //www.com.google. NOT matches .com 
+                    var hostname = page.location.hostname;
+                    var pattern = list[i]['pattern'];
+                    if (pattern[0] != '.')
+                        pattern = "." + pattern;
+                    flag = hostname.isEndWith(pattern) ||(hostname == list[i]['pattern']);
+                    break;
+                case 'wildcard':
+                    var re =  RegExp(list[i]['pattern'].wilcard2RE());
+                    flag = (page.location.href.match(re) != null);
+                    break;
+                case 'regular expression':
+                    var re = RegExp(list[i]['pattern']);
+                    flag = (page.location.href.match(re) != null)
+                    break;
+                default:
+                    log("invaild rule" + list[i]); 
+                    //something wrong;
+                    break;
+                }
+            }
+            flags[j] = flag;
+        }
+        log("[Should Index ?][exclude=" + flags[0] + "][include=" + flags[1] + "]");
+        if(!flags[0] && !flags[1])
+            return prefObject['beagle.default.action'] == 1;
+        if(flags[0] && flags[1])
+            return prefObject['beagle.conflict.action'] == 1;
+        return flags[1];
+
+    },
+    
+    /**
+     * just set the status label 
+     */
+    setStatusLabel : function (msg)
+    {
+        setTimeout(
+            function(){document.getElementById('statusbar-display').label = msg},
+            100
+        );
+    },
+    
+    /**
+     * prompt extra keywords on demand-index
+     */
+    promptExtraKeywords : function(url)
+    {
+        if(this.pref.get("beagle.prompt.keywords.active"))
+        {
+            var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                                    .getService(Components.interfaces.nsIPromptService);
+            var input = { value: "" };
+            var chk = { value:false };
+            result = prompts.prompt(window, 
+                _("beagle_prompt_keywords_title"),
+                _("beagle_prompt_keywords_text"), input, null, chk);
+            if (result && input.value != "")
+            {
+                this.tasks[url]["meta"].push("t:dc:keyword="+ input.value);
+            }
+        }
+    },
+
+    /***************************************************
+     *        IO related code 
+     **************************************************/
+
+    /**
+     * write page content (NOT the HTML source, 
+     * the DOM instead, it may include dym contnent created by js)
+     */
+    writeContent : function(page, tmpfilepath)
+    {
+        var tmpfile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+        tmpfile.initWithPath(tmpfilepath);
+
+        var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Components.interfaces.nsIWebBrowserPersist);
+        persist.persistFlags = this.PersistMask;
+        persist.saveDocument(page, tmpfile, null, null, this.EncodeMask, 0);
+    },
+
+    /**
+     * for non-html and non-text file . save it 
+     * progressListener is used by index-link. to show the progree.
+     */
+    saveFile : function(url,path,progressListener)
+    {
+        var tmpfile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+        tmpfile.initWithPath(path);
+        var cacheKey  = Components.classes['@mozilla.org/supports-string;1'].createInstance(Components.interfaces.nsISupportsString);
+        cacheKey.data = url;
+        var urifix  = Components.classes['@mozilla.org/docshell/urifixup;1'].getService(Components.interfaces.nsIURIFixup);
+        var uri     = urifix.createFixupURI(url, 0);
+        var hosturi = null;
+        if (uri.host.length > 0)
+        {
+            hosturi = urifix.createFixupURI(uri.host, 0);
+        }
+        this.persist = Components.classes['@mozilla.org/embedding/browser/nsWebBrowserPersist;1'].createInstance(Components.interfaces.nsIWebBrowserPersist);
+        this.persist.persistFlags = this.PersistMask;
+        if(progressListener)
+            this.persist.progressListener = progressListener; 
+        this.persist.saveURI(uri, cacheKey, hosturi, null, null, tmpfile);
+    },
+
+    /**
+     * write raw-meatadata 
+     */
+    writeRawMetadata : function(meta, tmpfilepath)
+    {
+        var tmpfile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+        tmpfile.initWithPath(tmpfilepath);
+
+        var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
+        stream.QueryInterface(Components.interfaces.nsIOutputStream);
+        stream.init(tmpfile, 0x04 | 0x08 | 0x20, 0600, 0);
+
+        var line;
+        log("writing metas ");
+        for(var i = 0; i < meta.length; i++)
+        {
+            line = meta[i] + "\n";
+            log(meta[i]);
+            stream.write(line, line.length);
+        }
+        stream.flush();
+        stream.close();
+    },
+
+
+    /**
+     * write meatadata of page  
+     * include URI hittype mimetype characterset referrer 
+     * if any extra meta is set in task, write it too.
+     */
+    writeMetadata : function(page, tmpfilepath)
+    {
+        var url = page.location.href;
+        var meta = [
+            url,
+            'WebHistory',
+            page.contentType,
+            "k:_unindexed:encoding="+page.characterSet,
+            ];
+        if(typeof page.referrer != "undefined" && page.referrer != "")
+        {
+            meta.push("t:fixme:referrer=" + page.referrer);
+        }
+        meta = meta.concat(this.tasks[url]['meta'])
+        beagle.writeRawMetadata(meta,tmpfilepath);
+    },
+
+    /**
+     * index a page 
+     * write content and meta
+     */
+    indexPage : function(page)
+    {
+        var url = page.location.href;
+        log(" We will index " + url ); 
+        
+        try {
+            this.writeContent(page, this.getContentPath(url));
+            this.writeMetadata(page, this.getMetaPath(url));
+        } catch (ex) {
+            log ("beaglePageLoad: beagleWriteContent/Metadata failed: " + ex );
+            if(confirm(_('beagle_write_error_confirm')))
+                this.disable();
+            return;
+        }
+        this.setStatusLabel(_f("beagle_statuslabel_indexing",[url]));
+    },
+    
+    /**
+     * index a file (non-html and non-text) 
+     * we assume the content is saved already.
+     * just write meta here
+     */
+    indexFile : function(url,contentType)
+    {
+        log(" We will index " + url ); 
+        
+        var meta = [url,'WebHistory',contentType];
+        meta = meta.concat(this.tasks[url]['meta'])
+        try {
+            this.writeRawMetadata(meta, this.getMetaPath(url));
+        } catch (ex) {
+            log ("[indexFile] beage write Metadata failed: " + ex + "\n");
+            if(confirm(_('beagle_write_error_confirm')))
+                this.disable();
+            return;
+        }
+        this.setStatusLabel(_f("beagle_statuslabel_indexing",[url]));
+    },
+    
+    /****************************************************************************
+     *                      Event Handlers 
+     ***************************************************************************/
+
+    /**
+     * index this page (event handler)
+     */
+    indexThisPage : function()
+    {
+        var doc = document.getElementById('content').selectedBrowser.contentDocument;
+        if(!this.checkPage(doc))
+            return;
+        var url = doc.location.href;
+        this.startTask(url,[]);
+        this.promptExtraKeywords(url);
+        if(doc.contentType.match(/(text|html|xml)/i))// a document
+        {
+            this.indexPage(doc);
+        }
+        else
+        {
+            this.saveFile(url,this.getContentPath(url),null);
+            this.indexFile(url,doc.contentType);
+        }
+    },
+
+    /**
+     * index link (event handler)
+     */
+    indexLink : function()
+    {
+        var url = gContextMenu.linkURL; 
+        if (!url)
+            return;
+        var referrer = gBrowser.currentURI.spec;
+        this.startTask(url,
+            ["t:fixme:referrer=" + referrer]
+            );
+        window.openDialog("chrome://beagle/content/indexLink.xul",
+            "","chrome,centerscreen,all,resizable,dialog=no",url,referrer);
+    },
+    /**
+     * index image (event handler)
+     */
+    indexImage : function()
+    {
+        var image = gContextMenu.target; 
+        if(image.tagName.toLowerCase() != 'img' || !image.src)
+            return;
+        var url = image.src;
+        var referrer = gBrowser.currentURI.spec;
+        this.startTask(url,[
+                "t:alttext="+(image.getAttribute('alt')?image.getAttribute('alt'):""),
+                "t:fixme:referrer="+referrer]
+                );
+        window.openDialog("chrome://beagle/content/indexLink.xul",
+            "","chrome,centerscreen,all,resizable,dialog=no",url,referrer);
+    },
+
+    /**
+     * callback for link loaded  (called from indexLink.js)
+     * TODO: what if the url is no longer the url we passed to indexLink
+     */
+    onLinkLoad : function(url,contentType,doc,orginalURL)
+    {   
+        if(url != orginalURL)
+        {
+            log(url)
+            log(orginalURL);
+            this.tasks[url] = this.tasks[orginalURL];
+        }
+        this.promptExtraKeywords(url);
+        if(contentType.match(/(text|html|xml)/i) && doc)// a document
+        {
+            if(!this.checkPage(doc))
+                return;
+            this.indexPage(doc);
+        }
+        else
+        {
+            this.indexFile(url,contentType);
+        }
+    },
+
+    /**
+     * called when page is loaded (event handler)
+     */
+    onPageLoad : function(event)
+    { 
+        log("Page Loaded ");
+        //if disabled or error
+        if(this.runStatus != this.RUN_ENABLED)
+        {
+            log(" NOT RUN_ENABLED status .  NO INDEX");
+            return;
+        }
+        var page = event.originalTarget;
+        if (!this.checkPage(page))
+            return;
+        if (!this.shouldIndex(page))
+            return;
+        var url = page.location.href;
+        this.startTask(url,[]);
+        if(page.contentType.match(/(text|html|xml)/i))// a document
+        {
+            this.indexPage(page);
+        }
+        else
+        {
+            this.saveFile(url,this.getContentPath(url),null);
+            this.indexFile(url,page.contentType);
+        }
+    },   
+    
+        
+    /**
+     * add exclude /include rule
+     * the "domain" rule
+     */
+    quickAddRule : function (page,flag)
+    {
+        try{
+            var domain =  page.location.hostname;
+            this.pref.addRule("qa_" + domain,domain,"domain",flag);
+        }
+        catch(e){
+            alert(_("beagle_quick_add_rule_error"));
+        }
+    },
+
+    /**
+     * show preference winodw (event handler)
+     */
+    showPrefs : function()
+    {
+        window.openDialog('chrome://beagle/content/beaglePrefs.xul',
+                'PrefWindow',
+                'chrome,resizable=no',
+                'browser');
+    },
+
+    /**
+     * status icon clicked. (event handler)
+     * toggle auto-index
+     */
+    onIconClick : function(event)
+    {
+       // Left-click event (also single click, like Mac).
+        if (event.button == 0 && event.ctrlKey == 0) {
+            switch(this.runStatus)
+            {
+            case this.RUN_ENABLED:
+                // currently enabled. disable 
+                this.disable();
+                break;
+            case this.RUN_DISABLED:
+                // currently disabled  enable.
+                this.enable();
+                break;
+            default:
+                // last run was an error, show the error
+                alert("Error running Beagle Indexer: " + this.RunStatus);
+                break;
+            }
+        }
+    },
+
+    /**
+     * call beagle search by query 
+     */
+    search : function(query)
+    {
+        if(!this.beagleSearchPath)
+            return;
+        try {
+            log("Running beagle search with query: "+ query );
+            var retval = this.FILE_UTILS.spawn(this.beagleSearchPath, ["", query]);
+            if (retval) 
+                alert("Error running beagle search: " + retval);
+        } 
+        catch(e){
+                alert("Caught error from beagle-search: " + e);
+        }
+    },
+    
+    /************************************************************
+     *  status switch functions
+     ************************************************************/
+    
+    /**
+     * disable beagle auto index
+     */
+    disable : function()
+    {
+        this.runStatus = this.RUN_DISABLED;
+        this.STATUS_ICON.setAttribute("status","00f");
+        this.STATUS_ICON.setAttribute("tooltiptext",_("beagle_tooltip_disabled"));
+        this.pref.set("beagle.autoindex.active",false);
+    },
+
+    /**
+     * enable beagle auto index
+     */
+    enable : function()
+    {
+        this.runStatus = this.RUN_ENABLED;
+        this.STATUS_ICON.setAttribute("status","000");
+        this.STATUS_ICON.setAttribute("tooltiptext",_("beagle_tooltip_actived"));
+        this.pref.set("beagle.autoindex.active",true);
+    },
+    
+    /**
+     * error occours
+     */
+    error : function(msg)
+    {
+        this.runStatus = this.RUN_ERROR;
+        this.STATUS_ICON.setAttribute("status","f00");
+        this.STATUS_ICON.setAttribute("tooltiptext",_f("beagle_tooltip_error",[msg]));
+        this.pref.set("beagle.autoindex.active",false);
+    },
+};
+
+// Create event listener.
+window.addEventListener('load', Function.bind(beagle.init,beagle),false); 
+

Added: trunk/extensions/firefox-extension/chrome/content/beagleOverlay.xul
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/beagleOverlay.xul	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://beagle/skin/overlay.css" type="text/css"?>
+<!DOCTYPE overlay SYSTEM "chrome://beagle/locale/beagle.dtd">
+
+<overlay id="BeagleOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";>
+         
+<stringbundleset id="stringbundleset">
+    <stringbundle id="beagleStrings"
+            src="chrome://beagle/locale/beagle.properties"/>
+</stringbundleset>
+
+
+
+<!-- jslib sources used for executing beagle -->
+<script type="text/javascript" src="jslib/jslib.js"/>
+<script type="text/javascript" src="jslib/io/file.js"/>
+<script type="text/javascript" src="jslib/io/fileUtils.js"/>
+<script type="text/javascript" src="jslib/io/dir.js"/>
+<script type="text/javascript" src="jslib/io/dirUtils.js"/>
+
+<script type="text/javascript" src="utils.js" />
+<script type="text/javascript" src="i18n.js"/>
+<script type="text/javascript" src="md5.js" />
+<script type="text/javascript" src="json.js" />
+<script type="text/javascript" src="beaglePrefs.js" />
+<script type="text/javascript" src="beagleOverlay.js" />
+<script type="text/javascript" src="indexBookmark.js" />
+
+<commandset id="mainCommandSet">
+    <command id="IndexThisCmd" label="&beagle.run.index.this.label;" 
+        oncommand="beagle.indexThisPage();"/>
+    <command id="AlwaysIndexThisSiteCmd" label="&beagle.run.always.index.label;"  
+        oncommand="beagle.quickAddRule(document.getElementById('content').selectedBrowser.contentDocument,beaglePref.RULE_INCLUDE)"/>
+    <command id="NeverIndexThisSiteCmd" label="&beagle.run.never.index.label;" 
+        oncommand="beagle.quickAddRule(document.getElementById('content').selectedBrowser.contentDocument,beaglePref.RULE_EXCLUDE)"/>
+    <command id="ShowPrefsCmd" label="&beagle.run.preferences.label;" 
+            oncommand="beagle.showPrefs()"/>
+    <command id="IndexThisLinkCmd" label="&beagle.run.index.link.label;" 
+        oncommand="beagle.indexLink()"/>
+    <command id="IndexThisImageCmd" label="&beagle.run.index.image.label;" 
+        oncommand="beagle.indexImage()"/>
+    <command id="SearchLinkCmd" label="&beagle.context.search.link.label;"
+        oncommand="beagle.search(gContextMenu.linkURL);"/>
+    <command id="SearchPageCmd" label="&beagle.context.search.page.label;"
+        oncommand="beagle.search(getWebNavigation().currentURI.spec);"/>
+    <command id="SearchTextCmd" 
+        oncommand="beagle.search(getBrowserSelection());"/>
+    <!--
+    <command id="IndexAllBookmarksCmd" label="&beagle.bookmark.index.all.label;"
+        oncommand="BookmarkIndexer.indexAll();"/>
+    -->
+    <command id="IndexModifiedBookmarkCmd" label="&beagle.bookmark.index.modified.label;"
+        oncommand="bookmarkIndexer.indexModified(true);"/>
+</commandset>
+
+<!-- toolbar is not necessary -->
+<!--
+<toolbarpalette id="BrowserToolbarPalette">
+    <toolbarbutton id="beagle-button" type="menu-button"
+                   class="toolbarbutton-1 chromeclass-toolbar-additional"
+                   context="beagle-toolbar-popup"
+                   tooltiptext="&beagle.run.index.this.label;"
+                   label="beagle">
+        <menupopup id="beagle-toolbar-popup" >
+            <menuitem  command="IndexThisCmd"/>
+            <menuseparator />
+            <menuitem  command="AlwaysIndexThisSiteCmd"/> 
+            <menuitem  command="NeverIndexThisSiteCmd"/> 
+            <menuseparator />
+            <menuitem  command="ShowPrefsCmd"/> 
+        </menupopup>
+    </toolbarbutton>
+</toolbarpalette>
+-->
+
+<!--  Add  Index Bookmark menuitem in Bookmarks Menu -->
+<!--  position=4 to place item after Bookmark Manager which is normally 3 with Firefox 1.5-->
+<menupopup id="menu_BookmarksPopup" contextmenu='bookmarks-context-menu'>
+    <menuitem id="beagle-index-modified-bookmarks"
+	command="IndexModifiedBookmarkCmd"/>
+</menupopup>
+
+
+<popup id="contentAreaContextMenu">
+    <menuseparator />
+    <menu label="&beagle.run.context.menu.label;">
+        <menupopup id="beagle-content-popup">
+            <menuitem  id="beagle-context-index-this-link" command="IndexThisLinkCmd"/>
+            <menuitem  id="beagle-context-index-this-image" command="IndexThisImageCmd"/>
+            <menuitem  id="beagle-context-index-this" command="IndexThisCmd"/>
+            <menuseparator />
+            <menuitem id="beagle-context-search-link" command="SearchLinkCmd"/>
+            <menuitem id="beagle-context-search-text" command="SearchTextCmd"/>
+            <menuitem id="beagle-context-search-page" command="SearchPageCmd"/>
+            <menuseparator />
+            <menuitem command="AlwaysIndexThisSiteCmd"/> 
+            <menuitem command="NeverIndexThisSiteCmd"/> 
+            <menuseparator />
+            <menuitem command="ShowPrefsCmd"/> 
+        </menupopup>
+    </menu>
+    <menuseparator />
+
+</popup>
+
+<statusbar id="status-bar">
+    <statusbarpanel
+        class="statusbarpanel-menu-iconic"
+        id="beagle-notifier-status"
+        context='beagle-status-popup'
+        status="000"
+        >
+    </statusbarpanel> 
+    <menupopup id="beagle-status-popup" position="before_end">
+        <menuitem command="IndexThisCmd"/>
+        <menuseparator />
+        <menuitem command="AlwaysIndexThisSiteCmd"/> 
+        <menuitem command="NeverIndexThisSiteCmd"/> 
+        <menuseparator />
+        <menuitem command="ShowPrefsCmd"/> 
+   </menupopup>
+</statusbar> 
+</overlay>

Added: trunk/extensions/firefox-extension/chrome/content/beaglePrefs.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/beaglePrefs.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,324 @@
+/*
+ * Beagle Extension: Index webpages you visit using the Beagle Indexing Engine.
+ * An Extension for the Firefox Browser.
+ */
+
+// Initiate a new preference instance.
+var gPrefService = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
+
+var beaglePref = {
+   
+    //some constant
+    RULE_INCLUDE : 1,
+    RULE_EXCLUDE : 2,
+
+    // Declare Pref Keys and Type.
+    prefKeys : { 
+      'beagle.security.active':{'type':'bool','default':false},
+      'beagle.bookmark.active':{'type':'bool','default':false},
+      'beagle.prompt.keywords.active':{'type':'bool','default':false},
+      'beagle.default.action':{'type':'int','default':1},
+      'beagle.conflict.action':{'type':'int','default':1},
+      'beagle.include.list':{'type':'string','default':"[]"},
+      'beagle.exclude.list':{'type':'string','default':"[]"},
+      'beagle.autoindex.active':{'type':'bool','default':true},
+      'beagle.bookmark.last.indexed.date':{'type':'string','default':'0'},
+      'beagle.first.run':{'type':'bool','default':true},
+    },
+
+   
+    //functions used to get/set pref
+    func_factory:{
+        'get':{
+            'bool': Function.bind(gPrefService.getBoolPref,gPrefService),
+            'int': Function.bind(gPrefService.getIntPref,gPrefService),
+            'string' : Function.bind(gPrefService.getCharPref,gPrefService)
+        },
+        'set':{
+            'bool': Function.bind(gPrefService.setBoolPref,gPrefService),
+            'int' : Function.bind(gPrefService.setIntPref,gPrefService),
+            'string' : Function.bind(gPrefService.setCharPref,gPrefService)
+        }
+    },
+
+    prefObject : {},
+    
+    /**
+     * get the pref value by key
+     * we will use right type according to prefKeys
+     */
+    get : function(key)
+    {
+        if(!this.prefKeys.hasOwnProperty(key))
+            return null;
+        try{
+            return this.func_factory['get'][this.prefKeys[key]['type']].call(null,key);
+        }
+        catch(ex){
+            log("[beaglPref.get " + key + "] " + ex );
+            return this.prefKeys[key]['default']; 
+        }
+    },
+
+    /**
+     * set pref value 
+     * we will use right type according to prefKeys
+     */
+    set : function(key,value)
+    {
+        if(!this.prefKeys.hasOwnProperty(key))
+            return false;
+        try{
+            this.func_factory['set'][this.prefKeys[key]['type']].call(null,key,value);
+            return true;
+        }
+        catch(ex){
+            return false; 
+        }
+        
+    },
+
+    /*
+     * Load Prefs into a javascript object (this.prefObject)
+     *
+     */
+    load : function()
+    {
+        //log(toJSONString(this.prefKeys));
+        
+        for(key in this.prefKeys)
+        {
+            if(!this.prefKeys.hasOwnProperty(key))
+                continue;
+            var value = this.get(key);
+            if(value != null)
+                this.prefObject[key] = value;
+            else
+                log(key + " is null" );
+        }
+        return this.prefObject;
+    },
+
+    /*
+     * Save Prefs (in this.prefObject) into firefox
+     */
+    save : function()
+    {
+        for(key in this.prefKeys)
+        {
+            this.set(key, this.prefObject[key]);
+        }
+        log("Save Beagle Prefs:" + toJSONString(this.prefObject) );
+    },
+
+    /**
+     * init beagle pref , load pref, init UI
+     */
+    init : function ()
+    {
+        log("beaglePref init");
+        this.load(); 
+        this.UIInit();
+    },
+
+    /**
+     *  init the UI
+     */
+    UIInit : function ()
+    {
+        log("beaglePref uiinit");
+        var checkboxElements = ["beagle.security.active","beagle.bookmark.active","beagle.prompt.keywords.active"]
+        for(var i = 0; i < checkboxElements.length; i++)
+        {
+            var elementID = checkboxElements[i];
+            try{
+                document.getElementById(elementID).checked = this.prefObject[elementID]
+             }
+            catch(ex){
+                log(ex);
+                document.getElementById(elementID).checked = true;
+             }
+        }
+
+        var radioElements = ["beagle.default.action","beagle.conflict.action"]
+        for(var i = 0; i < radioElements.length; i++)
+        {
+            var elementID = radioElements[i];
+            var radios = document.getElementById(elementID).getElementsByTagName('radio');
+            try{
+                for (var j = 0; j < radios.length; j++)
+                {
+                    if(radios[j].value == this.prefObject[elementID])
+                    {
+                        document.getElementById(elementID).selectedItem = radios[j]
+                        break;
+                    }
+                }
+            }
+            catch(ex){
+                log(ex);
+            }
+        }
+     
+        //beagle.include.list and beagle.exclude.list
+        var listElements = ["beagle.include.list","beagle.exclude.list"];
+        for (var i = 0; i < listElements.length; i++)
+        {
+            var elementID = listElements[i];
+            try{
+                var items = parseJSON(this.prefObject[elementID]); 
+                var listbox = document.getElementById(elementID) ;
+                //log("listbox.getRowCount:" + listbox.getRowCount() + '\n');
+                var num = listbox.getRowCount();
+                for (var j = 0; j < num; j++)
+                    listbox.removeItemAt(0);
+                
+                for (var j = 0; j < items.length; j++){
+                    appendRow(listbox,items[j]['name'],items[j]['pattern'],items[j]['patternType']);
+                 }
+            } catch(ex) {
+                log(ex);
+                log(this.prefObject[elementID]);
+            }
+        }
+     
+    },
+
+    /****************************************************************************
+     *                      Event Handlers 
+     ***************************************************************************/
+    
+    /*
+     *  This function is called when the save button is clicked
+     */
+    onSave : function ()
+    {
+        var prefs = {};
+        
+        var checkboxElements = ["beagle.security.active","beagle.bookmark.active","beagle.prompt.keywords.active"]
+        for(var i = 0; i < checkboxElements.length; i++)
+        {
+            var elementID = checkboxElements[i];
+            try{
+                prefs[elementID] = document.getElementById(elementID).checked;
+             }
+            catch(e){
+                prefs[elementID] = false;
+             }
+        }
+
+        var radioElements = ["beagle.default.action","beagle.conflict.action"]
+        for(var i = 0; i < radioElements.length; i++)
+        {
+            var elementID = radioElements[i];
+            try{
+                prefs[elementID] = document.getElementById(elementID).value;
+             }
+            catch(e){
+             }
+        }
+             
+        //beagle.include.list and beagle.exclude.list
+        var listElementIDs = ["beagle.include.list","beagle.exclude.list"];
+        for (var i = 0; i < listElementIDs.length; i++)
+        {
+            var elementID = listElementIDs[i];
+            try {
+                var items = new Array() ;
+                var listbox = document.getElementById(elementID) ;
+
+                for (var j = 0; j < listbox.getRowCount(); j++){
+                    var listitem =  listbox.getItemAtIndex(j);
+                    var name = listitem.getElementsByTagName('listcell')[0].getAttribute('value');
+                    var pattern = listitem.getElementsByTagName('listcell')[1].getAttribute('value');
+                    var patternType = listitem.getElementsByTagName('listcell')[2].getAttribute('value');
+                    items.push({'name':name,'pattern':pattern,'patternType':patternType});
+                }
+                var value = toJSONString(items);
+                prefs[elementID] = value;
+            } catch(e) {
+                // We don't seem to care about this.
+            }
+        }
+
+        this.prefObject = prefs;
+        this.save();   
+    },
+
+    /**
+     * open a dialog to add a filter 
+     */
+    onAddFilter : function (type)
+    {
+        window.openDialog(
+            'chrome://beagle/content/beagleAddFilter.xul',
+            "add_filter_dialog", 
+            'chrome,modal',
+            type
+        );
+    },
+
+    /**
+     *remove a filter
+     */
+    onRemoveFilter : function(type) 
+    {
+        try{
+            var listbox = document.getElementById('beagle.'+type+'.list');
+            listbox.removeItemAt(listbox.selectedIndex);
+        } catch(e){
+            //ignore
+        }
+    },
+
+    
+    /**
+     * Add Exclude / Include rule
+     * name the rule name
+     * pattern the pattern
+     * type the pattern type 
+     * flag  RULE_INCLUDE or RULE_EXCLUDE
+     */
+    addRule : function (name,pattern,type,flag)
+    {
+        switch(flag)
+        {
+        case this.RULE_INCLUDE:
+            key = "beagle.include.list";
+            break;
+        case this.RULE_EXCLUDE:
+            key = "beagle.exclude.list";
+            break;
+        default:
+            //error
+            return;
+        }
+        var rules = parseJSON(this.get(key));
+        rules.push({"name":name,"pattern":pattern,"patternType":type});
+        this.set(key,toJSONString(rules));
+    },
+
+    /**
+     * First Run import (from old extension)
+     */
+    firstRunImport : function()
+    {
+        try{
+            this.set("beagle.autoindex.active",gPrefService.getBoolPref("beagle.enabled"));
+            this.set("beagle.security.active",gPrefService.getBoolPref("beagle.security.active"));
+            var filters = gPrefService.getCharPref("beagle.security.filters").split(";");
+            var excludeList = parseJSON(this.get("beagle.exclude.list"));
+            for(var i = 0; i < filters.length; i++)
+            {
+                if(filters[i] != "")         
+                    excludeList.push({"name":"Import_"+i,"pattern":filters[i],"patternType":"domain"});
+            }
+            this.set("beagle.exclude.list",toJSONString(excludeList));
+        }
+        catch(ex){
+            log("first run import error");
+            log(ex);
+        }
+    },
+}
+

Added: trunk/extensions/firefox-extension/chrome/content/beaglePrefs.xul
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/beaglePrefs.xul	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,141 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE window SYSTEM "chrome://beagle/locale/beagle.dtd">
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+<dialog id="beagle-pref"
+    buttons="accept,cancel,help" 
+    onload="beaglePref.init();" 
+    ondialogaccept="beaglePref.onSave();window.close();"
+    ondialoghelp="window.open('http://beagle-project.org/Browser_Extension#Firefox_Extension');"
+    persist="screenX screenY"
+    title="&beagle.pref.label;"
+    flex="1"
+    style="min-width:500px"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";>
+    <stringbundleset id="stringbundleset">
+        <stringbundle id="beagleStrings"
+                src="chrome://beagle/locale/beagle.properties"/>
+    </stringbundleset>
+
+
+    <!-- jslib sources used for executing beagle -->
+    <script type="text/javascript" src="jslib/jslib.js"/>
+    <script type="text/javascript" src="jslib/io/file.js"/>
+    <script type="text/javascript" src="jslib/io/fileUtils.js"/>
+
+    <script type="text/javascript" src="utils.js" />
+
+    <script type="text/javascript" src="json.js" />
+      
+    <script type="text/javascript" src="i18n.js" />
+    
+    <script type="text/javascript" src="beaglePrefs.js" />
+    
+    
+    <groupbox>
+        <caption label="&beagle.pref.groupbox.general.label;" />
+        <!--checkbox 
+          id="beagle.context.active" 
+          label="&beagle.pref.context.active.label;"
+          type="checkbox" 
+        /-->
+
+        <checkbox 
+          id="beagle.security.active" 
+          label="&beagle.pref.security.active.label;"
+          type="checkbox" 
+          />
+        <checkbox 
+          id="beagle.bookmark.active" 
+          label="&beagle.pref.bookmark.active.label;"
+          type="checkbox" 
+          />
+         <checkbox 
+          id="beagle.prompt.keywords.active" 
+          label="&beagle.pref.prompt.keywords.active.label;"
+          type="checkbox" 
+          />
+        <hbox>
+            <label tooltiptext="&beagle.pref.default.action.tooltip;">&beagle.pref.default.action.label;:</label>
+            <radiogroup id="beagle.default.action" orient="horizontal">
+                <radio id="beagle.default.action.noindex" value="0" label="&beagle.pref.action.noindex.label;" />
+                <radio id="beagle.default.action.index" value="1" label="&beagle.pref.action.index.label;"/>
+            </radiogroup>
+        </hbox>
+        <hbox>
+            <label tooltiptext="&beagle.pref.conflict.action.tooltip;">&beagle.pref.conflict.action.label;:</label>
+            <radiogroup id="beagle.conflict.action" orient="horizontal">
+                <radio id="beagle.conflict.action.noindex" value="0" label="&beagle.pref.action.noindex.label;" />
+                <radio id="beagle.conflict.action.index" value="1" label="&beagle.pref.action.index.label;"/>
+            </radiogroup>
+        </hbox>
+
+    </groupbox>
+
+    <!--The Patterns to Include-->		  
+    <groupbox flex="1">
+        <caption label="&beagle.pref.groupbox.include.label;"/>
+        <hbox flex="1">
+        <vbox flex="1">
+        <listbox flex="1" rows="4" id="beagle.include.list">
+        <listhead>
+            <listheader id="includeName" label="&beagle.pref.filter.name.label;" />
+            <listheader id="includePattern" label="&beagle.pref.filter.pattern.label;" />
+            <listheader id="includePatternType" label="&beagle.pref.filter.patterntype.label;" />
+        </listhead>
+        <listcols>
+            <listcol />
+            <listcol flex="2"/>
+            <listcol flex="1"/>
+        </listcols>
+        </listbox>
+        </vbox>
+        <vbox>
+        <button command="AddIncludeFilterCmd" />
+        <button command="RemoveIncludeFilterCmd"  />
+        </vbox>
+        </hbox>
+    </groupbox>
+
+
+    <!--The Patterns to Exclude-->		  
+    <groupbox flex="1">
+        <caption label="&beagle.pref.groupbox.exclude.label;"/>	
+        <hbox flex="1">
+        <vbox flex="1">
+        <listbox flex="1" rows="4" id="beagle.exclude.list">
+        <listhead>
+            <listheader id="excludeName" label="&beagle.pref.filter.name.label;" />
+            <listheader id="excludePattern" label="&beagle.pref.filter.pattern.label;" />
+            <listheader id="excludePatternType" label="&beagle.pref.filter.patterntype.label;" />
+        </listhead>
+        <listcols>
+            <listcol />
+            <listcol flex="2"/>
+            <listcol flex="1"/>
+        </listcols>
+        </listbox>
+        </vbox>
+        <vbox>
+        <button command="AddExcludeFilterCmd" />
+        <button command="RemoveExcludeFilterCmd"  />
+        </vbox>
+        </hbox>
+    </groupbox>
+
+    <commandset>
+        <command id="AddIncludeFilterCmd" label="&beagle.pref.filter.add.label;" 
+            oncommand="beaglePref.onAddFilter('include')"/>
+        <command id="AddExcludeFilterCmd" label="&beagle.pref.filter.add.label;" 
+            oncommand="beaglePref.onAddFilter('exclude')"/>
+        <command id="RemoveIncludeFilterCmd" label="&beagle.pref.filter.remove.label;" 
+            oncommand="beaglePref.onRemoveFilter('include')"/>
+        <command id="RemoveExcludeFilterCmd" label="&beagle.pref.filter.remove.label;" 
+            oncommand="beaglePref.onRemoveFilter('exclude')"/>
+    </commandset>
+</dialog> 
+
+
+

Added: trunk/extensions/firefox-extension/chrome/content/contents.rdf
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/contents.rdf	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; 
+	 xmlns:chrome="http://www.mozilla.org/rdf/chrome#";>
+
+  <RDF:Seq RDF:about="urn:mozilla:package:root">
+    <RDF:li RDF:resource="urn:mozilla:package:beagle"/>
+  </RDF:Seq>
+    
+  <RDF:Seq RDF:about="urn:mozilla:overlays">
+    <RDF:li RDF:resource="chrome://browser/content/browser.xul"/>
+    <RDF:li RDF:resource="chrome://navigator/content/navigator.xul"/>
+  </RDF:Seq>
+     
+  <RDF:Seq RDF:about="chrome://browser/content/browser.xul">
+    <RDF:li>chrome://beagle/content/beagleOverlay.xul</RDF:li>
+  </RDF:Seq>
+  
+  <RDF:Seq about="chrome://navigator/content/navigator.xul">
+    <RDF:li>chrome://beagle/content/beagleOverlay.xul</RDF:li>
+  </RDF:Seq>  
+  
+  <RDF:Description 
+    RDF:about="urn:mozilla:package:beagle"
+    chrome:displayName="Beagle Indexer 0.2"
+    chrome:author="Filia Tao"
+    chrome:authorURL="mailto:filia tao gmail com"
+    chrome:name="beagle"
+    chrome:extension="true"
+    chrome:description="Index webpages you visit using the Beagle Indexing Engine."
+    chrome:settingsURL="chrome://beagle/content/beaglePrefs.xul">
+  </RDF:Description>
+
+</RDF:RDF>

Added: trunk/extensions/firefox-extension/chrome/content/i18n.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/i18n.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,54 @@
+//check the string budles
+var bundles  = new Array();
+
+function gettext(key)
+{
+    //dump("\ncallled gettext  bundles.length = " + bundles.length + "\n");
+    var ret = null;
+    for(var i = 0 ; i < bundles.length; i++)
+    {
+        try{
+            ret = bundles[i].getString(key);
+        }
+        catch(e){dump(e); }
+        if (ret != null)
+            break;  
+    }
+    //not found , just return the  orginal string 
+    if (ret == null) 
+        ret = key;
+    //dump(ret + '\n');
+    return ret;
+}
+
+var _ = gettext;
+
+function getformatedtext(key,subs)
+{
+    var ret = null;
+    for(var i = 0 ; i < bundles.length; i++)
+    {
+        try{
+            ret = bundles[i].getString(key);
+            if (ret != null)
+            {
+                return bundles[i].getFormattedString(key,subs);
+            }
+        }
+        catch(e){}
+    }
+    //not found , just return the   orginal string 
+    if (ret == null) 
+        ret = key;
+    return ret;
+}
+
+var _f = getformatedtext;
+
+function initBundles(){
+    bundles.push(document.getElementById('beagleStrings'));
+}
+
+window.addEventListener('load', initBundles, false); 
+
+

Added: trunk/extensions/firefox-extension/chrome/content/indexBookmark.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/indexBookmark.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,207 @@
+/**
+* index bookmarks.
+* Include URL,name,shorcurURL (the keywords), description
+* After index, a last-indexed-date is saved.
+* Later only index the modified bookmark or new bookmarks.
+*/
+
+
+//Used to include only one time bookmark.js and avoid error message about already specified constant
+try{
+    if(ADD_BM_DIALOG_FEATURES) {}
+} catch(e){
+    var loader =  Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+		    .getService(Components.interfaces.mozIJSSubScriptLoader);
+    loader.loadSubScript("chrome://browser/content/bookmarks/bookmarks.js");
+}
+if(!BMDS)
+{
+    //init bookmark js service
+    initServices();
+    initBMService();
+}
+
+/**
+ * a class for Bookmark
+ */
+function Bookmark(bmRes,path)
+{
+    this.bmRes = bmRes;
+    this.URL = this.getLiteral(this.URLArc);
+    this.Name = this.getLiteral(this.NameArc);
+    this.ShortcutURL = this.getLiteral(this.ShorcurURLArc);
+    this.Description = this.getLiteral(this.DescriptionArc);
+    this.LastModifiedDate = this.getDate(this.LastModifiedDateArc);
+    this.LastVisitDate = this.getDate(this.LastVisitDateArc);
+    this.BookmarkAddDate = this.getDate(this.BookmarkAddDateArc);
+    this.type = BookmarksUtils.resolveType(this.bmRes);
+    this.path = path; 
+}
+
+Bookmark.prototype = {
+    URLArc:             RDF.GetResource(gNC_NS + "URL"),
+    //FeedURLArc:         RDF.GetResource(gNCNS + "FeedURL",
+    NameArc:            RDF.GetResource(gNC_NS + "Name"),
+    ShortcutURLArc:     RDF.GetResource(gNC_NS + "ShortcutURL"),
+    DescriptionArc:     RDF.GetResource(gNC_NS + "Description"),
+    LastModifiedDateArc:RDF.GetResource(gWEB_NS + "LastModifiedDate"),
+    LastVisitDateArc:   RDF.GetResource(gWEB_NS + "LastVisitDate"),
+    BookmarkAddDateArc:   RDF.GetResource(gNC_NS + "BookmarkAddDate"),
+    
+    /**
+     * is bookmark newer than lastIndexDate
+     */
+    isModified: function(lastIndexDate)
+    {   
+        var last_modified = this.LastModifiedDate;
+        if (!last_modified)
+            last_modified = this.BookmarkAddDate;
+        return last_modified && last_modified > lastIndexDate;
+    },
+
+    /**
+     * folder / seperator / livebookmark  are not "bookmark"
+     */
+    isBookmark: function()
+    {
+        var parent = BMSVC.getParent(this.bmRes);
+        if (parent) 
+            var type = BookmarksUtils.resolveType(parent);
+        if (type == "Livemark") 
+            return false;
+        return !!this.URL;
+    },
+
+    getLiteral:function(arc) 
+    {
+        try{
+            var target = BMDS.GetTarget(this.bmRes, arc, true);          
+            if (target) {
+                   return target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
+            }
+        } catch (e) { /* probably a bad interface */ }
+        return null;
+    },
+
+    getDate:function(arc) 
+    {
+        try{
+            var target = BMDS.GetTarget(this.bmRes, arc, true);          
+            if (target) {
+                   return target.QueryInterface(Components.interfaces.nsIRDFDate).Value/1000;
+            }
+        } catch (e) { /* probably a bad interface */ }
+        return null;
+    },
+
+    /**
+     * get children bookmarks 
+     */
+    getChildren:function()
+    {
+        var container = Components.classes["@mozilla.org/rdf/container;1"]
+                    .createInstance(Components.interfaces.nsIRDFContainer);
+        container.Init(BMDS, this.bmRes);
+        var bookmarks = new Array();
+        var elements = container.GetElements();
+        while (elements.hasMoreElements()) {
+            var element = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
+            bookmarks.push(new Bookmark(element,this.path + " " + this.Name))
+        }
+        return bookmarks;
+    }
+
+}
+
+var bookmarkIndexer = {
+    
+    /**
+     * get the bookmark  one by one 
+     * if filter(bookmark) == true do action(bookmark)
+     * return the num of indexed bookmarks
+     */
+    walk: function(bm,filter,action)
+    {
+        var num = 0;
+        switch(bm.type)
+        {
+        //folder. walk it's chidren
+        case "Folder":
+        case "PersonalToolbarFolder":
+        case "IEFavoriteFolder":
+            var children = bm.getChildren();
+            for(var i = 0; i < children.length; i++)
+                num += this.walk(children[i],filter,action);
+            break;
+        default:
+            if(filter.call(null,bm))
+            {
+                action.call(null,bm);
+                num ++;
+            }
+            break;
+        }
+        return num;
+    },
+    
+    /**
+     * Index a bookmark.
+     * write meta to metafile and write a empty content file
+     */
+    indexBookmark: function(bookmark)
+    {
+        log("index bookmark " + bookmark.URL );
+        var meta = [
+            bookmark.URL,
+            "FirefoxBookmark",
+            "text/plain", //TODO what the content type should be 
+            "t:name=" + bookmark.Name,
+            "t:path=" + bookmark.path,
+        ];
+        if(bookmark.Description)
+            meta.push("t:description=" + bookmark.Description);
+        if(bookmark.ShortcutURL)
+            meta.push("t:shortcuturl=" + bookmark.ShortcutURL);
+        //if(bookmark.LastModifiedDate)
+        //    meta.push("k:lastmodifieddate=" + bookmark.LastModifiedDate);
+        //if(bookmark.LastVisitDate)
+        //    meta.push("k:lastvisitdate=" + bookmark.LastVisitDate);
+        beagle.writeRawMetadata(meta,beagle.getMetaPath(bookmark.URL,"bookmark"));
+        // a little hack , write empty content to content file
+        beagle.writeRawMetadata([],beagle.getContentPath(bookmark.URL,"bookmark"));
+    },
+    
+    /**
+     * Index all the bookmarks. 
+     * It is not used.
+     */
+    indexAll:function()
+    {
+        this.walk(
+            function(bookmark){return bookmark.isBookmark();}, 
+            this.indexBookmark
+        );
+        beaglePref.set("beagle.bookmark.last.indexed.date","" + (new Date()).getTime());
+    },
+    
+    /**
+     * Index the modifled (or new ) bookmarks.
+     * if report is true , alert the num of indexed bookmarks
+     */
+    indexModified:function(report)
+    {
+        var root = new Bookmark(RDF.GetResource("NC:BookmarksRoot"),"");
+        var lastIndexDate = beaglePref.get("beagle.bookmark.last.indexed.date");
+        var num = this.walk(
+            root,
+            function(bookmark){return bookmark.isBookmark() && bookmark.isModified(lastIndexDate);},
+            this.indexBookmark
+        );
+        beaglePref.set("beagle.bookmark.last.indexed.date","" + (new Date()).getTime());
+        if(report)
+           alert(_f("beagle_index_bookmark_finish",[num]));
+        log(_f("beagle_index_bookmark_finish",[num]));
+    }
+}
+
+

Added: trunk/extensions/firefox-extension/chrome/content/indexLink.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/indexLink.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,338 @@
+/**
+ * a browser used to download the link/image and index it
+ */
+
+beagleInvisibleBrowser = {
+
+    get ELEMENT() { return document.getElementById("beagle-invisible-browser"); },
+    
+    get STATUS_ELEMENT() { return document.getElementById("beagle-index-link-status");},
+    
+    get START_BUTTON() { return document.getElementById("beagle-index-link-start");},
+    
+    get STOP_BUTTON() { return document.getElementById("beagle-index-link-stop");},
+    
+    currentURL: null,
+
+    referrer : null, 
+
+    currentContentType:null,
+    
+    isDocument:null,
+    
+    sniffer: null,
+    
+    persist : null, 
+   
+    /**
+     * get current URL . It might be differen't with this.currentURL
+     * because of meta redirection / javascript redirection
+     */
+    getCurrentURL : function()
+    {
+        if(this.isDocument)
+        {
+            return this.ELEMENT.currentURI.spec;
+        }
+        else
+            return this.currentURL;
+    },
+    /**
+     * connect to sever
+     * sniff the contentType 
+     */
+	connect : function(url,referrer)
+	{
+        this.currentURL = url;
+        this.referrer = referrer;
+        this.sniffer = new headerSniffer(
+            url,
+            referrer,
+            Function.bind(this.onGetContentType,this),
+            Function.bind(this.onGetResponseError,this)
+        );
+        this.sniffer.httpHead();
+        this.STATUS_ELEMENT.value = _f("beagle_index_link_connect",[url]);
+    },
+
+    /**
+     * for non-html file . save it (to ~/.beagle/ToIndex)
+     */
+    save : function(url,path)
+    {
+        window.opener.beagle.saveFile(url,path,this);
+    },
+
+    /**
+     * for html/xml file . load it  (and then index the DOM)
+     * TODO: more thing can be just do once ? not every time
+     * TODO: what allow ? 
+     */
+	load : function(url,referrer)
+	{
+        try{
+            this.ELEMENT.webProgress.addProgressListener(this, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
+        }
+        catch(ex){log(ex)};
+        this.ELEMENT._load_cb = Function.bind(this.doIndex,this);
+        this.ELEMENT.addEventListener("load", this.ELEMENT._load_cb, true);
+		this.ELEMENT.docShell.allowJavascript = true;
+		this.ELEMENT.docShell.allowImages     = false;
+		this.ELEMENT.docShell.allowMetaRedirects = true;
+		this.ELEMENT.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).useGlobalHistory = false;
+		this.ELEMENT.loadURI(url,null, null);
+	},
+
+    /**
+     * called when the start button is clicked
+     * TODO:shall we re-sniff when reload?
+     */
+    reload : function()
+    {
+        this.START_BUTTON.disabled=true;
+        this.STOP_BUTTON.disabled=false;
+        this.connect(this.currentURL,this.referrer);
+    },
+
+    /**
+     * called when the stop button is clicked
+     */
+    stop : function()
+    {
+        this.START_BUTTON.disabled=false;
+        this.STOP_BUTTON.disabled=true;
+		this.STATUS_ELEMENT.value = _("beagle_index_link_stop");
+        
+        if(this.currentContentType == null)  //not get contenttype yet
+        {
+            this.sniffer.cancel();
+            return;
+        }
+        if(this.isDocument)
+        {
+            this.ELEMENT.stop();
+            this.ELEMENT.removeEventListener('load',this.ELEMENT._load_cb,true);
+        }
+        else
+        {
+            
+            this.persist.progressListener =  null;
+            this.persist.cancelSave();
+            //if we cancel save . It's our responsibility to clean the tmp file
+            try{
+                var tmpfile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+                tmpfile.initWithPath(window.opener.beagle.getContentPath(this.currentURL));
+                tmpfile.remove(false);
+            }
+            catch(ex){ log(ex);}
+        }
+        this.currentContentType = null;
+    },
+
+    /**
+     * call window.opener.beagle to index the file/document
+     */
+	doIndex : function()
+	{
+        this.STOP_BUTTON.disabled=true;
+		this.STATUS_ELEMENT.value = _f("beagle_index_link_saving",[this.getCurrentURL()]);
+        window.opener.beagle.onLinkLoad(
+            this.getCurrentURL(),
+            this.currentContentType,
+            this.ELEMENT.contentDocument,
+            window.arguments[0]);
+        window.close();
+	},
+
+	QueryInterface : function(aIID)
+	{
+		if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
+			aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+			aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
+			aIID.equals(Components.interfaces.nsISupports))
+			return this;
+		throw Components.results.NS_NOINTERFACE;
+	},
+
+    /***************************************************************
+     * the five functions below is progresslistener interface 
+     ***************************************************************/
+
+	onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
+	{
+        //alert(aStateFlags);
+		if ( aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START )
+		{
+			this.STATUS_ELEMENT.value = _f("beagle_index_link_start",[this.currentURL]);
+		}
+		if ( !this.isDocument && aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP )
+        {
+            this.STATUS_ELEMENT.value = _f("beagle_index_link_saving",[this.currentURL]);
+            window.opener.beagle.onLinkLoad(this.currentURL,this.currentContentType,null,window.arguments[0]);
+            window.close();
+        }
+	},
+
+	onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
+	{
+        if ( aCurTotalProgress != aMaxTotalProgress )
+        {
+            var progress = (aMaxSelfProgress > 0) ? Math.round(aCurSelfProgress / aMaxSelfProgress * 100) + "%" : aCurSelfProgress + "Bytes";
+            this.STATUS_ELEMENT.value = _f("beagle_index_link_progress",[progress,this.currentURL]); 
+        } 
+	},
+
+	onStatusChange   : function() {},
+	onLocationChange : function() {},
+	onSecurityChange : function() {},
+    /**
+     * pass it as a callback to sniffer
+     * when we get the contentType , it is called.
+     */
+    onGetContentType : function(contentType,url)
+    {
+        if(!contentType)
+            contentType ="text/html";
+        this.currentContentType = contentType;
+        this.currentURL = url;
+        if(contentType.match(/(text|html|xml)/i))
+        {   
+            this.isDocument = true;
+            this.load(url,this.referrer);
+        }
+        else
+        {
+            this.isDocument = false;
+            this.save(url,window.opener.beagle.getContentPath(url));
+        }
+    },
+    /**
+     * pass it as a callback to sniffer
+     * when some error occurs, it is called
+     */
+    onGetResponseError : function(msg)
+    {
+        this.STATUS_ELEMENT.value = msg;
+    },
+
+};
+
+
+/**
+ * sniff the head 
+ * here is used to get the mimetype of the given url
+ */
+function headerSniffer(URLSpec, RefURLSpec,onSuccess,onError)
+{
+	this.URLSpec    = URLSpec;
+	this.refURLSpec = RefURLSpec;
+    this.onSuccess = onSuccess;
+    this.onError = onError;
+}
+
+
+headerSniffer.prototype = {
+
+	_URL     : Components.classes['@mozilla.org/network/standard-url;1'].createInstance(Components.interfaces.nsIURL),
+    _IO      : Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService),
+	_channel : null,
+	_headers : null,
+    
+    /**
+     * send http head 
+     */
+	httpHead : function()
+	{
+		this._channel = null;
+		this._headers = {};
+		try {
+			this._URL.spec = this.URLSpec;
+			this._channel = this._IO.newChannelFromURI(this._URL).QueryInterface(Components.interfaces.nsIHttpChannel);
+			this._channel.loadFlags = this._channel.LOAD_BYPASS_CACHE;
+			this._channel.setRequestHeader("User-Agent", navigator.userAgent, false);
+			if ( this.refURLSpec ) this._channel.setRequestHeader("Referer", this.refURLSpec, false);
+		} catch(ex) {
+			this.onError(_("beagle_index_link_invalid_url"));
+		}
+		try {
+			this._channel.requestMethod = "HEAD";
+			this._channel.asyncOpen(this, this);
+		} catch(ex) {
+			this.onError(ex);
+		}
+	},
+
+    /**
+     * cancel sniff 
+     * I didn't find any way to stop the request ?
+     * So here  we will just remove the callback function
+     */
+    cancel : function()
+    {
+        log("sniff canceled");
+        this.onSuccess =  function(){};
+        this.onError = function(){};
+    },
+
+    /**
+     * get response header
+     */
+	getHeader : function(header_name)
+	{
+	 	try { return this._channel.getResponseHeader(header_name); } catch(ex) { return ""; }
+	},
+
+    /**
+     * get http status 
+     */
+	getStatus : function()
+	{
+		try { return this._channel.responseStatus; } catch(ex) { return ""; }
+	},
+	
+    onDataAvailable : function() {},
+	onStartRequest  : function() {},
+	onStopRequest   : function() { this.onHttpSuccess(); },
+    
+    /**
+     * get http reponse successfully 
+     */
+	onHttpSuccess : function()
+	{
+		var contentType = this.getHeader("Content-Type");
+		var httpStatus = this.getStatus();
+		
+        switch ( httpStatus )
+		{
+			case 404 : this.onError(_("beagle_index_link_http_403")); return;
+			case 403 : this.onError(_("beagle_index_link_http_404")); return;
+			case 500 : this.onError(_("beagle_index_link_http_500")); return;
+		}
+
+        //if redirect 
+		var redirectURL = this.getHeader("Location");
+		if ( redirectURL )
+		{
+			if ( redirectURL.indexOf("http") != 0 ) redirectURL = this._URL.resolve(redirectURL);
+			//re-sniffer 
+            this.URLSpec = redirectURL;
+            this.httpHead();
+			return;
+		}
+        //contenType may looks like text/html; charset=UTF-8
+        //we only need text/html
+        contentType = contentType.split(';',1)[0];
+        log("get contenttype = " + contentType);
+        this.onSuccess(contentType,this.URLSpec);
+        
+	},
+
+};
+
+
+window.onload = function()
+{
+    //window.arguments[0] is the url to load
+    //window.arguments[1] is referrer
+    beagleInvisibleBrowser.connect(window.arguments[0],window.arguments[1]);
+}

Added: trunk/extensions/firefox-extension/chrome/content/indexLink.xul
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/indexLink.xul	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+<!DOCTYPE window SYSTEM "chrome://beagle/locale/beagle.dtd">
+
+<window id="beagle-index-link"
+    title="Beagle Index "
+    style="width:400px" 
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";>
+    
+<stringbundleset id="stringbundleset">
+     <stringbundle id="beagleStrings"
+         src="chrome://beagle/locale/beagle.properties"/>
+</stringbundleset>
+
+<script type="application/x-javascript" 
+		src="chrome://beagle/content/i18n.js" />
+<script type="application/x-javascript" 
+		src="chrome://beagle/content/utils.js" />
+<script type="application/x-javascript" 
+		src="chrome://beagle/content/indexLink.js" />
+
+<textbox id="beagle-index-link-status" readonly="true" value="" />
+<hbox>
+    <button id="beagle-index-link-start" label="&beagle.index.link.start.label;" 
+        oncommand="beagleInvisibleBrowser.reload();" disabled="true"/>
+    <button id="beagle-index-link-stop" label="&beagle.index.link.stop.label;"  
+        oncommand="beagleInvisibleBrowser.stop();" />
+</hbox>
+
+<browser id="beagle-invisible-browser" type="content" collapsed="true"/>
+
+</window> 

Added: trunk/extensions/firefox-extension/chrome/content/jslib/debug/debug.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/debug/debug.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,156 @@
+/*
+
+The contents of this file are subject to the Mozilla Public
+License Version 1.1 (the "License"); you may not use this file
+except in compliance with the License. You may obtain a copy of
+the License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS
+IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+implied. See the License for the specific language governing
+rights and limitations under the License.
+
+The Original Code is jslib team code.
+The Initial Developer of the Original Code is jslib team.
+
+Portions created by jslib team are
+Copyright (C) 2000 jslib team.  All
+Rights Reserved.
+
+Original Author: Pete Collins <pete mozdev org>
+Contributor(s):
+  Henrik Gemal <http://gemal.dk>
+*/
+
+/************** DUBUG ******************/
+if (typeof(JS_LIB_LOADED) == "boolean") 
+{
+
+  const JS_DEBUG_LOADED = true;
+  const JS_DEBUG_FILE = "debug.js";
+
+  /****************************************************************
+  * void jslibDebug(aOutString)                                   *
+  * aOutString is an argument of string debug message             *
+  * returns void                                                  *
+  *   eg:                                                         * 
+  *       var msg="Testing function";                             *
+  *       jslibDebug(msg);                                        *
+  *                                                               *
+  *   outputs: Testing function                                   *
+  ****************************************************************/
+
+  // DEPRECATED 
+  function jslib_debug(aOutString) { return jslibDebug(aOutString); }
+
+  function jslibDebug(aOutString) 
+  {
+    if (!JS_LIB_DEBUG)
+      return; 
+
+    if (JS_LIB_DEBUG_ALERT)
+      alert(aOutString);
+
+    dump(aOutString+'\n');
+  }
+
+  // print to stdout
+  function jslibPrint(aOutString) 
+  {
+    dump(aOutString+'\n');
+  }
+
+  // print to stdout
+  function jslibPrintDebug(aMsg, aOutString) 
+  {
+    if (!aMsg) aMsg = "JSLIB_DEBUG: ";
+    dump(aMsg+aOutString+'\n');
+  }
+
+  // print to stdout
+  function jslibPrintBracket(aOutString) 
+  {
+    dump("["+aOutString+']\n');
+  }
+
+  // print message
+  function jslibPrintMsg(aOutStr1, aOutStr2) 
+  {
+    dump(aOutStr1+": "+aOutStr2+"\n");
+  }
+
+
+  /****************************************************************
+  * void jslibError(e, aType, aResults, aCaller)                  *
+  * e        - argument of results exception                      *
+  * aType    - argument of string error type message              *
+  * aResults - argument of string Components.results name         *
+  * aCaller  - argument of string caller filename and func name   *
+  * returns void                                                  *
+  *   Ex:                                                         * 
+  *       jslibError(null, "Missing file path argument\n",        *
+  *                 "NS_ERROR_XPC_NOT_ENOUGH_ARGS",               *
+  *                 JS_LIB_FILE+": include");                     *
+  *                                                               *
+  *   outputs:                                                    *
+  *       -----======[ ERROR ]=====-----                          *
+  *       Error in jslib.js: include:  Missing file path argument *
+  *                                                               *
+  *       NS_ERROR_NUMBER:   NS_ERROR_XPC_NOT_ENOUGH_ARGS         *
+  *       ------------------------------                          *
+  *                                                               *
+  ****************************************************************/
+
+  function jslibError(e) 
+  {
+		var rv = null;
+    var errMsg="";
+    if (typeof(e) == 'object') {
+      var m, n, r, l, ln, fn = "";
+      try {
+        rv = e.result;
+        m  = e.message;
+        fn = e.filename;
+        l  = e.location; 
+        ln = l.lineNumber; 
+      } catch (e) {}
+      errMsg+="FileName:          "+fn+"\n"           +
+              "Result:            "+rv+"\n"           +
+              "Message:           "+m+"\n"            +
+              "LineNumber:        "+ln+"\n";
+    }
+
+    errMsg = "\n-----======[ jsLib ERROR ]=====-----\n" + errMsg;
+    errMsg += "-------------------------------------\n";
+
+    jslibDebug(errMsg);
+
+		return rv;
+  }
+
+	function jslibErrorMsg (e)
+	{
+		jslibDebug(e);
+		return null;
+	}
+
+	function jslibErrorWarn (e)
+	{
+		jslibDebug("jsLib warn: "+e);
+		return null;
+	}
+
+	function jslibErrorMsg (e)
+	{
+		jslibDebug(e);
+		return jslibRes[e];
+	}
+
+  // Welcome message
+  jslibDebug('*** load: '+JS_DEBUG_FILE+' OK');
+  jslibDebug(JS_LIB_HELP);
+  jslibDebug("\n\n*********************\nJS_LIB DEBUG IS ON\n*********************\n\n");
+
+} 
+                                                                                                    
+

Added: trunk/extensions/firefox-extension/chrome/content/jslib/io/dir.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/io/dir.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,231 @@
+/*** -*- Mode: Javascript; tab-width: 2;
+
+The contents of this file are subject to the Mozilla Public
+License Version 1.1 (the "License"); you may not use this file
+except in compliance with the License. You may obtain a copy of
+the License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS
+IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+implied. See the License for the specific language governing
+rights and limitations under the License.
+
+The Original Code is Collabnet code.
+The Initial Developer of the Original Code is Collabnet.
+
+Portions created by Collabnet are Copyright (C) 2000 Collabnet.
+All Rights Reserved.
+
+Contributor(s): Pete Collins, Doug Turner, Brendan Eich, Warren Harris,
+                Eric Plaster, Martin Kutschker
+
+
+JS Directory Class API
+
+  dir.js
+
+Function List
+
+    create(aPermissions);      // permissions are optional
+
+    files();                   // returns an array listing all files of a dirs contents 
+    dirs();                    // returns an array listing all dirs of a dirs contents 
+    list(aDirPath);            // returns an array listing of a dirs contents 
+
+    // help!
+    help();                    // currently dumps a list of available functions 
+
+Instructions:
+
+
+*/
+
+if (typeof(JS_LIB_LOADED)=='boolean') {
+
+/************* INCLUDE FILESYSTEM *****************/
+if(typeof(JS_FILESYSTEM_LOADED)!='boolean')
+  include(jslib_filesystem);
+/************* INCLUDE FILESYSTEM *****************/
+
+
+/****************** Globals **********************/
+const JS_DIR_FILE                    = "dir.js";
+const JS_DIR_LOADED                  = true;
+
+const JS_DIR_LOCAL_CID               = "@mozilla.org/file/local;1";
+const JS_DIR_LOCATOR_PROGID          = '@mozilla.org/filelocator;1';
+const JS_DIR_CID                     = "@mozilla.org/file/directory_service;1";
+
+const JS_DIR_I_LOCAL_FILE            = "nsILocalFile";
+const JS_DIR_INIT_W_PATH             = "initWithPath";
+
+const JS_DIR_PREFS_DIR               = 65539;
+
+const JS_DIR_DIRECTORY               = 0x01;     // 1
+const JS_DIR_OK                      = true;
+
+const JS_DIR_DEFAULT_PERMS           = 0766;
+
+const JS_DIR_FilePath                = new C.Constructor(JS_DIR_LOCAL_CID, 
+                                                   JS_DIR_I_LOCAL_FILE, 
+                                                   JS_DIR_INIT_W_PATH);
+/****************** Globals **********************/
+
+/****************** Dir Object Class *********************/
+// constructor
+function Dir(aPath) {
+
+  if(!aPath) {
+    jslibError(null,
+              "Please enter a local file path to initialize",
+              "NS_ERROR_XPC_NOT_ENOUGH_ARGS", JS_DIR_FILE);
+    throw C.results.NS_ERROR_XPC_NOT_ENOUGH_ARGS;
+  }
+
+  return this.initPath(arguments);
+} // end constructor
+
+Dir.prototype = new FileSystem;
+Dir.prototype.fileInst = null;
+
+/********************* CREATE ****************************/
+Dir.prototype.create = function(aPermissions) 
+{
+  if(!this.mPath) {
+    jslibError(null, "create (no file path defined)", "NS_ERROR_NOT_INITIALIZED");
+    return C.results.NS_ERROR_NOT_INITIALIZED;
+  }
+
+  if(this.exists()) {
+    jslibError(null, "(Dir already exists", "NS_ERROR_FAILURE", JS_DIR_FILE+":create");
+    return null;
+  }
+
+  if (typeof(aPermissions) == "number") {
+    var checkPerms = this.validatePermissions(aPermissions);
+
+    if(!checkPerms) {
+      jslibError(null, "create (invalid permissions)", 
+                       "NS_ERROR_INVALID_ARG", JS_DIR_FILE+":create");
+      return C.results.NS_ERROR_INVALID_ARG;
+    }               
+  } else {
+    checkPerms = this.mFileInst.parent.permissions;
+  }
+
+  var rv = null;
+
+  try {
+    rv=this.mFileInst.create(JS_DIR_DIRECTORY, checkPerms);
+  } catch (e) { 
+    jslibError(e, "(unable to create)", "NS_ERROR_FAILURE", JS_DIR_FILE+":create");
+    rv=null;
+  }
+
+  return rv;
+};
+
+/********************* READDIR **************************/
+Dir.prototype.readDir = function ()
+{
+
+  if(!this.exists()) {
+    jslibError(null, "(Dir already exists", "NS_ERROR_FAILURE", JS_DIR_FILE+":readDir");
+    return null;
+  }
+
+  var rv=null;
+
+  try {
+    if(!this.isDir()) {
+      jslibError(null, "(file is not a directory)", "NS_ERROR_FAILURE", JS_DIR_FILE+":readDir");
+      return null;
+    }
+
+    var files     = this.mFileInst.directoryEntries;
+    var listings  = new Array();
+    var file;
+
+    if(typeof(JS_FILE_LOADED)!='boolean')
+      include(JS_LIB_PATH+'io/file.js');
+
+    while(files.hasMoreElements()) {
+      file = files.getNext().QueryInterface(C.interfaces.nsILocalFile);
+      if(file.isFile())
+        listings.push(new File(file.path));
+
+      if(file.isDirectory())
+        listings.push(new Dir(file.path));
+    }
+
+    rv=listings;
+  } catch(e) { 
+    jslibError(e, "(unexpected error)", "NS_ERROR_UNEXPECTED", JS_FILE_FILE+":readDir");
+    rv=null;
+  }
+
+  return rv;
+};
+
+/********************* REMOVE *******************************/
+Dir.prototype.remove = function (aRecursive)
+{
+
+  if(typeof(aRecursive)!='boolean')
+    aRecursive=false;
+
+  if(!this.checkInst())
+    throw C.results.NS_ERROR_NOT_INITIALIZED;
+
+  if(!this.mPath)
+  {
+    jslibError(null, "remove (no path defined)", 
+                     "NS_ERROR_INVALID_ARG", JS_DIR_FILE+":remove");
+    return null;
+  }
+
+  var rv=null
+
+  try { 
+    if(!this.exists()) {
+      jslibError(null, "(directory doesn't exist)", "NS_ERROR_FAILURE", JS_DIR_FILE+":remove");
+      return null;
+    }
+
+    if(!this.isDir()) {
+      jslibError(null, "(file is not a directory)", "NS_ERROR_FAILURE", JS_DIR_FILE+":remove");
+      return null;
+    }
+
+    rv=this.mFileInst.remove(aRecursive);
+  } catch (e) { 
+    jslibError(e, "(dir not empty, use 'remove(true)' for recursion)", "NS_ERROR_UNEXPECTED", 
+                  JS_DIR_FILE+":remove");
+    rv=null;
+  }
+
+  return rv;
+};
+
+/********************* HELP *****************************/
+Dir.prototype.super_help = FileSystem.prototype.help;
+
+Dir.prototype.__defineGetter__('help', 
+function() {
+  var help = this.super_help()              +
+
+    "   create(aPermissions);\n"            +
+    "   remove(aRecursive);\n"              +
+    "   readDir(aDirPath);\n";
+
+  return help;
+});
+
+jslibDebug('*** load: '+JS_DIR_FILE+' OK');
+
+} else {
+    dump("JSLIB library not loaded:\n"                                  +
+         " \tTo load use: chrome://jslib/content/jslib.js\n"            +
+         " \tThen: include(jslib_dir);\n\n");
+}
+

Added: trunk/extensions/firefox-extension/chrome/content/jslib/io/dirUtils.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/io/dirUtils.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,185 @@
+/*** -*- Mode: Javascript; tab-width: 2;
+
+The contents of this file are subject to the Mozilla Public
+License Version 1.1 (the "License"); you may not use this file
+except in compliance with the License. You may obtain a copy of
+the License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS
+IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+implied. See the License for the specific language governing
+rights and limitations under the License.
+
+The Original Code is Collabnet code.
+The Initial Developer of the Original Code is Collabnet.
+
+Portions created by Collabnet are Copyright (C) 2000 Collabnet.
+All Rights Reserved.
+
+Contributor(s): Pete Collins, Doug Turner, Brendan Eich, Warren Harris,
+                Eric Plaster, Martin Kutschker
+
+
+JS Directory Class API
+
+  dirUtils.js
+
+Function List
+
+
+Instructions:
+
+
+*/
+
+if(typeof(JS_LIB_LOADED)=='boolean') {
+
+const JS_DIRUTILS_FILE              = "dirUtils.js";
+const JS_DIRUTILS_LOADED            = true;
+
+const JS_DIRUTILS_FILE_LOCAL_CID    = "@mozilla.org/file/local;1";
+const JS_DIRUTILS_FILE_DIR_CID      = "@mozilla.org/file/directory_service;1";
+
+const JS_DIRUTILS_FILE_I_LOCAL_FILE = "nsILocalFile";
+const JS_DIRUTILS_INIT_W_PATH       = "initWithPath";
+const JS_DIRUTILS_I_PROPS           = "nsIProperties";
+const JS_DIRUTILS_NSIFILE           = C.interfaces.nsIFile;
+
+const NS_APP_PREFS_50_DIR           = "PrefD"; // /root/.mozilla/Default User/k1m30xaf.slt
+const NS_APP_CHROME_DIR             = "AChrom"; // /usr/src/mozilla/dist/bin/chrome
+const NS_APP_USER_PROFILES_ROOT_DIR = "DefProfRt";  // /root/.mozilla
+const NS_APP_USER_PROFILE_50_DIR    = "ProfD";      // /root/.mozilla/Default User/k1m30xaf.slt
+
+const NS_APP_APPLICATION_REGISTRY_DIR  = "AppRegD"; // /root/.mozilla
+const NS_APP_APPLICATION_REGISTRY_FILE = "AppRegF"; // /root/.mozilla/appreg
+const NS_APP_DEFAULTS_50_DIR           = "DefRt";   // /usr/src/mozilla/dist/bin/defaults 
+const NS_APP_PREF_DEFAULTS_50_DIR      = "PrfDef";  // /usr/src/mozilla/dist/bin/defaults/pref
+const NS_APP_PROFILE_DEFAULTS_50_DIR   = "profDef"; // /usr/src/mozilla/dist/bin/defaults/profile/US
+const NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR = "ProfDefNoLoc"; // /usr/src/mozilla/dist/bin/defaults/profile 
+const NS_APP_RES_DIR                      = "ARes"; // /usr/src/mozilla/dist/bin/res
+const NS_APP_PLUGINS_DIR                  = "APlugns"; // /usr/src/mozilla/dist/bin/plugins
+const NS_APP_SEARCH_DIR                   = "SrchPlugns"; // /usr/src/mozilla/dist/bin/searchplugins
+const NS_APP_PREFS_50_FILE                = "PrefF"; // /root/.mozilla/Default User/k1m30xaf.slt/prefs.js
+const NS_APP_USER_CHROME_DIR              = "UChrm"; // /root/.mozilla/Default User/k1m30xaf.slt/chrome
+const NS_APP_LOCALSTORE_50_FILE           = "LclSt"; // /root/.mozilla/Default User/k1m30xaf.slt/localstore.rdf
+const NS_APP_HISTORY_50_FILE              = "UHist"; // /root/.mozilla/Default User/k1m30xaf.slt/history.dat
+const NS_APP_USER_PANELS_50_FILE          = "UPnls"; // /root/.mozilla/Default User/k1m30xaf.slt/panels.rdf
+const NS_APP_USER_MIMETYPES_50_FILE       = "UMimTyp"; // /root/.mozilla/Default User/k1m30xaf.slt/mimeTypes.rdf
+const NS_APP_BOOKMARKS_50_FILE            = "BMarks"; // /root/.mozilla/Default User/k1m30xaf.slt/bookmarks.html 
+const NS_APP_SEARCH_50_FILE               = "SrchF"; // /root/.mozilla/Default User/k1m30xaf.slt/search.rdf
+const NS_APP_MAIL_50_DIR                  = "MailD"; // /root/.mozilla/Default User/k1m30xaf.slt/Mail
+const NS_APP_IMAP_MAIL_50_DIR             = "IMapMD"; // /root/.mozilla/Default User/k1m30xaf.slt/ImapMail
+const NS_APP_NEWS_50_DIR                  = "NewsD"; // /root/.mozilla/Default User/k1m30xaf.slt/News
+const NS_APP_MESSENGER_FOLDER_CACHE_50_DIR = "MFCaD"; // /root/.mozilla/Default User/k1m30xaf.slt/panacea.dat
+
+// Useful OS System Dirs
+const NS_OS_CURRENT_PROCESS_DIR = "CurProcD"; // /usr/src/mozilla/dist/bin
+const NS_OS_HOME_DIR = "Home"; // /root
+const NS_OS_TEMP_DIR = "TmpD"; // /tmp
+const NS_XPCOM_COMPONENT_DIR = "ComsD"; // /usr/src/mozilla/dist/bin/components
+
+const JS_DIRUTILS_FilePath  = new C.Constructor(JS_DIRUTILS_FILE_LOCAL_CID,
+                                                JS_DIRUTILS_FILE_I_LOCAL_FILE,
+                                                JS_DIRUTILS_INIT_W_PATH);
+
+const JS_DIRUTILS_DIR       = new C.Constructor(JS_DIRUTILS_FILE_DIR_CID,
+                                                JS_DIRUTILS_I_PROPS);
+
+// constructor
+function DirUtils(){}
+
+DirUtils.prototype = {
+
+getPath   : function (aAppID) {
+
+  if(!aAppID) {
+    jslibError(null, "(no arg defined)", "NS_ERROR_INVALID_ARG", JS_FILE_FILE+":getPath");
+    return null;
+  }
+
+  var rv;
+
+  try { 
+    rv=(new JS_DIRUTILS_DIR()).get(aAppID, JS_DIRUTILS_NSIFILE).path; 
+  } catch (e) {
+    jslibError(e, "(unexpected error)", "NS_ERROR_FAILURE", JS_DIRUTILS_FILE+":getPath");
+    rv=null;
+  }
+
+  return rv;
+},
+
+getPrefsDir : function () { return this.getPath(NS_APP_PREFS_50_DIR); },
+getChromeDir : function () { return this.getPath(NS_APP_CHROME_DIR); },
+getMozHomeDir : function () { return this.getPath(NS_APP_USER_PROFILES_ROOT_DIR); },
+getMozUserHomeDir : function () { return this.getPath(NS_APP_USER_PROFILE_50_DIR); },
+getAppRegDir : function () { return this.getPath(NS_APP_APPLICATION_REGISTRY_FILE); },
+getAppDefaultDir : function () { return this.getPath(NS_APP_DEFAULTS_50_DIR); },
+getAppDefaultPrefDir : function () { return this.getPath(NS_APP_PREF_DEFAULTS_50_DIR); },
+getProfileDefaultsLocDir : function () { return this.getPath(NS_APP_PROFILE_DEFAULTS_50_DIR); },
+getProfileDefaultsDir : function () { return this.getPath(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR); },
+getAppResDir : function () { return this.getPath(NS_APP_RES_DIR); },
+getAppPluginsDir : function () { return this.getPath(NS_APP_PLUGINS_DIR); },
+getSearchPluginsDir : function () { return this.getPath(NS_APP_SEARCH_DIR); },
+getPrefsFile : function () { return this.getPath(NS_APP_PREFS_50_FILE); },
+getUserChromeDir : function () { return this.getPath(NS_APP_USER_CHROME_DIR); },
+getLocalStore : function () { return this.getPath(NS_APP_LOCALSTORE_50_FILE); },
+getHistoryFile : function () { return this.getPath(NS_APP_HISTORY_50_FILE); },
+getPanelsFile : function () { return this.getPath(NS_APP_USER_PANELS_50_FILE); },
+getMimeTypes : function () { return this.getPath(NS_APP_USER_MIMETYPES_50_FILE); },
+getBookmarks : function () { return this.getPath(NS_APP_BOOKMARKS_50_FILE); },
+getSearchFile : function () { return this.getPath(NS_APP_SEARCH_50_FILE); },
+getUserMailDir : function () { return this.getPath(NS_APP_MAIL_50_DIR); },
+getUserImapDir : function () { return this.getPath(NS_APP_IMAP_MAIL_50_DIR); },
+getUserNewsDir : function () { return this.getPath(NS_APP_NEWS_50_DIR); },
+getMessengerFolderCache : function () { return this.getPath(NS_APP_MESSENGER_FOLDER_CACHE_50_DIR); },
+getCurProcDir : function () { return this.getPath(NS_OS_CURRENT_PROCESS_DIR); },
+getHomeDir : function () { return this.getPath(NS_OS_HOME_DIR); },
+getTmpDir : function () { return this.getPath(NS_OS_TEMP_DIR); },
+getComponentsDir : function () { return this.getPath(NS_XPCOM_COMPONENT_DIR); },
+
+get help() {
+  const help =
+
+    "\n\nFunction and Attribute List:\n"    +
+    "\n"                                    +
+    "    getPrefsDir()\n"                       +
+    "    getChromeDir()\n"                      +
+    "    getMozHomeDir()\n"                     +
+    "    getMozUserHomeDir()\n"                 +
+    "    getAppRegDir()\n"                      +
+    "    getAppDefaultDir()\n"                  +
+    "    getAppDefaultPrefDir()\n"              +
+    "    getProfileDefaultsLocDir()\n"          +
+    "    getProfileDefaultsDir()\n"             +
+    "    getAppResDir()\n"                      +
+    "    getAppPluginsDir()\n"                  +
+    "    getSearchPluginsDir()\n"               +
+    "    getPrefsFile()\n"                      +
+    "    getUserChromeDir()\n"                  +
+    "    getLocalStore()\n"                     +
+    "    getHistoryFile()\n"                    +
+    "    getPanelsFile()\n"                     +
+    "    getMimeTypes()\n"                      +
+    "    getBookmarks()\n"                      +
+    "    getSearchFile()\n"                     +
+    "    getUserMailDir()\n"                    +
+    "    getUserImapDir()\n"                    +
+    "    getUserNewsDir()\n"                    +
+    "    getMessengerFolderCache()\n\n";
+
+  return help;
+}
+
+}; //END CLASS 
+
+jslibDebug('*** load: '+JS_DIRUTILS_FILE+' OK');
+
+} // END BLOCK JS_LIB_LOADED CHECK
+
+else {
+    dump("JSLIB library not loaded:\n"                                  +
+         " \tTo load use: chrome://jslib/content/jslib.js\n"            +
+         " \tThen: include(jslib_dirutils);\n\n");
+}
+

Added: trunk/extensions/firefox-extension/chrome/content/jslib/io/file.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/io/file.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,771 @@
+/*** -*- Mode: Javascript; tab-width: 2; 
+The contents of this file are subject to the Mozilla Public
+License Version 1.1 (the "License"); you may not use this file
+except in compliance with the License. You may obtain a copy of
+the License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS
+IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+implied. See the License for the specific language governing
+rights and limitations under the License.
+
+The Original Code is jslib code.
+The Initial Developer of the Original Code is jslib team.
+
+Portions created by jslib team are
+Copyright (C) 2000 jslib team.  All
+Rights Reserved.
+
+Contributor(s): Pete Collins, 
+                Doug Turner, 
+                Brendan Eich, 
+                Warren Harris, 
+                Eric Plaster,
+                Martin Kutschker
+
+The purpose of this file is to make it a little easier to use 
+xpcom nsIFile file IO library from js
+
+ File API 
+    file.js
+
+ Base Class:
+    FileSystem
+      filesystem.js
+
+ Function List:
+    // Constructor
+    File(aPath)                         creates the File object and sets the file path
+
+    // file stream methods
+    open(aMode, aPermissions);          open a file handle for reading,
+                                        writing or appending.  permissions are optional.
+    read();                             returns the contents of a file
+    readline();                         returns the next line in the file.
+    EOF;                                boolean check 'end of file' status
+    write(aContents);                   writes the contents out to file.
+    copy(aDest);                        copy the current file to a aDest
+    close();                            closes a file handle
+    create();                           creates a new file if one doesn't already exist
+    exists();                           check to see if a file exists
+
+    // file attributes
+    size;                               read only attribute gets the file size
+    ext;                                read only attribute gets a file extension if there is one
+    permissions;                        attribute gets or sets the files permissions
+    dateModified;                       read only attribute gets last modified date in locale string
+
+    // file path attributes
+    leaf;                               read only attribute gets the file leaf
+    path;                               read only attribute gets the path
+    parent;                             read only attribute gets parent dir part of a path
+
+    // direct manipulation
+    nsIFile                             returns an nsIFile obj
+
+    // utils
+    remove();                           removes the current file
+    append(aLeaf);                      appends a leaf name to the current file
+    appendRelativePath(aRelPath);       appends a relitave path the the current file
+
+    // help!
+    help;                               currently dumps a list of available functions
+
+ Instructions:
+
+       First include this js file in your xul file.  
+       Next, create an File object:
+
+          var file = new File("/path/file.ext");
+
+       To see if the file exists, call the exists() member.  
+       This is a good check before going into some
+       deep code to try and extract information from a non-existant file.
+
+       To open a file for reading<"r">, writing<"w"> or appending<"a">,
+       just call:
+
+          file.open("w", 0644);
+
+       where in this case you will be creating a new file called '/path/file.ext', 
+       with a mode of "w" which means you want to write a new file.
+
+       If you want to read from a file, just call:
+
+          file.open(); or
+          file.open("r");
+          var theFilesContents    = file.read();
+
+          ---- or ----
+
+          while(!file.EOF) {
+            var theFileContentsLine = file.readline();
+            dump("line: "+theFileContentsLine+"\n");
+          }
+
+       The file contents will be returned to the caller so you can do something usefull with it.
+
+          file.close();
+
+       Calling 'close()' destroys any created objects.  If you forget to use file.close() no probs
+       all objects are discarded anyway.
+
+       Warning: these API's are not for religious types
+
+************/
+
+// insure jslib base is loaded
+if (typeof(JS_LIB_LOADED)=='boolean') {
+
+// test to make sure filesystem base class is loaded
+if (typeof(JS_FILESYSTEM_LOADED)!='boolean')
+  include(jslib_filesystem);
+
+/****************** Globals **********************/
+const JS_FILE_LOADED           = true;
+const JS_FILE_FILE             = "file.js";
+
+const JS_FILE_IOSERVICE_CID    = "@mozilla.org/network/io-service;1";
+const JS_FILE_I_STREAM_CID     = "@mozilla.org/scriptableinputstream;1";
+const JS_FILE_OUTSTREAM_CID    = "@mozilla.org/network/file-output-stream;1";
+
+const JS_FILE_F_TRANSPORT_SERVICE_CID  = "@mozilla.org/network/file-transport-service;1";
+
+const JS_FILE_I_IOSERVICE              = C.interfaces.nsIIOService;
+const JS_FILE_I_SCRIPTABLE_IN_STREAM   = "nsIScriptableInputStream";
+const JS_FILE_I_FILE_OUT_STREAM        = C.interfaces.nsIFileOutputStream;
+
+const JS_FILE_READ          = 0x01;  // 1
+const JS_FILE_WRITE         = 0x08;  // 8
+const JS_FILE_APPEND        = 0x10;  // 16
+
+const JS_FILE_READ_MODE     = "r";
+const JS_FILE_WRITE_MODE    = "w";
+const JS_FILE_APPEND_MODE   = "a";
+
+const JS_FILE_FILE_TYPE     = 0x00;  // 0
+
+const JS_FILE_CHUNK         = 1024;  // buffer for readline => set to 1k
+
+const JS_FILE_DEFAULT_PERMS = 0644;
+
+const JS_FILE_OK            = true;
+
+try {
+  const JS_FILE_InputStream  = new C.Constructor
+  (JS_FILE_I_STREAM_CID, JS_FILE_I_SCRIPTABLE_IN_STREAM);
+
+  const JS_FILE_IOSERVICE    = C.classes[JS_FILE_IOSERVICE_CID].
+  getService(JS_FILE_I_IOSERVICE);
+
+} catch (e) {
+  jslibError(e);
+}
+
+/***
+ * Possible values for the ioFlags parameter 
+ * From: 
+ * http://lxr.mozilla.org/seamonkey/source/nsprpub/pr/include/prio.h#601
+ */
+
+
+// #define PR_RDONLY       0x01
+// #define PR_WRONLY       0x02
+// #define PR_RDWR         0x04
+// #define PR_CREATE_FILE  0x08
+// #define PR_APPEND       0x10
+// #define PR_TRUNCATE     0x20
+// #define PR_SYNC         0x40
+// #define PR_EXCL         0x80
+
+const JS_FILE_NS_RDONLY               = 0x01;
+const JS_FILE_NS_WRONLY               = 0x02;
+const JS_FILE_NS_RDWR                 = 0x04;
+const JS_FILE_NS_CREATE_FILE          = 0x08;
+const JS_FILE_NS_APPEND               = 0x10;
+const JS_FILE_NS_TRUNCATE             = 0x20;
+const JS_FILE_NS_SYNC                 = 0x40;
+const JS_FILE_NS_EXCL                 = 0x80;
+/****************** Globals **********************/
+
+
+/****************************************************************
+* void File(aPath)                                              *
+*                                                               *
+* class constructor                                             *
+* aPath is an argument of string local file path                *
+* returns NS_OK on success, exception upon failure              *
+*   Ex:                                                         *
+*     var p = '/tmp/foo.dat';                                   *
+*     var f = new File(p);                                      *
+*                                                               *
+*   outputs: void(null)                                         *
+****************************************************************/
+
+function File(aPath) {
+
+  if (!aPath)
+    return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+
+  return this.initPath(arguments);
+} // constructor
+
+File.prototype = new FileSystem();
+
+// member vars
+File.prototype.mMode        = null;
+File.prototype.mFileChannel = null;
+File.prototype.mTransport   = null;
+File.prototype.mURI         = null;
+File.prototype.mOutStream   = null;
+File.prototype.mInputStream = null;
+File.prototype.mLineBuffer  = null;
+File.prototype.mPosition    = 0;
+
+/********************* OPEN *************************************
+* bool open(aMode, aPerms)                                      *
+*                                                               *
+* opens a file handle to read, write or append                  *
+* aMode is an argument of string 'w', 'a', 'r'                  *
+* returns true on success, null on failure                      *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*                                                               *
+*   outputs: void(null)                                         *
+****************************************************************/
+
+File.prototype.open = function (aMode, aPerms) 
+{
+
+  // close any existing file handles
+  this.close();
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (!this.mPath) 
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (this.exists() && this.mFileInst.isDirectory()) 
+      return jslibErrorMsg("NS_ERROR_FILE_IS_DIRECTORY");
+
+  if (this.mMode) 
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (!this.mURI) {
+    if (!this.exists())
+      this.create();
+    this.mURI = JS_FILE_IOSERVICE.newFileURI(this.mFileInst);
+  }
+
+  if (!aMode)
+    aMode=JS_FILE_READ_MODE;
+
+  this.resetCache();
+  var rv;
+
+  switch (aMode) 
+  {
+    case JS_FILE_WRITE_MODE: 
+    case JS_FILE_APPEND_MODE: {
+      try {
+        if (!this.mFileChannel)
+          this.mFileChannel = JS_FILE_IOSERVICE.newChannelFromURI(this.mURI);
+      } catch (e)    {
+        return jslibError(e);
+      }    
+
+      if (aPerms && !this.validatePermissions(aPerms))
+        jslibErrorMsg("NS_ERROR_INVALID_ARG");
+
+      if (!aPerms)
+        aPerms=JS_FILE_DEFAULT_PERMS;
+
+      try {
+        var offSet=0;
+        if (aMode == JS_FILE_WRITE_MODE) {
+          this.mMode=JS_FILE_WRITE_MODE;
+          // create a filestream
+          var fs = jslibCreateInstance(JS_FILE_OUTSTREAM_CID, JS_FILE_I_FILE_OUT_STREAM);
+
+          fs.init(this.mFileInst, JS_FILE_NS_TRUNCATE | 
+                                  JS_FILE_NS_WRONLY, 00004, null); 
+          this.mOutStream = fs;
+        } else {
+          this.mMode=JS_FILE_APPEND_MODE;
+          // create a filestream
+          fs = jslibCreateInstance(JS_FILE_OUTSTREAM_CID, JS_FILE_I_FILE_OUT_STREAM);
+
+          fs.init(this.mFileInst, JS_FILE_NS_RDWR | 
+                                  JS_FILE_NS_APPEND, 00004, null); 
+          this.mOutStream = fs;
+        }
+      } catch (e) {
+        return jslibError(e);
+      }
+      rv = JS_LIB_OK;
+      break;
+    }
+
+    case JS_FILE_READ_MODE: {
+      if (!this.exists()) 
+        jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+
+      this.mMode=JS_FILE_READ_MODE;
+
+      try {
+        jslibDebug('****** '+this.mURI);
+        this.mFileChannel = JS_FILE_IOSERVICE.newChannelFromURI(this.mURI);
+        this.mInputStream = new JS_FILE_InputStream();    
+        this.mInputStream.init(this.mFileChannel.open());
+        this.mLineBuffer  = new Array();
+        rv = JS_LIB_OK;
+      } catch (e) {
+        rv = jslibError(e);
+      }
+      break;
+    }
+
+    default:
+      rv = jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  }
+  return rv;
+}
+
+/********************* READ *************************************
+* string read()                                                 *
+*                                                               *
+* reads a file if the file is binary it will                    *
+* return type ex: ELF                                           *
+* takes no arguments needs an open read mode filehandle         *
+* returns string on success, null on failure                    *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.open(p);                                                *
+*     f.read();                                                 *
+*                                                               *
+*   outputs: <string contents of foo.dat>                       *
+****************************************************************/
+
+File.prototype.read = function (aSize) 
+{
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (this.mMode != JS_FILE_READ_MODE) {
+    this.close();
+    return jslibErrorMsg("NS_ERROR_NOT_AVAILABLE");
+  }
+
+  var rv = null;
+  try {
+    if (!this.mFileInst || !this.mInputStream) 
+      jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+    rv = this.mInputStream.read(aSize != undefined ? aSize : this.mFileInst.fileSize);
+    this.mInputStream.close();
+  } catch (e) { 
+    rv = jslibError(e);
+  }
+  return rv;
+}
+
+/********************* READLINE**********************************
+* string readline()                                             *
+*                                                               *
+* reads a file if the file is binary it will                    *
+* return type string                                            *
+* takes no arguments needs an open read mode filehandle         *
+* returns string on success, null on failure                    *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.open();                                                 *
+*     while(!f.EOF)                                             *
+*       dump("line: "+f.readline()+"\n");                       *
+*                                                               *
+*   outputs: <string line of foo.dat>                           *
+****************************************************************/
+
+File.prototype.readline = function ()
+{
+
+  if (!this.checkInst() || !this.mInputStream)
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  var rv      = null;
+  var buf     = null;
+  var tmp     = null;
+  try {
+    if (this.mLineBuffer.length < 2) {
+      buf = this.mInputStream.read(JS_FILE_CHUNK);
+      this.mPosition = this.mPosition + JS_FILE_CHUNK;
+      if (this.mPosition > this.mFileInst.fileSize) 
+        this.mPosition  = this.mFileInst.fileSize;
+      if (buf) {
+        if (this.mLineBuffer.length == 1) {
+          tmp = this.mLineBuffer.shift();
+          buf = tmp+buf;
+        }
+        this.mLineBuffer = buf.split(/[\n\r]/);
+      }
+    }
+    rv = this.mLineBuffer.shift();
+  } catch (e) {
+    rv = jslibError(e);
+  }
+  return rv;
+}
+
+/********************* EOF **************************************
+* bool getter EOF()                                             *
+*                                                               *
+* boolean check 'end of file' status                            *
+* return type boolean                                           *
+* takes no arguments needs an open read mode filehandle         *
+* returns true on eof, false when not at eof                    *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.open();                                                 *
+*     while(!f.EOF)                                             *
+*       dump("line: "+f.readline()+"\n");                       *
+*                                                               *
+*   outputs: true or false                                      *
+****************************************************************/
+
+File.prototype.__defineGetter__('EOF', 
+function ()
+{
+  if (!this.checkInst() || !this.mInputStream)
+    throw jslibErrorThrow("NS_ERROR_NOT_INITIALIZED");
+
+  if ((this.mLineBuffer.length > 0) || (this.mInputStream.available() > 0)) 
+    return false;
+  
+  return true;
+})
+
+/********************* WRITE ************************************
+* write()                                                       *
+*                                                               *
+*  Write data to a file                                         *
+*                                                               *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.open("w");                                              *
+*     f.write();                                                *
+*                                                               *
+*   outputs: JS_LIB_OK upon success                             *
+****************************************************************/
+
+File.prototype.write = function (aBuffer)
+{
+
+  if (!aBuffer)
+    return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (this.mMode == JS_FILE_READ_MODE) {
+    this.close();
+    jslibErrorMsg("NS_ERROR_FILE_READ_ONLY");
+  }
+
+  if (!this.mFileInst)
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED")
+
+  var rv = null;
+  try {
+    this.mOutStream.write(aBuffer, aBuffer.length);
+    this.mOutStream.flush();
+    rv = JS_LIB_OK;
+  } catch (e) { 
+    rv = jslibError(e);
+  }
+
+  return rv;
+}
+
+/********************* COPY *************************************
+* void copy(aDest)                                              *
+*                                                               *
+* void file close                                               *
+* return type void(null)                                        *
+* takes no arguments closes an open file stream and             *
+* deletes member var instances of objects                       *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     fopen();                                                  *
+*     f.close();                                                *
+*                                                               *
+*   outputs: JS_LIB_OK upon success                             *
+****************************************************************/
+
+File.prototype.copy = function (aDest)
+{
+
+  if (!aDest)
+    return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (!this.exists()) 
+    return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+
+  var rv = JS_LIB_OK;
+  try {
+    var dest = new JS_FS_File_Path(aDest);
+    var copyName, dir = null;
+
+    if (dest.equals(this.mFileInst)) 
+      return jslibErrorMsg("NS_ERROR_FILE_COPY_OR_MOVE_FAILED");
+
+    if (dest.exists()) 
+      return jslibErrorMsg("NS_ERROR_FILE_ALREADY_EXISTS");
+
+    if (this.mFileInst.isDirectory()) 
+      return jslibErrorMsg("NS_ERROR_FILE_IS_DIRECTORY");
+
+    if (!dest.exists()) {
+      copyName = dest.leafName;
+      dir = dest.parent;
+
+      if (!dir.exists()) 
+        return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+
+      if (!dir.isDirectory()) 
+        return jslibErrorMsg("NS_ERROR_FILE_DESTINATION_NOT_DIR");
+    }
+
+    if (!dir) {
+      dir = dest;
+      if (dest.equals(this.mFileInst)) 
+        return jslibErrorMsg("NS_ERROR_FILE_COPY_OR_MOVE_FAILED");
+    }
+    this.mFileInst.copyTo(dir, copyName);
+    jslibDebug(JS_FILE_FILE+":copy successful!");
+  } catch (e) {
+    rv = jslibError(e);
+  }
+  return rv;
+}
+
+/********************* CLOSE ************************************
+* void close()                                                  *
+*                                                               *
+* void file close                                               *
+* return type void(null)                                        *
+* takes no arguments closes an open file stream and             *
+* deletes member var instances of objects                       *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     fopen();                                                  *
+*     f.close();                                                *
+*                                                               *
+*   outputs: void(null)                                         *
+****************************************************************/
+
+File.prototype.close = function () 
+{
+  /***************** Destroy Instances *********************/
+  if (this.mFileChannel)   delete this.mFileChannel;
+  if (this.mInputStream)   delete this.mInputStream;
+  if (this.mTransport)     delete this.mTransport;
+  if (this.mMode)          this.mMode=null;
+  if (this.mOutStream) {
+    this.mOutStream.close();
+    delete this.mOutStream;
+  }
+  if (this.mLineBuffer)    this.mLineBuffer=null;
+  this.mPosition           = 0;
+  /***************** Destroy Instances *********************/
+
+  return void(null);
+}
+
+/********************* CREATE *****************************/
+File.prototype.create = function ()
+{
+
+  // We can probably implement this so that it can create a 
+  // file or dir if a long non-existent mPath is present
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (this.exists()) 
+    return jslibErrorMsg("NS_ERROR_FILE_ALREADY_EXISTS");
+
+  var rv = null;
+  try { 
+    rv = this.mFileInst.create(JS_FILE_FILE_TYPE, JS_FILE_DEFAULT_PERMS); 
+  } catch (e) {
+    rv = jslibError(e);
+  }
+
+  return rv;
+}
+
+/********************* REMOVE *******************************/
+File.prototype.remove = function ()
+{
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (!this.mPath) 
+    return jslibErrorMsg("NS_ERROR_FILE_INVALID_PATH");
+
+  this.close();
+  var rv;
+  try {
+    // this is a non recursive remove because we are only dealing w/ files.
+    rv = this.mFileInst.remove(false); 
+  } catch (e) {
+    rv = jslibError(e);
+  }
+
+  return rv;
+}
+
+/********************* POS **************************************
+* int getter POS()                                              *
+*                                                               *
+* int file position                                             *
+* return type int                                               *
+* takes no arguments needs an open read mode filehandle         *
+* returns current position, default is 0 set when               *
+* close is called                                               *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.open();                                                 *
+*     while(!f.EOF){                                            *
+*       dump("pos: "+f.pos+"\n");                               *
+*       dump("line: "+f.readline()+"\n");                       *
+*     }                                                         *
+*                                                               *
+*   outputs: int pos                                            *
+****************************************************************/
+
+File.prototype.__defineGetter__('pos', function (){ return this.mPosition; })
+
+/********************* SIZE *************************************
+* int getter size()                                             *
+*                                                               *
+* int file size                                                 *
+* return type int                                               *
+* takes no arguments a getter only                              *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.size;                                                   *
+*                                                               *
+*   outputs: int 16                                             *
+****************************************************************/
+
+File.prototype.__defineGetter__('size',
+function ()
+{
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (!this.mPath) 
+    return jslibErrorMsg("NS_ERROR_FILE_INVALID_PATH");
+
+  if (!this.exists()) 
+    return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+
+  var rv = null;
+  this.resetCache();
+  try { 
+    rv=this.mFileInst.fileSize; 
+  } catch(e) {
+    rv = jslibError(e);
+  }
+
+  return rv;
+}) // END size Getter
+
+/********************* EXTENSION ********************************
+* string getter ext()                                           *
+*                                                               *
+* string file extension                                         *
+* return type string                                            *
+* takes no arguments a getter only                              *
+*   Ex:                                                         *
+*     var p='/tmp/foo.dat';                                     *
+*     var f=new File(p);                                        *
+*     f.ext;                                                    *
+*                                                               *
+*   outputs: dat                                                *
+****************************************************************/
+
+File.prototype.__defineGetter__('ext', 
+function ()
+{
+
+  if (!this.checkInst())
+    return jslibErrorMsg("NS_ERROR_NOT_INITIALIZED");
+
+  if (!this.mPath) 
+    return jslibErrorMsg("NS_ERROR_FILE_INVALID_PATH");
+  
+  if (!this.exists()) 
+    return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+
+  var rv = null;
+  try {
+    var leafName  = this.mFileInst.leafName;
+    var dotIndex  = leafName.lastIndexOf('.');
+    rv=(dotIndex >= 0) ? leafName.substring(dotIndex+1) : "";
+  } catch(e) {
+    rv = jslibError(e);
+  }
+
+  return rv;
+}) // END ext Getter
+
+File.prototype.super_help = FileSystem.prototype.help;
+
+/********************* HELP *****************************/
+File.prototype.__defineGetter__('help', 
+function ()
+{
+  const help = this.super_help()            +
+    "   open(aMode);\n"                     +
+    "   read();\n"                          +
+    "   readline();\n"                      +
+    "   EOF;\n"                             +
+    "   write(aContents, aPermissions);\n"  +
+    "   copy(aDest);\n"                     +
+    "   close();\n"                         +
+    "   create();\n"                        +
+    "   remove();\n"                        +
+    "   size;\n"                            +
+    "   ext;\n"                             +
+    "   help;\n";
+
+  return help;
+})
+
+jslibDebug('*** load: '+JS_FILE_FILE+' OK');
+
+} // END BLOCK JS_LIB_LOADED CHECK
+
+// If jslib base library is not loaded, dump this error.
+else
+{
+    dump("JS_FILE library not loaded:\n"                                +
+         " \tTo load use: chrome://jslib/content/jslib.js\n"            +
+         " \tThen: include(jslib_file);\n\n");
+}

Added: trunk/extensions/firefox-extension/chrome/content/jslib/io/fileUtils.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/io/fileUtils.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,598 @@
+/*** -*- Mode: Javascript; tab-width: 2; -*-
+  
+  The contents of this file are subject to the Mozilla Public
+  License Version 1.1 (the "License"); you may not use this file
+  except in compliance with the License. You may obtain a copy of
+  the License at http://www.mozilla.org/MPL/
+  
+  Software distributed under the License is distributed on an "AS
+  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  implied. See the License for the specific language governing
+  rights and limitations under the License.
+  
+  The Original Code is Collabnet code.
+  The Initial Developer of the Original Code is Collabnet.
+  
+  Portions created by Collabnet are Copyright (C) 2000 Collabnet.
+  All Rights Reserved.
+  
+  Contributor(s): Pete Collins,
+                  Doug Turner,
+                  Brendan Eich,
+                  Warren Harris,
+                  Eric Plaster,
+                  Martin Kutschker
+                  Philip Lindsay
+  
+  
+  JS FileUtils IO API (The purpose of this file is to make it a little easier to do file IO from js) 
+  
+      fileUtils.js
+  
+  Function List
+  
+      chromeToPath(aPath)              // Converts a chrome://bob/content uri to a path.
+                                       // NOTE: although this gives you the
+                                       // path to a file in the chrome directory, you will
+                                       // most likely not have permisions
+                                       // to create or write to files there.
+      chromeToURL(aPath)               // Converts a chrome://bob/content file:// uri.
+      urlToPath(aPath)                 // Converts a file:// url to a path
+      exists(aPath);                   // check to see if a file exists
+      append(aDirPath, aFileName);     // append is for abstracting platform specific file paths
+      remove(aPath);                   // remove a file
+      copy(aSource, aDest);            // copy a file from source to destination
+      leaf(aPath);                     // leaf is the endmost file string
+                                       //  eg: foo.html in /myDir/foo.html
+      permissions(aPath);              // returns the files permissions
+      dateModified(aPath);             // returns the last modified date in locale string
+      size(aPath);                     // returns the file size
+      ext(aPath);                      // returns a file extension if there is one
+      parent(aPath)                    // returns the dir part of a path
+      dirPath(aPath)                   // *Depriciated* use parent 
+      spawn(aPath, aArgs)              // spawns another program 
+      nsIFile(aPath)                   // returns an nsIFile obj 
+      help;                            // currently returns a list of available functions 
+  
+    Deprecated
+  
+      chrome_to_path(aPath);           // synonym for chromeToPath
+      URL_to_path(aPath)               // synonym for use urlToPath
+      rm(aPath);                       // synonym for remove
+      extension(aPath);                // synonym for ext
+  
+  Instructions:
+  
+    First include this js file 
+  
+     var file = new FileUtils();
+  
+    Examples:
+  
+     var path='/usr/X11R6/bin/Eterm';
+     file.spawn(path, ['-e/usr/bin/vi']); 
+     *note* all args passed to spawn must be in the form of an array
+  
+     // to list help
+     dump(file.help);
+  
+    Warning: these API's are not for religious types
+  
+*******************************************/
+  
+  // Make sure jslib is loaded
+  if (typeof(JS_LIB_LOADED)=='boolean')
+  {
+  
+  /****************** Globals **********************/
+  
+  const JS_FILEUTILS_FILE                    = "fileUtils.js";
+  const JS_FILEUTILS_LOADED                  = true;
+  
+  const JS_FILEUTILS_LOCAL_CID               = "@mozilla.org/file/local;1";
+  const JS_FILEUTILS_FILESPEC_PROGID         = '@mozilla.org/filespec;1';
+  const JS_FILEUTILS_NETWORK_STD_CID         = '@mozilla.org/network/standard-url;1';
+  const JS_FILEUTILS_SIMPLEURI_PROGID        = "@mozilla.org/network/simple-uri;1";
+  const JS_FILEUTILS_CHROME_REG_PROGID       = '@mozilla.org/chrome/chrome-registry;1';
+  const JS_FILEUTILS_DR_PROGID               = "@mozilla.org/file/directory_service;1";
+  const JS_FILEUTILS_PROCESS_CID             = "@mozilla.org/process/util;1";
+  
+  const JS_FILEUTILS_I_LOCAL_FILE            = "nsILocalFile";
+  const JS_FILEUTILS_INIT_W_PATH             = "initWithPath";
+  const JS_FILEUTILS_I_PROPS                 = "nsIProperties";
+  
+  const JS_FILEUTILS_CHROME_DIR              = "AChrom";
+  
+  const JS_FILEUTILS_OK                      = true;
+  const JS_FILEUTILS_FilePath                = new C.Constructor(JS_FILEUTILS_LOCAL_CID, 
+                                                                 JS_FILEUTILS_I_LOCAL_FILE, 
+                                                                 JS_FILEUTILS_INIT_W_PATH);
+  
+  
+  /****************** FileUtils Object Class *********************/
+  function FileUtils () 
+  {
+    include (jslib_dirutils);
+    this.mDirUtils = new DirUtils();
+  } // constructor
+  
+  FileUtils.prototype  = 
+  {
+    mFileInst        : null,
+    mDirUtils        : null,
+  
+    /********************* CHROME_TO_PATH ***************************/
+    // this is here for backward compatability but is deprecated --pete
+    chrome_to_path : function (aPath) { return this.chromeToPath(aPath); },
+  
+    chromeToPath : function (aPath) 
+    {
+      if (!aPath)
+        return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+      return this.urlToPath(this.chromeToURL(aPath));
+    },
+  
+    chromeToURL : function (aPath) 
+    {
+      if (!aPath)
+        return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+      var uri = jslibCreateInstance(JS_FILEUTILS_SIMPLEURI_PROGID, "nsIURI");
+  
+      var rv = null;
+      if (/^chrome:/.test(aPath)) {
+        try {
+          var cr        = jslibGetService(JS_FILEUTILS_CHROME_REG_PROGID);
+          if (cr) {
+            cr          = jslibQI(cr, "nsIChromeRegistry");
+            uri.spec    = aPath;
+            uri.spec    = cr.convertChromeURL(uri);
+            rv          = uri.path;
+  
+            // deal w/ jar resource files
+            if (/.jar!/.test(rv)) {
+              rv = rv.replace(/resource:/, "");
+              rv =  "file://"+this.mDirUtils.getCurProcDir()+rv;
+            }
+          }
+        } catch (e) {}
+  
+        if (/^\/|\\|:chrome/.test(rv)) {
+          try {
+            // prepend the system path to this process dir
+            rv = "file:///"+(''+this.mDirUtils.getCurProcDir()+rv)
+                  .replace(/\\/g, "\/").replace(/^\s*\/?/, "").replace(/\ /g, "%20");
+          } catch (e) {
+            rv = jslibError(e);
+          }
+        }
+      } else if (/^file:/.test(aPath)) {
+        rv = this.urlToPath(aPath); 
+      } 
+
+      return rv;
+    },
+  
+    /********************* URL_TO_PATH ***************************/
+    URL_to_path : function (aPath) { return this.urlToPath(aPath); },
+  
+  urlToPath : function (aPath)
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    // xpcshell doesn't have unescape func
+    const hasUnescape = (typeof(unescape)=="function");
+    var path = aPath;
+    var rv;
+  
+    if (/^file:/.test(path)) {
+      try {
+        var uri = jslibCreateInstance(JS_FILEUTILS_NETWORK_STD_CID, "nsIURI");
+        uri.spec = path;
+        rv = uri.path; 
+  
+        var file = jslibCreateInstance(JS_FILEUTILS_LOCAL_CID, "nsILocalFile");
+  
+        // unix and friends
+        try {
+          file.initWithPath(rv);
+          rv = hasUnescape ? unescape(file.path) : file.path;
+          return rv;
+        } catch (e) {}
+  
+        // windows
+        try {
+          file.initWithPath(rv.replace(/^\//,"").replace(/\//g,"\\"));
+          rv = hasUnescape ? unescape(file.path) : file.path;
+          return rv;
+        } catch (e) {}
+  
+        // FIXME: add checking for Mac
+      
+      } catch (e) { 
+        rv = jslibError(e);
+      }
+    }
+  
+    return rv;
+  },
+  
+  /********************* EXISTS ***************************/
+  exists : function (aPath) 
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    var rv;
+    try { 
+      var file = new JS_FILEUTILS_FilePath(aPath);
+      rv = file.exists();
+    } catch (e) { 
+      rv = jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* RM *******************************/
+  rm : function (aPath) { return this.remove(aPath); },
+  
+  remove : function (aPath) 
+  {
+    if (!aPath) 
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath))
+      return jslibErrorMsg("NS_ERROR_FILE_TARGET_DOES_NOT_EXIST");
+  
+    var rv;
+  
+    try { 
+      var fileInst = new JS_FILEUTILS_FilePath(aPath);
+      if (fileInst.isDirectory())
+        return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+      fileInst.remove(false);
+      rv = jslibRes.NS_OK;
+    } catch (e) { 
+      rv = jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* COPY *****************************/
+  copy  : function (aSource, aDest) 
+  {
+    if (!aSource || !aDest) 
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aSource)) 
+      return jslibErrorMsg("NS_ERROR_UNEXPECTED");
+  
+    var rv;
+  
+    try { 
+      var fileInst = new JS_FILEUTILS_FilePath(aSource);
+      var dir      = new JS_FILEUTILS_FilePath(aDest);
+      var copyName = fileInst.leafName;
+  
+      if (fileInst.isDirectory())
+        return jslibErrorMsg("NS_ERROR_FILE_COPY_OR_MOVE_FAILED");
+  
+      if (!this.exists(aDest) || !dir.isDirectory()) {
+        copyName   = dir.leafName;
+        dir        = new JS_FILEUTILS_FilePath(dir.path.replace(copyName,''));
+  
+        if (!this.exists(dir.path)) 
+          return jslibErrorMsg("NS_ERROR_FILE_ALREADY_EXISTS");
+  
+        if (!dir.isDirectory())
+          return jslibErrorMsg("NS_ERROR_FILE_INVALID_PATH");
+      }
+  
+      if (this.exists(this.append(dir.path, copyName))) 
+        return jslibError("NS_ERROR_FILE_ALREADY_EXISTS");
+  
+      rv = fileInst.copyTo(dir, copyName);
+      rv = jslibRes.NS_OK;
+    } catch (e) { 
+      return jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* LEAF *****************************/
+  leaf  : function (aPath) 
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath)) 
+      jslibErrorWarn("NS_ERROR_FILE_NOT_FOUND ["+aPath+"]")
+  
+    var rv;
+  
+    try {
+      var fileInst = new JS_FILEUTILS_FilePath(aPath);
+      rv=fileInst.leafName;
+    }
+  
+    catch (e) { 
+      return jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* APPEND ***************************/
+  append : function (aDirPath, aFileName) 
+  {
+    if (!aDirPath || !aFileName)
+      jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aDirPath)) 
+      return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+    var rv;
+  
+    try { 
+      var fileInst = new JS_FILEUTILS_FilePath(aDirPath);
+      if (fileInst.exists() && !fileInst.isDirectory()) 
+        return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+      fileInst.append(aFileName);
+      rv=fileInst.path;
+      delete fileInst;
+    } catch (e) { 
+      return jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* VALIDATE PERMISSIONS *************/
+  validatePermissions : function(aNum) 
+  {
+    if ( parseInt(aNum.toString(10).length) < 3 ) 
+      return false;
+  
+    return JS_FILEUTILS_OK;
+  },
+  
+  /********************* PERMISSIONS **********************/
+  permissions : function (aPath) 
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath)) 
+      return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+    var rv;
+  
+    try { 
+      rv=(new JS_FILEUTILS_FilePath(aPath)).permissions.toString(8);
+    } catch (e) { 
+      rv = jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* MODIFIED *************************/
+  dateModified  : function (aPath) 
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath)) 
+      jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+    var rv;
+  
+    try { 
+      var date = new Date((new JS_FILEUTILS_FilePath(aPath)).lastModifiedTime).toLocaleString();
+      rv=date;
+    } catch (e) { 
+      rv = jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* SIZE *****************************/
+  size  : function (aPath) 
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath)) 
+      return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+    var rv;
+  
+    try { 
+      rv = (new JS_FILEUTILS_FilePath(aPath)).fileSize;
+    } catch (e) { 
+      jslibError(e);
+      rv=0;
+    }
+  
+    return rv;
+  },
+  
+  /********************* EXTENSION ************************/
+  extension  : function (aPath) { return this.ext(aPath); },
+  
+  ext  : function (aPath)
+  {
+    if (!aPath) 
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath)) 
+      return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+    var rv;
+  
+    try { 
+      var leafName  = (new JS_FILEUTILS_FilePath(aPath)).leafName;
+      var dotIndex  = leafName.lastIndexOf('.'); 
+      rv=(dotIndex >= 0) ? leafName.substring(dotIndex+1) : ""; 
+    } catch (e) { 
+      return jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* DIRPATH **************************/
+  dirPath   : function (aPath) { return this.parent(aPath); }, 
+  
+  parent   : function (aPath) 
+  {
+    if (!aPath)
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    var rv;
+  
+    try { 
+      var fileInst = new JS_FILEUTILS_FilePath(aPath);
+  
+      if (!fileInst.exists()) 
+        return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+      if (fileInst.isFile())
+        rv = fileInst.parent.path;
+  
+      else if (fileInst.isDirectory())
+        rv = fileInst.path;
+  
+      else
+        rv = null;
+    }
+  
+    catch (e) { 
+      return jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* SPAWN ****************************/
+  spawn : function (aPath, aArgs) { this.run(aPath, aArgs); },
+  run : function (aPath, aArgs) 
+  /*
+   * Trys to execute the requested file as a separate *non-blocking* process.
+   * 
+   * Passes the supplied *array* of arguments on the command line if
+   * the OS supports it.
+   *
+   */
+  {
+    if (!aPath) 
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    if (!this.exists(aPath)) 
+      return jslibErrorMsg("NS_ERROR_FILE_NOT_FOUND");
+  
+    var len = 0;
+    if (aArgs)
+      len = aArgs.length;
+    else
+      aArgs = null;
+  
+    var rv;
+    try { 
+      var fileInst = new JS_FILEUTILS_FilePath(aPath);
+  
+      if (!fileInst.isExecutable()) 
+        return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+      if (fileInst.isDirectory())
+        return jslibErrorMsg("NS_ERROR_FILE_IS_DIRECTORY");
+        // Create and execute the process...
+        /*
+         * NOTE: The first argument of the process instance's 'run' method
+         *       below specifies the blocking state (false = non-blocking).
+         *       The last argument, in theory, contains the process ID (PID)
+         *       on return if a variable is supplied--not sure how to implement
+         *       this with JavaScript though.
+         */
+        try {
+          var theProcess = jslibCreateInstance(JS_FILEUTILS_PROCESS_CID, "nsIProcess");
+          
+          theProcess.init(fileInst);
+  
+          rv = theProcess.run(false, aArgs, len);
+          jslib_debug("rv="+rv);
+        } catch (e) {
+          rv = jslibError(e);
+        }
+    } catch (e) { 
+      rv = jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* nsIFILE **************************/
+  nsIFile : function (aPath) 
+  {
+    if (!aPath) 
+      return jslibErrorMsg("NS_ERROR_INVALID_ARG");
+  
+    var rv;
+    try {
+      rv = new JS_FILEUTILS_FilePath(aPath);
+    } catch (e) { 
+      rv = jslibError(e);
+    }
+  
+    return rv;
+  },
+  
+  /********************* HELP *****************************/
+  get help() 
+  {
+    var help =
+  
+      "\n\nFunction List:\n"                  +
+      "\n"                                    +
+      "   exists(aPath);\n"                   +
+      "   chromeToPath(aPath);\n"             +
+      "   chromeToURL(aPath);\n"              +
+      "   urlToPath(aPath);\n"                +
+      "   append(aDirPath, aFileName);\n"     +
+      "   remove(aPath);\n"                   +
+      "   copy(aSource, aDest);\n"            +
+      "   leaf(aPath);\n"                     +
+      "   permissions(aPath);\n"              +
+      "   dateModified(aPath);\n"             +
+      "   size(aPath);\n"                     +
+      "   ext(aPath);\n"                      +
+      "   parent(aPath);\n"                   + 
+      "   run(aPath, aArgs);\n"               + 
+      "   nsIFile(aPath);\n"                  + 
+      "   help;\n";
+  
+    return help;
+  }
+  
+};
+  
+jslibDebug('*** load: '+JS_FILEUTILS_FILE+' OK');
+  
+} // END BLOCK JS_LIB_LOADED CHECK
+  
+// If jslib base library is not loaded, dump this error.
+else
+{
+    dump("JS_FILE library not loaded:\n"                                +
+         " \tTo load use: chrome://jslib/content/jslib.js\n"            +
+         " \tThen: include(jslib_fileutils);\n\n");
+}
+  

Added: trunk/extensions/firefox-extension/chrome/content/jslib/io/filesystem.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/io/filesystem.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,648 @@
+/*** -*- Mode: Javascript; tab-width: 2;
+
+The contents of this file are subject to the Mozilla Public
+License Version 1.1 (the "License"); you may not use this file
+except in compliance with the License. You may obtain a copy of
+the License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS
+IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+implied. See the License for the specific language governing
+rights and limitations under the License.
+
+The Original Code is Collabnet code.
+The Initial Developer of the Original Code is Collabnet.
+
+Portions created by Collabnet are
+Copyright (C) 2000 Collabnet.  All
+Rights Reserved.
+
+Contributor(s): Pete Collins, 
+                Doug Turner, 
+                Brendan Eich, 
+                Warren Harris, 
+                Eric Plaster,
+                Martin Kutschker
+***/
+
+if (typeof(JS_LIB_LOADED)=='boolean') {
+
+/***************************
+* Globals                  *
+***************************/
+
+const JS_FILESYSTEM_LOADED = true;
+const JS_FILESYSTEM_FILE   = "filesystem.js";
+const JS_FS_LOCAL_CID      = "@mozilla.org/file/local;1";
+const JS_FS_DIR_CID        = "@mozilla.org/file/directory_service;1";
+const JS_FS_NETWORK_CID    = '@mozilla.org/network/standard-url;1';
+const JS_FS_URL_COMP       = "nsIURL";
+const JS_FS_I_LOCAL_FILE   = "nsILocalFile";
+const JS_FS_DIR_I_PROPS    = "nsIProperties";
+const JS_FS_INIT_W_PATH    = "initWithPath";
+const JS_FS_CHROME_DIR     = "AChrom";
+const JS_FS_USR_DEFAULT    = "DefProfRt";
+const JS_FS_PREF_DIR       = "PrefD";
+const JS_FS_OK             = true;
+const JS_FS_File_Path      = new Components.Constructor
+  (JS_FS_LOCAL_CID, JS_FS_I_LOCAL_FILE, JS_FS_INIT_W_PATH);
+const JS_FS_Dir            = new Components.Constructor
+  (JS_FS_DIR_CID, JS_FS_DIR_I_PROPS);
+const JS_FS_URL            = new Components.Constructor
+  (JS_FS_NETWORK_CID, JS_FS_URL_COMP);
+
+/***************************
+* Globals                  *
+***************************/
+
+/***************************
+* FileSystem Object Class  *
+***************************/
+function FileSystem(aPath) 
+{
+  return (aPath?this.initPath(arguments):void(null));
+} // constructor
+
+/***************************
+* FileSystem Prototype     *
+***************************/
+FileSystem.prototype  = {
+
+  mPath           : null,
+  mFileInst       : null,
+
+/***************************
+* INIT PATH                *
+***************************/
+initPath : function(args)
+{
+   // check if the argument is a file:// url
+   var fileURL;
+   if(typeof(args)=='object') {
+      for (var i=0; i<args.length; i++) {
+         if(args[i].search(/^file:/) == 0) {
+            try {
+               fileURL= new JS_FS_URL();
+               fileURL.spec=args[i];
+               args[i] = fileURL.path;
+            } catch (e) { 
+               jslibError(e, "(problem getting file instance)", 
+                     "NS_ERROR_UNEXPECTED", JS_FILESYSTEM_FILE+":initPath");
+               rv=null;
+            }
+         }
+      }
+   } else {
+      if(args.search(/^file:/) == 0) {
+         try {
+            fileURL= new JS_FS_URL();
+            fileURL.spec=args;
+            args = fileURL.path;
+         } catch (e) { 
+            jslibError(e, "(problem getting file instance)", 
+                  "NS_ERROR_UNEXPECTED", JS_FILESYSTEM_FILE+":initPath");
+            rv=null;
+         }
+      }
+   }
+
+  /** 
+   * If you are wondering what all this extra cruft is, well
+   * this is here so you can reinitialize 'this' with a new path
+   */
+  var rv = null;
+  try {
+    if (typeof(args)=='object') {
+      this.mFileInst = new JS_FS_File_Path(args[0]?args[0]:this.mPath);
+      if (args.length>1)
+        for (i=1; i<args.length; i++)
+          this.mFileInst.append(args[i]);
+      (args[0] || this.mPath)?rv=this.mPath = this.mFileInst.path:rv=null;
+    } else {
+      this.mFileInst = new JS_FS_File_Path(args?args:this.mPath);
+      this.mFileInst.path?rv=this.mPath = this.mFileInst.path:rv=null;
+    }
+  } catch(e) {
+    jslibError(e?e:null, 
+      "initPath (nsILocalFile problem)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":initPath");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  CHECK INST              *
+***************************/
+checkInst : function () 
+{
+  if (!this.mFileInst) {
+    jslibError(null, 
+      "(no path defined)", 
+      "NS_ERROR_NOT_INITIALIZED", 
+      JS_FILESYSTEM_FILE+":checkInstance");
+    return false;
+  }
+  return true;
+},
+
+/***************************
+*  PATH                    *
+***************************/
+get path() 
+{ 
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  return this.mFileInst.path; 
+},
+
+/***************************
+*  EXISTS                  *
+***************************/
+exists : function ()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  var rv = false;
+  try { 
+    rv = this.mFileInst.exists(); 
+  } catch(e) {
+    jslibError(e, 
+      "exists (nsILocalFile problem)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":exists");
+    rv = false;
+  }
+  return rv;
+},
+
+/***************************
+*  GET LEAF                *
+***************************/
+get leaf()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  var rv = null;
+  try { 
+    rv = this.mFileInst.leafName; 
+  } catch(e) {
+    jslibError(e, 
+      "(problem getting file instance)", 
+      "NS_ERROR_FAILURE", 
+      JS_FILESYSTEM_FILE+":leaf");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  SET LEAF                *
+***************************/
+set leaf(aLeaf)
+{
+  if (!aLeaf) {
+    jslibError(null, 
+      "(missing argument)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":leaf");
+    return null;
+  }
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  var rv = null;
+  try { 
+    rv = (this.mFileInst.leafName=aLeaf); 
+  } catch(e) {
+    jslibError(e, 
+        "(problem getting file instance)", 
+        "NS_ERROR_FAILURE", 
+        JS_FILESYSTEM_FILE+":leaf");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  PARENT                  *
+***************************/
+get parent()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  var rv = null;
+  try { 
+    if (this.mFileInst.parent.isDirectory()) {
+      if (typeof(JS_DIR_LOADED)!='boolean')
+        include(JS_LIB_PATH+'io/dir.js');
+      rv = new Dir(this.mFileInst.parent.path);
+    }
+  } catch (e) {
+    jslibError(e, 
+      "(problem getting file parent)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":parent");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  GET PERMISSIONS         *
+***************************/
+get permissions()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  if (!this.exists()) {
+    jslibError(null, 
+      "(file doesn't exist)", 
+      "NS_ERROR_FAILURE", 
+      JS_FILESYSTEM_FILE+":permisions");
+    return null;
+  }
+  var rv = null;
+  try { 
+    rv = this.mFileInst.permissions.toString(8); 
+  } catch(e) {
+    jslibError(e, 
+                "(problem getting file instance)", 
+                "NS_ERROR_UNEXPECTED", 
+                JS_FILESYSTEM_FILE+":permissions");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  SET PERMISSIONS         *
+***************************/
+set permissions(aPermission)
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+
+  if (!aPermission) {
+    jslibError(null, 
+      "(no new permission defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":permissions");
+    return null;
+  }
+  if (!this.exists()) {
+    jslibError(null, 
+                "(file doesn't exist)", 
+                "NS_ERROR_FAILURE", 
+                JS_FILESYSTEM_FILE+":permisions");
+    return null;
+  }
+  if (!this.validatePermissions(aPermission)) {
+    jslibError(null, 
+                "(invalid permission argument)", 
+                "NS_ERROR_INVALID_ARG", 
+                JS_FILESYSTEM_FILE+":permissions");
+    return null;
+  }
+  var rv = null;
+  try { 
+    rv = this.mFileInst.permissions=aPermission; 
+  } catch(e) {
+    jslibError(e, 
+      "(problem getting file instance)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":permissions");
+    rv = null;
+  }
+  return rv;
+
+},
+
+/***************************
+*  VALIDATE PERMISSIONS    *
+***************************/
+validatePermissions : function (aNum)
+{
+  if (typeof(aNum)!='number')
+    return false;
+  if (parseInt(aNum.toString(10).length) < 3 )
+    return false;
+  return true;
+},
+
+/***************************
+*  MODIFIED                *
+***************************/
+get dateModified()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  if (!this.exists()) {
+    jslibError(null, 
+      "(file doesn't exist)", 
+      "NS_ERROR_FAILURE", 
+      JS_FILESYSTEM_FILE+":dateModified");
+    return null;
+  }
+  var rv = null;
+  try { 
+    rv = (new Date(this.mFileInst.lastModifiedTime)); 
+  } catch(e) {
+    jslibError(e, 
+      "(problem getting file instance)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":dateModified");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  RESET CACHE             *
+***************************/
+resetCache : function()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  var rv = false;
+  if (this.mPath) {
+    delete this.mFileInst;
+    try {
+      this.mFileInst=new JS_FS_File_Path(this.mPath);
+      rv = true;
+    } catch(e) {
+      jslibError(e, 
+        "(unable to get nsILocalFile)", 
+        "NS_ERROR_UNEXPECTED", 
+        JS_FILESYSTEM_FILE+":resetCache");
+      rv = false;
+    }
+  }
+  return rv;
+},
+
+/***************************
+*  nsIFILE                 *
+***************************/
+get nsIFile()
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  var rv = null;
+  try { 
+    rv = this.mFileInst.clone(); 
+  } catch (e) {
+    jslibError(e, 
+      "(problem getting file instance)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":nsIFile");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  NOTE: after a move      *
+*  successful, 'this' will *
+*  be reinitialized        *
+*  to the moved file!      *
+***************************/
+move : function (aDest)
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  if (!aDest) {
+    jslibError(null, 
+      "(no destination path defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":move");
+    return false;
+  }
+  if (!this.mPath) {
+    jslibError(null, 
+      "(no path defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":move");
+    return false;
+  }
+  var rv = null;
+  var newName=null;
+  try {
+    var f = new JS_FS_File_Path(aDest);
+    if (f.exists() && !f.isDirectory()) {
+      jslibError(null, 
+        "(destination file exists remove it)", 
+        "NS_ERROR_INVALID_ARG", 
+        JS_FILESYSTEM_FILE+":move");
+      return false;
+    }
+    if (f.equals(this.mFileInst)) {
+      jslibError(null, 
+        "(destination file is this file)", 
+        "NS_ERROR_INVALID_ARG", 
+        JS_FILESYSTEM_FILE+":move");
+      return false;
+    }
+    if (!f.exists() && f.parent.exists())
+      newName=f.leafName;
+    if (f.equals(this.mFileInst.parent) && !newName) {
+      jslibError(null,  
+        "(destination file is this file)", 
+        "NS_ERROR_INVALID_ARG", 
+        JS_FILESYSTEM_FILE+":move");
+      return false;
+    }
+    var dir=f.parent;
+    if (dir.exists() && dir.isDirectory()) {
+      jslibDebug(newName);
+      this.mFileInst.moveTo(dir, newName);
+      jslibDebug(JS_FILESYSTEM_FILE+':move successful!\n');
+      this.mPath=f.path;
+      this.resetCache();
+      delete dir;
+      rv = true;
+    } else {
+      jslibError(null, 
+        "(destination "+dir.parent.path+" doesn't exists)", 
+        "NS_ERROR_INVALID_ARG", 
+        JS_FILESYSTEM_FILE+":move");
+      return false;
+    }
+  } catch (e) {
+    jslibError(e, 
+      "(problem getting file instance)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":move");
+    rv = false;
+  }
+  return rv;
+},
+
+/***************************
+*  APPEND                  *
+***************************/
+append : function(aLeaf)
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  if (!aLeaf) {
+    jslibError(null, 
+      "(no argument defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":append");
+    return null;
+  }
+  if (!this.mPath) {
+    jslibError(null, 
+      "(no path defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":append");
+    return null;
+  }
+  var rv = null;
+  try {
+    this.mFileInst.append(aLeaf);
+    rv = this.mPath=this.path;
+  } catch(e) {
+    jslibError(null, 
+      "(unexpected error)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":append");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  APPEND RELATIVE         *
+***************************/
+appendRelativePath : function(aRelPath)
+{
+  if (!this.checkInst())
+    throw jslibRes.NS_ERROR_NOT_INITIALIZED;
+  if (!aRelPath) {
+    jslibError(null, 
+      "(no argument defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":appendRelativePath");
+    return null;
+  }
+  if (!this.mPath) {
+    jslibError(null, 
+      "(no path defined)", 
+      "NS_ERROR_INVALID_ARG", 
+      JS_FILESYSTEM_FILE+":appendRelativePath");
+    return null;
+  }
+  var rv = null;
+  try {
+    this.mFileInst.appendRelativePath(aRelPath);
+    rv = this.mPath=this.path;
+  } catch(e) {
+    jslibError(null, 
+      "(unexpected error)", 
+      "NS_ERROR_UNEXPECTED", 
+      JS_FILESYSTEM_FILE+":appendRelativePath");
+    rv = null;
+  }
+  return rv;
+},
+
+/***************************
+*  GET URL                 *
+***************************/
+get URL()
+{
+  return (this.path?'file:///'+this.path.replace(/\\/g, "\/").replace(/^\s*\/?/, "").replace(/\ /g, "%20"):'');
+},
+
+/***************************
+*  ISDIR                   *
+***************************/
+isDir : function()
+{
+  var rv = false;
+  try {
+    rv = this.mFileInst.isDirectory();
+  } catch (e) { rv = false; }
+    
+  return rv;
+},
+
+/***************************
+*  ISFILE                  *
+***************************/
+isFile : function()
+{
+  var rv = false;
+  try {
+    rv = this.mFileInst.isFile();
+  } catch (e) { rv = false; }
+    
+  return rv;
+},
+
+/***************************
+*  ISEXEC                  *  
+***************************/
+isExec : function()
+{
+  var rv = false;
+  try {
+    rv = this.mFileInst.isExecutable();
+  } catch (e) { rv = false; }
+    
+  return rv;
+},
+
+/***************************
+*  ISSYMLINK               *
+***************************/
+isSymlink : function()
+{
+  var rv = false;
+  try {
+    rv = this.mFileInst.isSymlink();
+  } catch (e) { rv = false; }
+    
+  return rv;
+},
+
+/***************************
+*  HELP                    *
+***************************/
+help  : function()
+{
+  const help =
+    "\n\nFunction and Attribute List:\n"    +
+    "\n"                                    +
+    "   initPath(aPath);\n"                 +
+    "   path;\n"                            +
+    "   exists();\n"                        +
+    "   leaf;\n"                            +
+    "   parent;\n"                          +
+    "   permissions;\n"                     +
+    "   dateModified;\n"                    +
+    "   nsIFile;\n"                         +
+    "   move(aDest);\n"                     +
+    "   append(aLeaf);\n"                   +
+    "   appendRelativePath(aRelPath);\n"    +
+    "   URL;\n"                             +
+    "   isDir();\n"                         +
+    "   isFile();\n"                        +
+    "   isExec();\n"                        +
+    "   isSymlink();\n";
+  return help;
+} 
+
+}; // END FileSystem Class
+
+jslibDebug('*** load: '+JS_FILESYSTEM_FILE+' OK');
+
+} // END BLOCK JS_LIB_LOADED CHECK
+
+else {
+    dump("JS_FILE library not loaded:\n"                                +
+         " \tTo load use: chrome://jslib/content/jslib.js\n"            +
+         " \tThen: include(jslib_filesystem);\n\n");
+}

Added: trunk/extensions/firefox-extension/chrome/content/jslib/jslib.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/jslib.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,264 @@
+/*** -*- Mode: Javascript; tab-width: 2;
+
+The contents of this file are subject to the Mozilla Public
+License Version 1.1 (the "License"); you may not use this file
+except in compliance with the License. You may obtain a copy of
+the License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS
+IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+implied. See the License for the specific language governing
+rights and limitations under the License.
+
+The Original Code is jslib team code.
+The Initial Developer of the Original Code is jslib team.
+
+Portions created by jslib team are
+Copyright (C) 2000 jslib team.  All
+Rights Reserved.
+
+Original Author: Pete Collins <pete mozdevgroup com>
+Contributor(s): Martin Kutschker <Martin T Kutschker blackbox net>
+
+***/
+
+/**
+ * insure jslib base is not already loaded
+ */
+if (typeof(JS_LIB_LOADED) != "boolean")
+{
+  try {
+
+  const JS_LIB_LOADED     = true;
+
+  const JS_LIBRARY        = "jslib";
+  const JS_LIB_FILE       = "jslib.js"
+  const JS_LIB_PATH       = "chrome://beagle/content/jslib/";
+  const JS_LIB_VERSION    = "0.1.184-modified";
+  const JS_LIB_AUTHORS    = "\tPete Collins       <pete mozdevgroup com>\n"
+                          + "\tNeil Deakin        <neil mozdevgroup com>\n"
+                          + "\tEric Plaster       <plaster urbanrage com>\n"
+                          + "\tMartin.T.Kutschker <Martin T Kutschker blackbox net>\n";
+  const JS_LIB_BUILD      = "mozilla 1.3+";
+  const JS_LIB_ABOUT      = "\tThis is an effort to provide a fully "
+                          + "functional js library\n"
+                          + "\tfor mozilla package authors to use "
+                          + "in their applications\n";
+  const JS_LIB_HOME       = "http://jslib.mozdev.org/";;
+
+  const ON                = true;
+  const OFF               = false;
+  const C                 = Components;
+  const jslibRes          = C.results;
+  const jslibI            = C.interfaces;
+
+  const JS_LIB_OK         = jslibRes.NS_OK;
+
+  // DEPRICATED
+  const jslib_results     = jslibRes;
+
+  if (typeof(JS_LIB_DEBUG) != "boolean")
+    var JS_LIB_DEBUG      = ON;
+
+  var JS_LIB_DEBUG_ALERT  = OFF;
+  var JS_LIB_ERROR        = ON;
+  var JS_LIB_ERROR_ALERT  = OFF;
+
+  const JS_LIB_HELP       = "\n\nWelcome to jslib version "+JS_LIB_VERSION+"\n\n"
+                          + "Global Constants:\n\n"
+                          + "JS_LIBRARY     \n\t"+JS_LIBRARY     +"\n"
+                          + "JS_LIB_FILE    \n\t"+JS_LIB_FILE    +"\n"
+                          + "JS_LIB_PATH    \n\t"+JS_LIB_PATH    +"\n"
+                          + "JS_LIB_VERSION \n\t"+JS_LIB_VERSION +"\n"
+                          + "JS_LIB_AUTHORS \n"  +JS_LIB_AUTHORS
+                          + "JS_LIB_BUILD   \n\t"+JS_LIB_BUILD   +"\n"
+                          + "JS_LIB_ABOUT   \n"  +JS_LIB_ABOUT
+                          + "JS_LIB_HOME    \n\t"+JS_LIB_HOME    +"\n\n"
+                          + "Global Variables:\n\n"
+                          + "  JS_LIB_DEBUG\n  JS_LIB_ERROR\n\n";
+
+
+  function jslibGetService (aURL, aInterface)
+  {
+    var rv;
+    try {
+      // determine how 'aInterface' is passed and handle accordingly
+      switch (typeof(aInterface))
+      {
+        case "object":
+          rv = C.classes[aURL].getService(aInterface);
+          break;
+
+        case "string":
+          rv = C.classes[aURL].getService(C.interfaces[aInterface]);
+          break;
+
+        default:
+          rv = C.classes[aURL].getService();
+          break;
+      }
+    } catch (e) {
+      rv = -1;
+    }
+    return rv;
+  }
+
+  function jslibCreateInstance (aURL, aInterface)
+  {
+    var rv;
+    try {
+      rv = C.classes[aURL].createInstance(C.interfaces[aInterface]);
+    } catch (e) {
+      rv = -1;
+    }
+    return rv;
+  }
+
+  function jslibGetInterface (aInterface)
+  {
+    var rv;
+    try {
+      rv = C.interfaces[aInterface];
+    } catch (e) {
+      rv = -1;
+    }
+    return rv;
+  }
+
+  function jslibQI (aObj, aInterface)
+  {
+    try {
+      return aObj.QueryInterface(C.interfaces[aInterface]);
+    } catch (e) {
+      throw ("Unable to QI " + aObj + " to " + aInterface);
+    }
+  }
+
+  /****************************************************************
+  * void include(aScriptPath)                                     *
+  * aScriptPath is an argument of string lib chrome path          *
+  * returns NS_OK on success, 1 if file is already loaded and     *
+  * - errorno or throws exception on failure                      *
+  *   eg:                                                         *
+  *       var path='chrome://jslib/content/io/file.js';           *
+  *       include(path);                                          *
+  *  Or:                                                          *
+  *       include(jslib_file);                                    *
+  *                                                               *
+  *   outputs: void(null)                                         *
+  ****************************************************************/
+
+  function include (aScriptPath)
+  {
+    if (!aScriptPath) {
+      dump("include: Missing file path argument\n");
+      throw - jslibRes.NS_ERROR_XPC_NOT_ENOUGH_ARGS;
+    }
+
+    if (aScriptPath == JS_LIB_PATH+JS_LIB_FILE) {
+      dump("include: "+aScriptPath+" is already loaded!\n");
+      throw - jslibRes.NS_ERROR_INVALID_ARG;
+    }
+
+    var start   = aScriptPath.lastIndexOf('/') + 1;
+    var end     = aScriptPath.lastIndexOf('.');
+    var slice   = aScriptPath.length - end;
+    var loadID  = aScriptPath.substring(start, (aScriptPath.length - slice));
+
+    if (typeof(this['JS_'+loadID.toUpperCase()+'_LOADED']) == "boolean")
+      return jslibRes.NS_OK;
+
+    var rv;
+    try {
+      if (jslibNeedsPrivs())
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      jslibGetService("@mozilla.org/moz/jssubscript-loader;1",
+                      "mozIJSSubScriptLoader").loadSubScript(aScriptPath);
+      rv = jslibRes.NS_OK;
+      dump("include: "+aScriptPath+"\n");
+    } catch (e) {
+      const msg = aScriptPath+" is not a valid path or is already loaded\n";
+      dump(e+"\n");
+      dump("include: "+msg+"\n");
+      rv = - jslibRes.NS_ERROR_INVALID_ARG;
+    }
+    return rv;
+  }
+
+  function jslibNeedsPrivs ()
+  {
+    var rv;
+    if (typeof(this.location) == "object") {
+      var proto = this.location.protocol;
+      rv = (proto == "file:")
+    }
+    return rv;
+  }
+
+  // include debug methods
+  const jslib_debug = JS_LIB_PATH+'debug/debug.js';
+  include(jslib_debug);
+
+  function jslibUninstall (aPackage, aCallback)
+  {
+    if (!aPackage)
+      throw - jslibRes.NS_ERROR_INVALID_ARG;
+
+    include (jslib_window);
+    var win = new CommonWindow(null, 400, 400);
+    win.position = JS_MIDDLE_CENTER;
+    win.openUninstallWindow(aPackage, aCallback);
+  }
+
+  /*********** Launch JSLIB Splash ***************/
+  function jslibLaunchSplash ()
+  {
+    include (jslib_window);
+    var win = new CommonWindow("chrome://jslib/content/splash.xul", 400, 220);
+    win.position = JS_MIDDLE_CENTER;
+    win.openSplash();
+  }
+
+  // DEPRICATED
+  function jslib_turnDumpOn () { jslibTurnDumpOn(); }
+
+  function jslibTurnDumpOn ()
+  {
+    include (jslib_prefs);
+    // turn on dump
+    var pref = new Prefs();
+    const prefStr = "browser.dom.window.dump.enabled"
+
+    // turn dump on if not enabled
+    if (!pref.getBool(prefStr)) {
+      pref.setBool(prefStr, true);
+      pref.save();
+    }
+    return;
+  }
+
+  // DEPRICATED
+  function jslib_turnDumpOff () { jslibTurnDumpOff(); }
+
+  function jslibTurnDumpOff ()
+  {
+    include (jslib_prefs);
+    // turn off dump
+    var pref = new Prefs();
+    const prefStr = "browser.dom.window.dump.enabled"
+
+    // turn dump off if enabled
+    if (pref.getBool(prefStr)) {
+      pref.setBool(prefStr, false);
+      pref.save();
+    }
+    return;
+  }
+
+  const jslib_modules = JS_LIB_PATH+'modules.js';
+  include (jslib_modules);
+
+  } catch (e) {}
+
+} // end jslib load test
+

Added: trunk/extensions/firefox-extension/chrome/content/jslib/modules.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/jslib/modules.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,74 @@
+/** 
+ * jslib module identifiers
+ */
+
+const JS_MODULES_LOADED        = true;
+const JS_MODULES_FILE          = "modules.js";
+
+// insure jslib base is loaded
+if (typeof(JS_LIB_LOADED)=='boolean') 
+{
+
+// help identifier
+const jslib_help = "need to write some global help docs here\n";
+
+// Library Identifiers
+
+// io library modules
+const jslib_io         = JS_LIB_PATH+'io/io.js';
+const jslib_filesystem = JS_LIB_PATH+'io/filesystem.js'
+const jslib_file       = JS_LIB_PATH+'io/file.js';
+const jslib_fileutils  = JS_LIB_PATH+'io/fileUtils.js';
+const jslib_dir        = JS_LIB_PATH+'io/dir.js';
+const jslib_dirutils   = JS_LIB_PATH+'io/dirUtils.js';
+
+// data structures
+const jslib_dictionary       = JS_LIB_PATH+'ds/dictionary.js';
+const jslib_chaindictionary  = JS_LIB_PATH+'ds/chainDictionary.js';
+
+// RDF library modules
+const jslib_rdf           = JS_LIB_PATH+'rdf/rdf.js';
+const jslib_rdffile       = JS_LIB_PATH+'rdf/rdfFile.js';
+const jslib_rdfcontainer  = JS_LIB_PATH+'rdf/rdfContainer.js';
+const jslib_rdfresource   = JS_LIB_PATH+'rdf/rdfResource.js';
+const jslib_rdfmemory     = JS_LIB_PATH+'rdf/inMemoryRDF.js';
+
+// network library modules
+const jslib_remotefile  = JS_LIB_PATH+'network/remoteFile.js';
+const jslib_socket      = JS_LIB_PATH+'network/socket.js';
+
+// network - http
+const jslib_http                = JS_LIB_PATH+'network/http.js';
+const jslib_getrequest          = JS_LIB_PATH+'network/getRequest.js';
+const jslib_postrequest         = JS_LIB_PATH+'network/postRequest.js';
+const jslib_multipartrequest    = JS_LIB_PATH+'network/multipartRequest.js';
+const jslib_filepart            = JS_LIB_PATH+'network/parts/filePart.js';
+const jslib_textpart            = JS_LIB_PATH+'network/parts/textPart.js';
+const jslib_urlparameterspart   = JS_LIB_PATH+'network/parts/urlParametersPart.js';
+const jslib_bodyparameterspart  = JS_LIB_PATH+'network/parts/bodyParametersPart.js';
+
+// xul dom library modules
+const jslib_dialog      = JS_LIB_PATH+'xul/commonDialog.js';
+const jslib_filepicker  = JS_LIB_PATH+'xul/commonFilePicker.js';
+const jslib_window      = JS_LIB_PATH+'xul/commonWindow.js';
+const jslib_routines    = JS_LIB_PATH+'xul/appRoutines.js';
+
+// sound library modules
+const jslib_sound = JS_LIB_PATH+'sound/sound.js';
+
+// utils library modules
+const jslib_date     = JS_LIB_PATH+'utils/date.js';
+const jslib_prefs    = JS_LIB_PATH+'utils/prefs.js';
+const jslib_validate = JS_LIB_PATH+'utils/validate.js';
+const jslib_sax      = JS_LIB_PATH+'utils/sax.js';
+
+// zip
+const jslib_zip  = JS_LIB_PATH+'zip/zip.js';
+
+// install/uninstall
+const jslib_install    = JS_LIB_PATH+'install/install.js';
+const jslib_uninstall  = JS_LIB_PATH+'install/uninstall.js';
+const jslib_autoupdate = JS_LIB_PATH+'install/autoupdate.js';
+
+}
+

Added: trunk/extensions/firefox-extension/chrome/content/json.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/json.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,287 @@
+/*
+    json.js
+    2007-04-30
+
+    Public Domain
+
+    This file adds these methods to JavaScript:
+
+        array.toJSONString()
+        boolean.toJSONString()
+        date.toJSONString()
+        number.toJSONString()
+        object.toJSONString()
+        string.toJSONString()
+            These methods produce a JSON text from a JavaScript value.
+            It must not contain any cyclical references. Illegal values
+            will be excluded.
+
+            The default conversion for dates is to an ISO string. You can
+            add a toJSONString method to any date object to get a different
+            representation.
+
+        string.parseJSON(filter)
+            This method parses a JSON text to produce an object or
+            array. It can throw a SyntaxError exception.
+
+            The optional filter parameter is a function which can filter and
+            transform the results. It receives each of the keys and values, and
+            its return value is used instead of the original value. If it
+            returns what it received, then structure is not modified. If it
+            returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. If a key contains the string 'date' then
+            // convert the value to a date.
+
+            myData = text.parseJSON(function (key, value) {
+                return key.indexOf('date') >= 0 ? new Date(value) : value;
+            });
+
+    It is expected that these methods will formally become part of the
+    JavaScript Programming Language in the Fourth Edition of the
+    ECMAScript standard in 2008.
+
+    This file will break programs with improper for..in loops. See
+    http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+
+    Use your own copy. It is extremely unwise to load untrusted third party
+    code into your pages.
+*/
+
+/*jslint evil: true */
+
+/**
+rewirite by taofei 2007-8-22
+to avoid for-in loop problem.
+toJSONString(anything)
+parseJSON(anything)
+*/
+
+
+
+//help function xxxToJSONString
+
+
+    function arrayToJSON (arrayVal) {
+        var a = ['['],  // The array holding the text fragments.
+            b,          // A boolean indicating that a comma is required.
+            i,          // Loop counter.
+            l = arrayVal.length,
+            v;          // The value to be stringified.
+
+        function p(s) {
+
+// p accumulates text fragments in an array. It inserts a comma before all
+// except the first fragment.
+
+            if (b) {
+                a.push(',');
+            }
+            a.push(s);
+            b = true;
+        }
+
+// For each value in arrayVal array...
+
+        for (i = 0; i < l; i += 1) {
+            v = arrayVal[i];
+            p(toJSONString(v));
+        }
+
+// Join all of the fragments together and return.
+
+        a.push(']');
+        return a.join('');
+    };
+
+
+
+
+    function objectToJSON(objectVal) {
+        var a = ['{'],  // The array holding the text fragments.
+            b,          // A boolean indicating that a comma is required.
+            k,          // The current key.
+            v;          // The current value.
+
+        function p(s) {
+
+// p accumulates text fragment pairs in an array. It inserts a comma before all
+// except the first fragment pair.
+
+            if (b) {
+                a.push(',');
+            }
+            a.push(toJSONString(k), ':', s);
+            b = true;
+        }
+
+// Iterate through all of the keys in the object, ignoring the proto chain.
+
+        for (k in objectVal) {
+            if (objectVal.hasOwnProperty(k)) {
+                v = objectVal[k];
+                p(toJSONString(v));
+            }
+        }
+
+// Join all of the fragments together and return.
+
+        a.push('}');
+        return a.join('');
+    };
+
+function strToJSON(str)
+{
+         var m = {
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        };
+
+   // If the string contains no control characters, no quote characters, and no
+    // backslash characters, then we can simply slap some quotes around it.
+    // Otherwise we must also replace the offending characters with safe
+    // sequences.
+
+    if (/["\\\x00-\x1f]/.test(str)) {
+        return '"' + str.replace(/([\x00-\x1f\\"])/g, function (a, b) {
+            var c = m[b];
+            if (c) {
+                return c;
+            }
+            c = b.charCodeAt();
+            return '\\u00' +
+                Math.floor(c / 16).toString(16) +
+                (c % 16).toString(16);
+        }) + '"';
+    }
+    return '"' + str + '"';
+}
+
+function boolToJSON(bool)
+{
+    return String(bool);
+}
+
+function dateToJSON(dateVal)
+{
+
+// Ultimately, this method will be equivalent to the date.toISOString method.
+
+        function f(n) {
+
+// Format integers to have at least two digits.
+
+            return n < 10 ? '0' + n : n;
+        }
+
+        return '"' + dataVal.getFullYear() + '-' +
+                f(dataVal.getMonth() + 1) + '-' +
+                f(dataVal.getDate()) + 'T' +
+                f(dataVal.getHours()) + ':' +
+                f(dataVal.getMinutes()) + ':' +
+                f(dataVal.getSeconds()) + '"';
+};
+
+function numberToJSON(numberVal) 
+{
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+        return isFinite(numberVal) ? String(numberVal) : "null";
+};
+
+function toJSONString(anything)
+{
+     switch (typeof anything) {
+
+// Serialize a JavaScript object value. Ignore objects thats lack the
+// toJSONString method. Due to a specification error in ECMAScript,
+// typeof null is 'object', so watch out for that case.
+    case 'array':
+        return arrayToJSON(anything);
+    case 'object':
+        if (anything) {
+            if (anything instanceof Array)
+                return arrayToJSON(anything);
+            else
+                return objectToJSON(anything);
+        } else {
+            return "null";
+        }
+        break;
+
+    case 'string':
+        return strToJSON(anything);
+    case 'number':
+        return numberToJSON(anything);
+    case 'boolean':
+        return boolToJSON(anything);
+    default:
+        return String(anything);
+    }
+}
+
+
+
+function parseJSON(str,filter) {
+    var j;
+
+    function walk(k, v) {
+        var i;
+        if (v && typeof v === 'object') {
+            for (i in v) {
+                if (v.hasOwnProperty(i)) {
+                    v[i] = walk(i, v[i]);
+                }
+            }
+        }
+        return filter(k, v);
+    }
+
+
+// Parsing happens in three stages. In the first stage, we run the text against
+// a regular expression which looks for non-JSON characters. We are especially
+// concerned with '()' and 'new' because they can cause invocation, and '='
+// because it can cause mutation. But just to be safe, we will reject all
+// unexpected characters.
+
+    if (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.
+            test(str)) {
+
+// In the second stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+        try {
+            j = eval('(' + str + ')');
+        } catch (e) {
+            throw new SyntaxError("parseJSON");
+        }
+    } else {
+        throw new SyntaxError("parseJSON");
+    }
+
+// In the optional third stage, we recursively walk the new structure, passing
+// each name/value pair to a filter function for possible transformation.
+
+    if (typeof filter === 'function') {
+        j = walk('', j);
+    }
+    dump(toJSONString(j));
+    return j;
+};
+
+
+
+

Added: trunk/extensions/firefox-extension/chrome/content/md5.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/md5.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}

Added: trunk/extensions/firefox-extension/chrome/content/utils.js
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/content/utils.js	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,51 @@
+/*
+ * Add A Row to a list 
+ * Param is string . Might be more than one .
+ * Every param is a considered to be a cell .
+ */
+function appendRow (){
+    var list = arguments[0];
+    var listitem = document.createElement('listitem');
+    for(var i = 1; i< arguments.length; i++)
+    {
+        var listcell = document.createElement('listcell');
+        listcell.setAttribute('label',arguments[i]);
+        listcell.setAttribute('value',arguments[i]);
+        listitem.appendChild(listcell);
+    }
+    list.appendChild(listitem);
+}
+
+
+/*
+ * check weather a string is end with another 
+ * usage: somestirng.endWith(antoherString)
+ * @param {string} subfix  
+ */
+String.prototype.isEndWith = function(subfix)
+{
+    var index = this.lastIndexOf(subfix);
+    return index != -1 && index + subfix.length == this.length;
+}
+
+/**
+ * convert  a wildcard expression to regular expression
+ * usage: wildcard.wildcard2RE
+ * @return the re string ( not RegExp Object)
+ */
+String.prototype.wildcard2RE = function()
+{
+    return this.replace(/([\\\+\[\]\{\}\^])/g,"\\$1").replace(/\?/g,".?").replace(/\*/g,".*");
+}
+
+Function.prototype.bind = function(f,obj) {
+    var temp = function() {
+        return f.apply(obj, arguments);
+    };
+    return temp;
+}
+
+function log(msg)
+{
+   dump("[xesam] " + msg + "\n"); 
+}

Added: trunk/extensions/firefox-extension/chrome/locale/en-US/beagle.dtd
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/locale/en-US/beagle.dtd	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,38 @@
+<!ENTITY beagle.context.search.link.label           "Find References to this Link">
+<!ENTITY beagle.context.search.page.label           "Find References to this Page">
+
+<!ENTITY beagle.pref.label                          "Xesam Preferences">
+<!ENTITY beagle.pref.security.active.label          "Index pages with secure content">
+<!ENTITY beagle.pref.bookmark.active.label          "Index bookmarks when close the window">
+<!ENTITY beagle.pref.prompt.keywords.active.label   "Prompt for keywords when indexing on demand">
+<!ENTITY beagle.pref.default.action.label           "Default Action">
+<!ENTITY beagle.pref.default.action.tooltip         "What to do When the URL doesn't match any rule">
+<!ENTITY beagle.pref.conflict.action.label          "Conflict Action">
+<!ENTITY beagle.pref.conflict.action.tooltip        "What to do When the URL matches both rules in include list and exclude list">
+<!ENTITY beagle.pref.action.index.label             "Index">
+<!ENTITY beagle.pref.action.noindex.label           "No Index">
+<!ENTITY beagle.pref.groupbox.general.label         "General">
+<!ENTITY beagle.pref.groupbox.include.label         "Include">
+<!ENTITY beagle.pref.groupbox.exclude.label         "Exclude">
+<!ENTITY beagle.pref.filter.name.label              "Name">
+<!ENTITY beagle.pref.filter.pattern.label           "Pattern">
+<!ENTITY beagle.pref.filter.patterntype.label       "PatternType">
+<!ENTITY beagle.pref.filter.add.label		        "Add">
+<!ENTITY beagle.pref.filter.remove.label            "Remove">
+<!ENTITY beagle.pref.filter.add.dlg.title           "Add Rule">
+<!ENTITY beagle.pref.help.label                     "Help">
+<!ENTITY beagle.pref.save.label                     "Save">
+<!ENTITY beagle.pref.cancel.label                   "Cancel">
+
+<!ENTITY beagle.run.index.this.label                "Index This Page">
+<!ENTITY beagle.run.always.index.label              "Always Index This Site">
+<!ENTITY beagle.run.never.index.label               "Never  Index This Site">
+<!ENTITY beagle.run.preferences.label               "Preferences">
+<!ENTITY beagle.run.context.menu.label              "Search">
+<!ENTITY beagle.run.index.link.label                "Index This Link">
+<!ENTITY beagle.run.index.image.label               "Index This Image">
+<!ENTITY beagle.index.link.start.label              "Start">
+<!ENTITY beagle.index.link.stop.label               "Stop">
+
+<!ENTITY beagle.bookmark.index.modified.label       "Index The Modified Bookmarks">
+

Added: trunk/extensions/firefox-extension/chrome/locale/en-US/beagle.properties
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/locale/en-US/beagle.properties	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,22 @@
+beagle_context_search_text=Search for "%S"
+beagle_tooltip_actived=Xesam auto index active. Click to disable.
+beagle_tooltip_disabled=Xesam auto index disabled. Click to active.
+beagle_tooltip_error=Xesam indexing error: %S
+beagle_not_found=beagle not found
+beagle_run_error=beagle run error
+beagle_check_env_error=~/.beagle Not Found.This extension will not work.
+beagle_write_error_confirm=Fail to write content/metadata.\n Would you like to disable beagle now ?
+beagle_statuslabel_indexing=xesam is indexing %S
+beagle_index_link_connect=Connecting ... %S
+beagle_index_link_start=Loading ... %S
+beagle_index_link_progress=Transferring Data (%S) %S
+beagle_index_link_saving=Saving ... %S
+beagle_index_link_stop=Stopped
+beagle_index_link_invalid_url=Invalid URL
+beagle_index_link_http_403=Access Denied (403 Forbidden)
+beagle_index_link_http_404=File Not Found (404 Not Found)
+beagle_index_link_http_500=500 Internal Server Error
+beagle_prompt_keywords_title=Keywords
+beagle_prompt_keywords_text=Extra keywords to index
+beagle_index_bookmark_finish=%S bookmarks have been indexed!
+beagle_quick_add_rule_error=Error! Not Found a hostname for this page!

Added: trunk/extensions/firefox-extension/chrome/locale/en-US/contents.rdf
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/locale/en-US/contents.rdf	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+         xmlns:chrome="http://www.mozilla.org/rdf/chrome#";>
+
+<!-- list all the packages being supplied by this jar -->
+<RDF:Seq about="urn:mozilla:locale:root">
+  <RDF:li resource="urn:mozilla:locale:en-US" />
+</RDF:Seq>
+
+<!-- locale information -->
+<RDF:Description about="urn:mozilla:locale:en-US"
+  chrome:displayName="English(US)"
+  chrome:author="Filia Tao"
+  chrome:name="en-US">
+  <chrome:packages>
+    <RDF:Seq about="urn:mozilla:locale:en-US:packages">
+      <RDF:li resource="urn:mozilla:locale:en-US:beagle" />
+    </RDF:Seq>
+  </chrome:packages>
+</RDF:Description>
+
+<!-- version information -->
+<RDF:Description about="urn:mozilla:locale:en-US:beagle"
+  chrome:localeVersion="1.4" />
+
+</RDF:RDF>

Added: trunk/extensions/firefox-extension/chrome/skin/classic/beagle-big.png
==============================================================================
Binary file. No diff available.

Added: trunk/extensions/firefox-extension/chrome/skin/classic/beagle-disabled.png
==============================================================================
Binary file. No diff available.

Added: trunk/extensions/firefox-extension/chrome/skin/classic/beagle-error.png
==============================================================================
Binary file. No diff available.

Added: trunk/extensions/firefox-extension/chrome/skin/classic/beagle.png
==============================================================================
Binary file. No diff available.

Added: trunk/extensions/firefox-extension/chrome/skin/classic/contents.rdf
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/skin/classic/contents.rdf	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+         xmlns:chrome="http://www.mozilla.org/rdf/chrome#";>
+
+  <RDF:Seq about="urn:mozilla:skin:root">
+    <RDF:li resource="urn:mozilla:skin:classic/1.0" />
+  </RDF:Seq>
+
+  <RDF:Description about="urn:mozilla:skin:classic/1.0">
+    <chrome:packages>
+      <RDF:Seq about="urn:mozilla:skin:classic/1.0:packages">
+        <RDF:li resource="urn:mozilla:skin:classic/1.0:beagle" />
+      </RDF:Seq>
+    </chrome:packages>
+  </RDF:Description>
+
+</RDF:RDF>

Added: trunk/extensions/firefox-extension/chrome/skin/classic/overlay.css
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/chrome/skin/classic/overlay.css	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,28 @@
+statusbarpanel#beagle-notifier-status[status="000"] {
+  list-style-image: url("chrome://beagle/skin/beagle.png");
+  padding-left: 8px;
+  padding-right: 8px;
+  padding-top: 2px;
+}
+
+statusbarpanel#beagle-notifier-status[status="00f"] {
+  list-style-image: url("chrome://beagle/skin/beagle-disabled.png");
+  padding-left: 8px;
+  padding-right: 8px;
+  padding-top: 2px;
+}
+
+statusbarpanel#beagle-notifier-status[status="f00"] {
+  list-style-image: url("chrome://beagle/skin/beagle-error.png");
+  padding-left: 8px;
+  padding-right: 8px;
+  padding-top: 2px;
+}
+
+#beagle-button {
+  list-style-image: url("chrome://beagle/skin/beagle.png");
+}
+
+toolbar[iconsize="small"] #beagle-button {
+  list-style-image: url("chrome://beagle/skin/beagle.png");
+}

Added: trunk/extensions/firefox-extension/firefox-extension-xesam.xpi
==============================================================================
Binary file. No diff available.

Added: trunk/extensions/firefox-extension/install.rdf
==============================================================================
--- (empty file)
+++ trunk/extensions/firefox-extension/install.rdf	Mon Feb 25 09:45:19 2008
@@ -0,0 +1,31 @@
+<?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>{fda00e13-8c62-4f63-9d19-d168115b11ca}</em:id>
+    <em:name>Firefox Extension for Xesam search enginer(beagle,tracker)</em:name>
+    <em:version>1.0.1</em:version>
+    <em:description>
+      Index webpages you visit using Beagle or Tracker
+    </em:description>
+    <em:creator>Tao Fei (Filia Tao gmail com) </em:creator>
+    <em:contributor>Alex Graveley  (Original Code)</em:contributor>
+    <em:contributor>Abby Coffin (Icon Design)</em:contributor>
+    <em:homepageURL>http://beagle-project.org/Browser_Extension#Firefox_Extension</em:homepageURL>
+    <em:iconURL>chrome://beagle/skin/beagle-big.png</em:iconURL>
+    <em:optionsURL>chrome://beagle/content/beaglePrefs.xul</em:optionsURL>
+
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>0.8</em:minVersion>
+        <em:maxVersion>3.0.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+  </Description>
+
+</RDF>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]