/* $Id: utils.js,v 1.5 2007/01/16 11:15:59 ebricca Exp $ */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * 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 Initial Developer of the Original Code is
 * Ernesto Bricca.
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

// dump service  ----

function dumpStatusBar(aString)
{
// !!! not usable .. the user wont notice that .. instead use browsermessage
// dumps the msg in the status bar and if the debug is set also dumps to the javascript console
	if (refsprefs.talktoPref(comVar.DEBUG_ID)){ dumpme('statusbar dump: ' + aString); }
	var statusTextFld = document.getElementById("statusbar-display");
	statusTextFld.label = aString;

}

function dumpBrowserMsg(aString, buttonTxt, destUri, destTxt)
{
//  browsermessage -- bloob that shows up atop of the rendered page (like on non trusted extension inst)
//  http://lxr.mozilla.org/mozilla/source/browser/base/content/browser.js#478
//  http://lxr.mozilla.org/mozilla/source/toolkit/content/widgets/tabbrowser.xml#202
    
//  getBrowser(), gBrowser  --  only exists in the browser.xul scope like in refspoof_overlay
//  document.getElementById("content");  is same ..
    
    
//  gBrowser.showMessage(gBrowser.mCurrentBrowser, null/*img*/, "message", "button",
//  null, null , "toolbar-context-menu", "top", true/*close x*/);
//  the rest is defined in msgPopup !!! interaction! (oncommand is fixed so we have to pass values there (openMyUri))

// set defaults if only minimal input is given   

if (typeof(gBrowser)=="object"){
    if (buttonTxt == null) {
        buttonTxt = "Help";
    }
    if (destUri == null) {
        destUri = "chrome://refspoof/locale/help.html";
    }
    if (destTxt == null) {
        destTxt = "Help";
    }
    
    if (refsprefs.talktoPref("extensions.lastAppVersion", null, 2).substring(0,1)>=2){
    //    gBrowser.getNotificationBox().appendNotification(aString,null,null,null,aButton);
	gBrowser.getNotificationBox().appendNotification(aString,null,null,4,Array({label: buttonTxt, callback: "doOK", popup: "msgPopup"})); 
 
    } else {
       // old syntax
    gBrowser.showMessage(gBrowser.mCurrentBrowser, null/*img*/, aString,
            buttonTxt, null, null , "msgPopup", "top", true/*close x*/);     
    
    }
    
   
} else {dumpme(aString);}
 
}

function dumpNagBrowserMsg(aString, buttonTxt, destUri, destTxt)
{
    if (refsprefs.talktoPref(comVar.URLREFNAG_ID)) {
        dumpBrowserMsg(aString, buttonTxt, destUri, destTxt);    
    }
}

function dumpBrowserMsgBlink(aString)
{
// not usable irritates too much
browser = getBrowser();

browser.showMessage(browser.selectedBrowser, "", aString, "", 
		browser.docShell, 
		null, null , "top", false); //last entry true gives an x

// flicker
// 6 s msg flicker .. function looses local vars
		setTimeout("getBrowser().hideMessage(getBrowser().selectedBrowser, 'top');",6000); 
}


function dumpAlert(aString)
{
// to refine could first getBrowser() via dom model
	alert(aString);

}

function dumpd(aString)
{
   if (refsprefs.talktoPref(comVar.DEBUG_ID)){ cdump('debug: ' + aString + '\n'); }
   //dump('debug: ' + aString + '\n');
};


function dumpme(aString)
{
//alert(aString);
	cdump(aString.toString() + '\n');

};

function cdump(s)
{
  var consoleService = getConsoleService();

  var excp;

  try
  {
    consoleService.logStringMessage(s);
  }
  catch(excp)
  {
  }

};


function getConsoleService()
{


  var excp;
  var gConsoleService;

  if (document.location.href.indexOf('chrome://') == -1)
  {
    try
    {
      netscape.security.PrivilegeManager.enablePrivilege(gConsoleSecurityPrivileges);
    }
    catch(excp)
    {
      alert(gConsoleSecurityMessage);
      return gConsoleService;
    }
  }

  try
  {
    gConsoleService = 
        Components.classes["@mozilla.org/consoleservice;1"]
        .getService(Components.interfaces.nsIConsoleService);
  }
  catch(excp)
  {
  }

  return gConsoleService;

}

// handle vars and defaults  (interfaces with prefs) ----

// common variables
var comVar = {

	BM_BUTTON_ID : {gui: "rstb_bm_button"},
	SPOOF_BUTTON_ID : {gui: "rstb_spoof"},
    
    BKMRK_PIPE_ID : {id: "refspoof.bkmrk_pipe", def : "none"},

    URLBAR_ID : {gui: "urlbar"}, //from navigator.xul
	REFBAR_ID : {id: "refspoof.tb_refbar", def : 5, gui: "rstb_refbar"},
	URLISREF_ID : {id : "refspoof.tb_urlisref", def : false, gui: "rstb_urlref"},
	OPENTAB_ID : {id : "refspoof.tb_opentab", def : false, gui: "rstb_openTab"}, 
    
	//in lack of a better names
	STORE_METHOD_ID : {id : "refspoof.bmStoreMethod", def : 0, gui : "bmStoreMethod"},
	STORE_LOCATION_ID : {id : "refspoof.bmStoreLocation", def : 0, gui : "bmStoreLocation"},
	
	SIDEBAR_CONTENT_ID : {id : "refspoof.sidebarContent", def : 0, gui : "sidebarContent"}, 
	SIDEBAR_URI_ID : {id : "refspoof.sidebarURI", def : "chrome://refspoof/locale/sidebar.html", gui: "sidebarURI"},
	
	DEBUG_ID : {id : "refspoof.debug", def : false, gui: "showLocalDebug"},
	URLREFNAG_ID : {id : "refspoof.urlrefnag", def : true, gui: "showUrlRefNag"},
	
	SPOOFMARK_FOLDER_ID : {id : "refspoof.folder_id", def : "NC:BookmarksRoot"},
	ALT_PRESSED_ID : {id : "refspoof.altPressed", def : 0},
	SHIFT_PRESSED_ID : {id : "refspoof.shiftPressed", def : 0},
	
	BROWSER_LOAD_TABS_IN_BG_ID : {id : "browser.tabs.loadInBackground", def : true},
    SEND_REFERRER_STATE : {id: "network.http.sendRefererHeader", def : 2, gui:"rstb_refStat",
        guiRadio: "rstb_refStat_radio"},
    ADD_HIST_WATCH : {id: "refspoof.historyWatch", def : "none"},

SEND_REFERRER_CUSTOM : {id: "refspoof.customRefState", def : 0},
    
    //-- taken from refspoof.dtd as unf there is no bridge xul - dtd <-> js - property list
    REF_ENABLED : {radio: 0, gui : "rstb_refEnabled", img : "chrome://refspoof/skin/icons/rstb_refEnabled.png"},
    REF_EMBED : {radio: 1, gui : "rstb_refEmbed", img : "chrome://refspoof/skin/icons/rstb_refEmbed.png"},
    REF_DISABLED : {radio: 2, gui : "rstb_refDisabled", img : "chrome://refspoof/skin/icons/rstb_refDisabled.png"},
    REF_STATIC : {radio: 3, gui : "rstb_refStatic", img : "chrome://refspoof/skin/icons/rstb_refFix.png"},
    REF_CUSTOM : {radio: 4, gui : "rstb_refCustom", img : "chrome://refspoof/skin/icons/rstb_refCustom.png"},



 //-- MEGASPOOF client part

    MEGSP_USER : {id : "refspoof.ms_user", def: "rs_user"},
//use a getter for the id later to check if set to none -> register
    MEGSP_ID : {id : "refspoof.ms_id", def:"361181"},
    MEGSP_PASSWORD : {id : "refspoof.ms_password", def:"A94F6B249892748B31A31BC7B53BD8E9"},
    MEGSP_HOST : {id : "refspoof.ms_host", def: "sms.supermegaspoof.com"},

    MEGSP_POP : {id : "refspoof.ms_popCache", gui:"Popular", req:"getpopular", def: 1},
    MEGSP_TOP : {id : "refspoof.ms_topCache", gui:"Top Rated", req:"gettopspoofs", def: 1},
    MEGSP_LAST : {id : "refspoof.ms_lastCache", gui:"Last Added", req:"getlastspoofs", def: 1},
    MEGSP_FAVS : {id:"refspoof.ms_favsCache", gui:"my Favorites", req:"empty", reqPart:"favs", def: 1},

    MEGSP_URSP : {id:"empty", idPart : "refspoof.ms_urspCache", gui:"empty", guiPart:"Spoofs from:", req:"empty", reqPart:"userspoofs", def: 1},

    MEGSP_SEARCH : {id:"empty", idPart:"refspoof.ms_searchCache", gui:"empty", flid:"msSearch", guiPart:"Search for: ", req:"empty", reqPart:"search", def: 1},


    MEGSP_MAIL : {id : "refspoof.ms_mail", gui:"My Mail", req:"emtpy", reqPart:"getmail", def: 1},

    MEGSP_VOTS : {id:"empty", idPart : "refspoof.ms_votes", gui:"empty", guiPart:"Votes for Spoof:", req:"emtpy", reqPart:"getvotes", def: 1},

    MEGSP_ADDSPF : {id : "refspoof.ms_aspoof", gui:"Add Spoof", req:"emtpy", reqPart:"addspoof", def: 1},
    MEGSP_SMSG : {id : "refspoof.ms_sendmsg", gui:"empty", guiPart:"my Message to:", req:"emtpy", reqPart:"sendmsg", def: 1},
    MEGSP_RPRT : {id : "refspoof.ms_report", gui:"empty", guiPart:"i report  Spoof:", req:"emtpy", reqPart:"report", def: 1},


    MEGSP_ADDFAV : {id : "refspoof.ms_ivote", gui:"empty", guiPart:"i vote Spoof:", req:"emtpy", reqPart:"addfav", def: 1},
    MEGSP_DELFAV : {id : "refspoof.ms_ivote", gui:"empty", guiPart:"i vote Spoof:", req:"emtpy", reqPart:"delfav", def: 1},
    MEGSP_IVOT : {id : "refspoof.ms_ivote", gui:"empty", guiPart:"i vote Spoof:", req:"emtpy", reqPart:"vote", def: 1},
    MEGSP_DELMAIL : {id : "refspoof.ms_report", gui:"empty", req:"emtpy", reqPart:"delmail", def: 1},

    MEGSP_CLOGIN : {id : "refspoof.ms_chklogin", gui:"empty", req:"emtpy", reqPart:"chklogin", def: 1},
    MEGSP_NEWUSR : {id : "refspoof.ms_newusr", gui:"empty", req:"emtpy", reqPart:"newuser", def: 1},


    MEGSP_HTMLBACK : {id: "refspoof.watch_pipe", def : "none"},
    MEGSP_UIDWATCH : {id: "refspoof.watuid_pipe", def : "none"},

    MEGSP_MSGDEST : {id: "refspoof.ms_msgdest", def : "none"},
    MEGSP_MSGCOUNT : {id: "refspoof.ms_msgcount", def : 28465}

}

// handle prefs----

var refsprefs = {

	// talktoPref needs to be able to handle passed objects *and* string values (prefsystem/self)
	// !no branch .. just clutters logic

	talktoPref : function (myId, myVal, myDefault) {
		if (myId == null) {
			dumpme("specify a store id");
			return null;
		} else {

			if (typeof(myId)=="object"){
				try {
				var myIdString = myId.id;
				myDefault = myId.def;
	
				// on items not in list mostly not need as "specify a store id" normally comes first
				} catch (e) {dumpme("spat error:" + myId); return null;} 
				if (myId.id == "undefined"){dumpme(".id gave undefined:" + myId); return null;}
				if (myId.def == "undefined"){dumpme(".def gave undefined:" + myId); return null;}
			} 

			if (typeof(myId)=="string"){

				var myIdString = myId;

				// myDefault should been given -- test

				if ((myVal == null) && (myDefault == null)){
					dumpme("no default was given .. bad!!");
					return null;
				}
			}

		}


		if (myVal == null) {
			try {
				return this.getPref(myIdString);
			} catch(ex) {
				return this.talktoPref(myIdString, myDefault); // set default
			}
		} else {
			try {
				this.setPref(myIdString, myVal);
				return this.getPref(myIdString);
			} catch(ex) {
				dumpme("bad as - "+ myId + ex + " - should have been catched earlier -- happens on wrong format")
			}
		}


		return null;
	},


	getPref : function (myId, myBranch) {
		var myPrefS = this.grabPrefS(myBranch);
         var type=myPrefS.getPrefType(myId); //bool==128, string==32, int==64
		//dumpd( myId + "on branch" + myBranch +" = " + type + " -- bool==128, string==32, int==64");
		switch (type){
			case 32:
				return myPrefS.getCharPref(myId);
			case 64:
				return myPrefS.getIntPref(myId);
			case 128:
				return myPrefS.getBoolPref(myId);
			case 0:
				throw "pref not defined";
		}
 		 dumpme("no get matchtype");
 		 return null;
	},

	setPref : function (myId, myVal, myBranch) {
		var myPrefS = this.grabPrefS(myBranch);
		var type = typeof(myVal);
		//dumpd(myId + " = " + type);
		switch (type){
			case "string":
				return myPrefS.setCharPref(myId, myVal);
			case "number":
				return myPrefS.setIntPref(myId, myVal);
			case "boolean":
				return myPrefS.setBoolPref(myId, myVal);
		}
  		dumpme("no set matchtype");
  		return null;
	},

	grabPrefS : function (myBranch) {
		if (!this.myPrefS){
			this.myPrefS = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
		}
		if (myBranch == null) {
		myBranch = "";
		}
		return this.myPrefS.getBranch(myBranch);
	},
	
	
	// remove all preferences can be invoced via js shell (use convert.xul scope)
	removePrefs: function() {
		var prefBranch = this.grabPrefS("refspoof.");

		try {
			prefBranch.deleteBranch("");
			return true;
		} catch(e) {
			return false;
		}
	},
    
    addPrefListener: function(aPrefString, aFunc) {
        var prefObserver;
        try {
            prefObserver = {
                domain: aPrefString,
                observe: aFunc
            };

            var pbi = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranchInternal);
            pbi.addObserver(prefObserver.domain, prefObserver, false);
        } catch(e) {
            alert(e);
            prefObserver = null;
        }

        return prefObserver;
    },

    removePrefListener: function(aObserver) {
        var prefObserver;
        try {
            var pbi = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranchInternal);
            pbi.removeObserver(aObserver.domain, aObserver);
        } catch(e) {
            alert(e)
        }
    }
	
}


function detectKbSwitch(event, myId, myKey) {
	var pressed=false;
	if (myKey=="alt") {
		if (event.altKey){
			pressed=true;
		}
	} else if (myKey=="shift"){
		if (event.shiftKey){
			pressed=true;
		}
	}

	if (pressed) {
		// testline of the using script
		//Boolean(Number(prefs.talktoPref(myId, null, 0)));
		// note to be resetted !!before usage in the xul .. call resetKbSwitch(myId)
		refsprefs.talktoPref(myId, 1);
	}

};

function resetKbSwitch(myId) {

// needs to be called at the end of the instruction that uses detectKbSwitch 

	refsprefs.talktoPref(myId, 0);

};

function openMyUri(myUri) {
	
	if (typeof(getBrowser)=='function'){
		getBrowser().loadURI(myUri);
	} else {
		window.open(myUri);
	} 
};


function rs_createBookmark(spoofUri, bmName, storeLocation) {

	// storeLocation:
	// 0==show save dialog
	// 1==use the selected folder as direct save

	// default location to store spoofuris to
	var refspoofFolderID = refsprefs.talktoPref(comVar.SPOOFMARK_FOLDER_ID)
		
    
	switch (storeLocation){
	  case 0:
	    
	    var myData = { name: bmName, url: spoofUri, folderURI: refspoofFolderID, charset: null,
		  bAddGroup: "", objGroup: ""};
	    window.openDialog('chrome://browser/content/bookmarks/addBookmark2.xul',
		    "xxx", "modal,centerscreen,chrome,dialog,resizable,dependent", myData);
	    break;
	  case 1:
	    dumpNagBrowserMsg("bookmark got stored automatically in the selected folder (toolbar>Options>Preferences..)");
	    var rspSource = BookmarksUtils.createBookmark(bmName, spoofUri, null, null, null, null);  
	    var mySelection = BookmarksUtils.getSelectionFromResource(rspSource);
	    var saveFolder = RDF.GetResource(refspoofFolderID);
	    var myTarget = BookmarksUtils.getTargetFromFolder(saveFolder);
	    
	    BookmarksUtils.insertAndCheckSelection("newbookmark", mySelection, myTarget);
	    
	    var remoteDS = BMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
	    remoteDS.Flush();
	    
	}
	





}





//------ versioning functions // build

	// checklist where to modify version tag ..
	// change install.rdf
	// change update.rdf
	// generate xpi
	// move to downloads cvs folder wait for propagation takes about 10h

	// change webpage information on
	//  installation webpage
	//  index webpage
	// cvs update
	// upload to addons.mozilla
	

// function borrowed from spellbound-dev_20060108
var rfsp_Migrate =
{
  migrate: function()
  {
    // Old versions of the extension and libraries
    // the pain of supporting multiple platforms before 1.5
    var extIDs = ["{E7847830-DB6A-05EB-669F-81B2ED2778C7}",
    			  "{e7847830-db6a-05eb-669f-81b2ed2778c7}"]

    var needsRestart = false;
    var em = Components.classes["@mozilla.org/extensions/manager;1"]
                       .getService(Components.interfaces.nsIExtensionManager);

    for (var i = 0; i < extIDs.length; ++i) {
      var id = extIDs[i];
      var installLocation = em.getInstallLocation(id);
      if (!installLocation)
        continue;
      needsRestart = true;
      var location = installLocation.getItemLocation(id);
      // All of these checks shouldn't be needed but this way it shouldn't
      // cause any more problems on a system that already has problems.
      if (location instanceof Components.interfaces.nsILocalFile &&
          location.exists() && location.isDirectory()) {
        if (installLocation.canAccess)
          em.uninstallItem(id);
        else
          em.disableItem(id);
      }
    }


    if (needsRestart)
      this.restart();
    return needsRestart;
  },

  restart: function()
  {
    Components.classes["@mozilla.org/toolkit/app-startup;1"]
              .getService(Components.interfaces.nsIAppStartup)
              .quit(Components.interfaces.nsIAppStartup.eRestart |
                    Components.interfaces.nsIAppStartup.eAttemptQuit);
  },
};


//chrome://mozapps/content/extensions/extensions.js
//not yet working correctly minor bug
//in ffx1.5 aTarget got set from Extension to item

function extensionExists(extensionName){
    aTarget = "item";
    var RDFService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
                                        .getService(Components.interfaces.nsIRDFService);
    var Container = Components.classes["@mozilla.org/rdf/container;1"]
                                       .getService(Components.interfaces.nsIRDFContainer);
    var extensionDS= Components.classes["@mozilla.org/extensions/manager;1"]
                                        .getService(Components.interfaces.nsIExtensionManager).datasource;
    var root = RDFService
    .GetResource("urn:mozilla:"+aTarget.toLowerCase()+":root");
    var nameArc = RDFService
    .GetResource("http://www.mozilla.org/2004/em-rdf#name");
    var versionArc = RDFService
    .GetResource("http://www.mozilla.org/2004/em-rdf#version");
    var disabledArc = RDFService
    .GetResource("http://www.mozilla.org/2004/em-rdf#disabled");
    
    
    Container.Init(extensionDS,root);
    var elements=Container.GetElements();
    
    while(elements.hasMoreElements()){
        var element=elements.getNext();
        var name="";
        var version="";
        var disabled="";
        element.QueryInterface(Components.interfaces.nsIRDFResource);
        var target=extensionDS.GetTarget(element, nameArc ,true);
        if(target)
            name=target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
        target=extensionDS.GetTarget(element, versionArc ,true);
        if(target)
            version=target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
        target=extensionDS.GetTarget(element, disabledArc ,true);
        if(target)
            disabled=target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
        
        enabled = true;
        if (disabled && disabled=="true")
            enabled = false;
        if( name == extensionName)
            return Array(name, version, enabled);
//      array scheme .. name , versionNumber, if enabled
        
        
    }
    
    return null;
};


// takes a version string, returns an integer triple containing (major version, minor version, patch level)
function versionStrDecode(versionStr) {
    var regexp = /([0-9]*)\.([0-9]*)\.([0-9]*)/;
    var result = regexp.exec(versionStr);
    return Array(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]));
};

// takes a version triple, returns an integer
function versionToInt(versionTriple) {
    return versionTriple[0]*100 + versionTriple[1]*10 + versionTriple[2];
};

// takes two version triples, returns 1 if the first is more recent, 0 otherwise
function versionCompare(versionA, versionB) {
    if(this.versionToInt(versionA) > this.versionToInt(versionB)) {
        return 1;
    } else {
        return 0;
    }
};

// takes a version triple, returns a formatted version string
function versionString(version, pretty) {
    var formatted;
    if(pretty) {
        formatted = version[0].toString() + '.' + version[1].toString();
        formatted += version[2] != 0 ? "." + version[2] : ""
    } else {
        formatted = version[0].toString() + '.' + version[1].toString() + '.' + version[2].toString();
    }
    return formatted;
};


  function selectTreeFolderRS()
  {
    rsBookmarksTree = document.getElementById("refopt-folder-tree");
    var resource = rsBookmarksTree.currentResource;
    refsprefs.talktoPref(comVar.SPOOFMARK_FOLDER_ID, resource.Value)
  }

  function selectFolderRS()
  {
      selected=refsprefs.talktoPref(comVar.SPOOFMARK_FOLDER_ID)
      selectedFolder = RDF.GetResource(selected);
      rsBookmarksTree = document.getElementById("refopt-folder-tree");
      rsBookmarksTree.treeBoxObject.view.selection.selectEventsSuppressed = true;
      rsBookmarksTree.treeBoxObject.view.selection.clearSelection();
      rsBookmarksTree.selectResource(selectedFolder);
    var index = rsBookmarksTree.currentIndex;
    rsBookmarksTree.treeBoxObject.ensureRowIsVisible(index);
    rsBookmarksTree.treeBoxObject.view.selection.selectEventsSuppressed = false;
  }
