[or-cvs] [torbutton/master] Added more UI elements on Cookie Protector and functionality to almost all the elements (except for the default cookie protection radio and filtering the protected/deleted cookies on toggle).
mikeperry at seul.org
mikeperry at seul.org
Wed Sep 23 23:49:11 UTC 2009
Author: Kory Kork <kory at korykirk.com>
Date: Sat, 15 Aug 2009 20:28:00 +0000
Subject: Added more UI elements on Cookie Protector and functionality to almost all the elements (except for the default cookie protection radio and filtering the protected/deleted cookies on toggle).
Commit: e71edaf86631a23f872a45fe8d201fe30b549975
svn:r20316
---
src/chrome/content/popup.xul | 4 +-
src/chrome/content/torcookie.js | 342 +++++++++++++++++++++++++++++++-
src/chrome/content/torcookiedialog.xul | 33 +++-
src/components/cookie-jar-selector.js | 92 ++++++++-
4 files changed, 452 insertions(+), 19 deletions(-)
diff --git a/src/chrome/content/popup.xul b/src/chrome/content/popup.xul
index 7691cf5..db576ca 100644
--- a/src/chrome/content/popup.xul
+++ b/src/chrome/content/popup.xul
@@ -23,10 +23,10 @@
insertafter="context-stop"
oncommand="torbutton_open_prefs_dialog()"/>
<menuitem id="torbutton-cookies"
- label="Cookie Manager"
+ label="Cookie Protections"
accesskey="C"
insertafter="context-stop"
- oncommand="window.openDialog('chrome://torbutton/content/torcookiedialog.xul','Cookie Manager',
+ oncommand="window.openDialog('chrome://torbutton/content/torcookiedialog.xul','Cookie Protections',
'centerscreen,chrome,dialog,modal,resizable')"/>
<menuitem id="torbutton-about"
label="&torbutton.context_menu.about;"
diff --git a/src/chrome/content/torcookie.js b/src/chrome/content/torcookie.js
index b9e286a..5bdef57 100644
--- a/src/chrome/content/torcookie.js
+++ b/src/chrome/content/torcookie.js
@@ -1,7 +1,12 @@
var cookiesTree = null;
var prefs = null;
var cookies = [];
-var protectedcookies = [];
+var protectedCookies = [];
+var deletedCookies = [];
+var lastCookieSortColumn = "";
+var lastCookieSortAscending = false;
+var cookiemanager = null;
+var selector = null;
//custom tree view, this is how we dynamically add the cookies
var cookiesTreeView = {
rowCount : 0,
@@ -14,7 +19,8 @@ var cookiesTreeView = {
switch (column.id) {
case "domainCol" : rv = cookies[row].rawHost; break;
case "nameCol" : rv = cookies[row].name; break;
- case "lockCol" : rv = cookies[row].isProtected;
+ case "lockCol" : rv = cookies[row].isProtected; break;
+ case "pathCol" : rv = cookies[row].path; break;
}
return rv;
},
@@ -27,16 +33,18 @@ var cookiesTreeView = {
getCellProperties : function(row,column,prop) {}
};
-function Cookie(number,name,value,isDomain,host,rawHost,path,isSecure,expires,
- isProtected) {
+function Cookie(number,name,value,isDomain,host,rawHost,HttpOnly,path,isSecure,isSession,
+ expires,isProtected) {
this.number = number;
this.name = name;
this.value = value;
this.isDomain = isDomain;
this.host = host;
this.rawHost = rawHost;
+ this.isHttpOnly = HttpOnly;
this.path = path;
this.isSecure = isSecure;
+ this.isSession = isSession;
this.expires = expires;
this.isProtected = isProtected;
}
@@ -45,12 +53,16 @@ function initDialog() {
cookiesTree = document.getElementById("cookiesTree");
prefs =Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
+ selector = Components.classes["@stanford.edu/cookie-jar-selector;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
var tor_enabled = prefs.getBoolPref("extensions.torbutton.tor_enabled");
//init cookie manager
- var cookiemanager = Components.classes["@mozilla.org/cookiemanager;1"].getService();
+ cookiemanager = Components.classes["@mozilla.org/cookiemanager;1"].getService();
cookiemanager = cookiemanager.QueryInterface(Components.interfaces.nsICookieManager);
var enumerator = cookiemanager.enumerator;
var count = 0;
+ getProtectedCookies();
while (enumerator.hasMoreElements()) {
var nextCookie = enumerator.getNext();
if (!nextCookie) break;
@@ -60,8 +72,8 @@ function initDialog() {
//populate list
cookies[count] =
new Cookie(count++, nextCookie.name, nextCookie.value, nextCookie.isDomain, host,
- (host.charAt(0)==".") ? host.substring(1,host.length) : host,
- nextCookie.path, nextCookie.isSecure, nextCookie.expires,
+ (host.charAt(0)==".") ? host.substring(1,host.length) : host, nextCookie.isHttpOnly,
+ nextCookie.path, nextCookie.isSecure, nextCookie.isSession, nextCookie.expires,
isProt);
}
//apply custom view
@@ -71,12 +83,324 @@ function initDialog() {
//grab data from xml files
//add protected tag
}
+function protectCookie()
+{
+ ProtectInTree(cookiesTree, cookiesTreeView,
+ cookies, "protectCookie", "unprotectCookie", "removeCookie");
+}
+function unprotectCookie() {
+ UnProtectInTree(cookiesTree, cookiesTreeView,
+ cookies, "protectCookie", "unprotectCookie", "removeCookie");
+}
function checkIfProtected(name, host, path)
{
-
+ for (var i = 0; i < protectedCookies.length; i++)
+ {
+ var cookie = protectedCookies[i];
+ if (cookie.name == name && cookie.host == host && cookie.path == path)
+ return true;
+ }
return false;
}
function itemSelected() {
- var item = document.getElementById("cookiesTree").selectedItemIndex;
+ var selections = getTreeSelections(cookiesTree);
+ if (selections.length) {
+
+//DY - check if (the last in list) selection is protected/unprotected, set buttons
+ if (cookies[selections[(selections.length)-1]].isProtected) {
+ document.getElementById("removeCookie").disabled = true;
+ document.getElementById("unprotectCookie").disabled = false;
+ document.getElementById("protectCookie").disabled = true;
+ } else {
+ document.getElementById("removeCookie").disabled = false;
+ document.getElementById("unprotectCookie").disabled = true;
+ document.getElementById("protectCookie").disabled = false;
+ }
+
+ }
+}
+function acceptDialog() {
+
+ FinalizeCookieDeletions();
+ var protectedcount = 0;
+ var protcookies = [];
+ for (var i = 0; i < cookies.length; i++)
+ {
+ if (cookies[i].isProtected)
+ {
+ protcookies[protectedcount] = cookies[i];
+ protectedcount++;
+ }
+ }
+ selector.protectCookies(protcookies);
+ //output protected cookies
+}
+function CookieColumnSort(column) {
+ lastCookieSortAscending =
+ SortTree(cookiesTree, cookiesTreeView, cookies,
+ column, lastCookieSortColumn, lastCookieSortAscending);
+ lastCookieSortColumn = column;
+}
+function DeleteCookie() {
+//DY - check if any selection is protected
+ var selections = getTreeSelections(cookiesTree);
+ var protect = false;
+ var i;
+ for (i=0; i<selections.length; i++) {
+ if (cookies[selections[i]].isProtected) {
+ protect = true;
+ }
+ }
+ if (!protect && i>0 ) {
+ DeleteSelectedItemFromTree(cookiesTree, cookiesTreeView,
+ cookies, deletedCookies,
+ "removeCookie", "removeAllCookies",
+ "protectCookie", "unprotectCookie");
+ if (!cookies.length) {
+ ;//ClearCookieProperties();
+ }
+
+ }
+}
+
+function getProtectedCookies()
+{
+ var tor_enabled = prefs.getBoolPref("extensions.torbutton.tor_enabled");
+ var cookiesAsXml = selector.getProtectedCookies(tor_enabled? "tor" : "nontor");
+
+ for (var i = 0; i < cookiesAsXml.cookie.length(); i++) {
+ var xml = cookiesAsXml.cookie[i];
+ var value = xml.toString();
+ var cname = xml. at name;
+ var host = xml. at host;
+ var path = xml. at path;
+ var expiry = xml. at expiry;
+ var isSecure = (xml. at isSecure == 1);
+ var isSession = (xml. at isSession == 1);
+ var isHttpOnly = (xml. at isHttpOnly == 1);
+ //this.logger.log(2, "Loading cookie: "+host+":"+cname+" until: "+expiry);
+ protectedCookies[i] = new Cookie(i,cname,value,true,host,(host.charAt(0)=="."),isHttpOnly, path, isSecure, isSession,
+ expiry, true)
+ }
+}
+
+//Tree Utils
+
+function SortTree(tree, view, table, column, lastSortColumn, lastSortAscending, updateSelection) {
+
+ // remember which item was selected so we can restore it after the sort
+ var selections = getTreeSelections(tree);
+ var selectedNumber = selections.length ? table[selections[0]].number : -1;
+
+ // determine if sort is to be ascending or descending
+ var ascending = (column == lastSortColumn) ? !lastSortAscending : true;
+
+ // do the sort or re-sort
+ var compareFunc = function compare(first, second) {
+ if (column=="isProtected") {
+ return second[column].toString().localeCompare(first[column].toString());
+ } else {
+ return first[column].toLowerCase().localeCompare(second[column].toLowerCase());
+ }
+ }
+ table.sort(compareFunc);
+ if (!ascending)
+ table.reverse();
+
+ // restore the selection
+ var selectedRow = -1;
+ if (selectedNumber>=0 && updateSelection) {
+ for (var s=0; s<table.length; s++) {
+ if (table[s].number == selectedNumber) {
+ // update selection
+ // note: we need to deselect before reselecting in order to trigger ...Selected()
+ if (oldTreeCode) {
+ tree.treeBoxObject.view.selection.select(-1);
+ tree.treeBoxObject.view.selection.select(s);
+ } else {
+ tree.view.selection.select(-1);
+ tree.view.selection.select(s);
+ }
+ selectedRow = s;
+ break;
+ }
+ }
+ }
+
+ // display the results
+ tree.treeBoxObject.invalidate();
+ if (selectedRow >= 0) {
+ tree.treeBoxObject.ensureRowIsVisible(selectedRow)
+ }
+
+ return ascending;
+}
+function FinalizeCookieDeletions() {
+ for (var c=0; c<deletedCookies.length; c++) {
+ cookiemanager.remove(deletedCookies[c].host,
+ deletedCookies[c].name,
+ deletedCookies[c].path,
+ false);
+ }
+ deletedCookies.length = 0;
+}
+function getTreeSelections(tree) {
+ var selections = [];
+ var select;
+
+ select = tree.view.selection;
+ if (select) {
+ var count = select.getRangeCount();
+ var min = new Object();
+ var max = new Object();
+ for (var i=0; i<count; i++) {
+ select.getRangeAt(i, min, max);
+ for (var k=min.value; k<=max.value; k++) {
+ if (k != -1) {
+ selections[selections.length] = k;
+ }
+ }
+ }
+ }
+ return selections;
+}
+function ProtectInTree
+ (tree, view, table, protButton, unprotButton, removeButton) {
+
+ var selections = getTreeSelections(tree);
+ for (var s=selections.length-1; s>= 0; s--) {
+ var i = selections[s];
+ table[i].isProtected = true;
+ }
+
+ //update tree view
+ tree.treeBoxObject.invalidate();
+//DY - Update selections
+ tree.treeBoxObject.ensureRowIsVisible(selections[0]);
+ // disable/enable buttons
+ document.getElementById(unprotButton).disabled = false;
+ document.getElementById(protButton).disabled = true;
+ document.getElementById(removeButton).disabled = true;
+}
+function UnProtectInTree
+ (tree, view, table, protButton, unprotButton, removeButton) {
+
+ var selections = getTreeSelections(tree);
+ for (var s=selections.length-1; s>= 0; s--) {
+ var i = selections[s];
+ table[i].isProtected = false;
+ }
+
+ //update tree view
+ tree.treeBoxObject.invalidate();
+//DY - Update selections
+ tree.treeBoxObject.ensureRowIsVisible(selections[0]);
+ // disable/enable buttons
+ document.getElementById(unprotButton).disabled = true;
+ document.getElementById(protButton).disabled = false;
+ document.getElementById(removeButton).disabled = false;
+}
+function DeleteAllCookies() {
+
+ DeleteAllFromTree(cookiesTree, cookiesTreeView,
+ cookies, deletedCookies,
+ "removeCookie", "removeAllCookies",
+ "protectCookie", "unprotectCookie");
+
+}
+function DeleteSelectedItemFromTree
+ (tree, view, table, deletedTable, removeButton, removeAllButton, protButton, unprotButton) {
+
+ var selections = getTreeSelections(tree);
+
+ tree.view.selection.clearSelection();
+
+ // remove selected items from list (by setting them to null) and place in deleted list
+ for (var s=selections.length-1; s>= 0; s--) {
+ var i = selections[s];
+ deletedTable[deletedTable.length] = table[i];
+ table[i] = null;
+ }
+ // collapse list by removing all the null entries
+ for (var j=0; j<table.length; j++) {
+ if (table[j] == null) {
+ var k = j;
+ while ((k < table.length) && (table[k] == null)) {
+ k++;
+ }
+ table.splice(j, k-j);
+ view.rowCount -= k - j;
+ tree.treeBoxObject.rowCountChanged(j, j - k);
+ }
+ }
+//DY - update selection and/or buttons
+ if (table.length) {
+
+//DY - update selection to previous (first of) selected position or bottom
+ var nextSelection = (selections[0] < table.length) ? selections[0] : table.length-1;
+
+ tree.view.selection.select(nextSelection);
+ tree.treeBoxObject.ensureRowIsVisible(nextSelection);
+ if (table[nextSelection].isProtected) {
+ document.getElementById(unprotButton).disabled = false;
+ document.getElementById(protButton).disabled = true;
+ } else {
+ document.getElementById(unprotButton).disabled = true;
+ document.getElementById(protButton).disabled = false;
+ }
+ } else {
+ // disable buttons
+ document.getElementById(removeButton).disabled = true;
+ document.getElementById(removeAllButton).disabled = true;
+ document.getElementById(unprotButton).disabled = true;
+ document.getElementById(protButton).disabled = true;
+ }
+}
+function DeleteAllFromTree
+ (tree, view, table, deletedTable, removeButton, removeAllButton, protButton, unprotButton) {
+
+ // remove items from table and place in deleted table
+ for (var i=0; i<table.length; i++) {
+//DY - only if unprotected
+ if (!table[i].isProtected) {
+ deletedTable[deletedTable.length] = table[i];
+ table[i] = null;
+ }
+ }
+
+ tree.view.selection.clearSelection();
+
+//DY - fix up tree
+ // collapse list by removing all the null entries
+ for (var j=0; j<table.length; j++) {
+ if (table[j] == null) {
+ var k = j;
+ while ((k < table.length) && (table[k] == null)) {
+ k++;
+ }
+ table.splice(j, k-j);
+ view.rowCount -= k - j;
+ tree.treeBoxObject.rowCountChanged(j, j - k);
+ }
+ }
+ // update selection and/or buttons
+ if (table.length) {
+ // update selection to top
+ if (oldTreeCode) {
+ tree.treeBoxObject.view.selection.select(0);
+ } else {
+ tree.view.selection.select(0);
+ }
+ tree.treeBoxObject.ensureRowIsVisible(0);
+ //if it exists is must already be protected
+ document.getElementById(unprotButton).disabled = false;
+ document.getElementById(protButton).disabled = true;
+ } else {
+ // disable all buttons
+ document.getElementById(removeButton).disabled = true;
+ document.getElementById(removeAllButton).disabled = true;
+ document.getElementById(unprotButton).disabled = true;
+ document.getElementById(protButton).disabled = true;
+ }
}
\ No newline at end of file
diff --git a/src/chrome/content/torcookiedialog.xul b/src/chrome/content/torcookiedialog.xul
index 3f39780..64ccc99 100644
--- a/src/chrome/content/torcookiedialog.xul
+++ b/src/chrome/content/torcookiedialog.xul
@@ -10,7 +10,7 @@
buttons="accept,cancel"
style="width: 30em;"
onload="initDialog();"
- ondialogaccept="return;"
+ ondialogaccept="acceptDialog();"
persist="screenX screenY width height">
<script src="chrome://torbutton/content/torbutton.js" type="application/x-javascript"/>
<script src="chrome://torbutton/content/torcookie.js" type="application/x-javascript"/>
@@ -34,8 +34,39 @@
<splitter class="tree-splitter"/>
<treecol id="nameCol" label="Name" flex="1"
onclick="CookieColumnSort('name', true);" persist="width"/>
+ <treecol id="pathCol" label="Path" flex="1"
+ onclick="CookieColumnSort('path', true);" persist="width"/>
+
</treecols>
<treechildren/>
</tree>
</vbox>
+ <groupbox>
+ <hbox>
+ <vbox>
+ <button id="protectCookie" disabled="true"
+ label="Protect Cookie"
+ oncommand="protectCookie();"/>
+ <button id="removeCookie" disabled="true"
+ label="Remove Cookie"
+ oncommand="DeleteCookie();"/>
+ </vbox>
+ <vbox>
+ <button id="unprotectCookie" disabled="true"
+ label="Unprotect Cookie"
+ oncommand="unprotectCookie();"/>
+ <button id="removeAllCookies"
+ label="Remove All But Protected"
+ oncommand="DeleteAllCookies();"/>
+ </vbox>
+ </hbox>
+ <hbox>
+ <radiogroup id="defaultCookieGroup">
+ <radio id="saveAllCookies" label="Protect All New Cookies" />
+ <radio id="donnotsaveCookies" label="Do Not Protect New Cookies" />
+ </radiogroup>
+ </hbox>
+ </groupbox>
+
</dialog>
+
diff --git a/src/components/cookie-jar-selector.js b/src/components/cookie-jar-selector.js
index f3d7c07..8ffe895 100644
--- a/src/components/cookie-jar-selector.js
+++ b/src/components/cookie-jar-selector.js
@@ -153,15 +153,93 @@ function CookieJarSelector() {
}
this._cookiesToFile = function(name) {
- var file = getProfileFile("cookies-" + name + ".xml");
- var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
- .createInstance(Ci.nsIFileOutputStream);
- foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
- var data = this["cookiesobj-" + name].toString();
- foStream.write(data, data.length);
- foStream.close();
+ var file = getProfileFile("cookies-" + name + ".xml");
+ var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
+ var data = this["cookiesobj-" + name].toString();
+ foStream.write(data, data.length);
+ foStream.close();
+ }
+ this._protectedCookiesToFile = function(name) {
+ var file = getProfileFile("protected-" + name + ".xml");
+ var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
+ var data = this["protected-" + name].toString();
+ foStream.write(data, data.length);
+ foStream.close();
+ }
+ this.getProtectedCookies = function(name) {
+ var file = getProfileFile("protected-" + name + ".xml");
+ if (!file.exists())
+ return null;
+ var data = "";
+ var fstream = Cc["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Ci.nsIFileInputStream);
+ var sstream = Cc["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(Ci.nsIScriptableInputStream);
+ fstream.init(file, -1, 0, 0);
+ sstream.init(fstream);
+
+ var str = sstream.read(4096);
+ while (str.length > 0) {
+ data += str;
+ str = sstream.read(4096);
+ }
+
+ sstream.close();
+ fstream.close();
+ try {
+ var ret = XML(data);
+ } catch(e) { // file has been corrupted; XXX: handle error differently
+ this.logger.log(5, "Cookies corrupted: "+e);
+ try {
+ file.remove(false); //XXX: is it necessary to remove it ?
+ var ret = null;
+ } catch(e2) {
+ this.logger.log(5, "Can't remove file "+e);
+ }
+ }
+ return ret;
}
+ this.protectCookies = function(cookies) {
+ var tor_enabled = this.prefs.getBoolPref("extensions.torbutton.tor_enabled");
+ var protname = tor_enabled? "tor" : "nontor";
+ this._writeProtectCookies(cookies,protname);
+ this._protectedCookiesToFile(protname);
+ }
+ this._writeProtectCookies = function(cookies, name) {
+ var cookieManager =
+ Cc["@mozilla.org/cookiemanager;1"]
+ .getService(Ci.nsICookieManager);
+ var cookiesEnum = cookieManager.enumerator;
+ var cookiesAsXml = new XML('<cookies/>');
+ for (var i = 0; i < cookies.length; i++) {
+ var cookie = cookies[i];
+ var xml = <cookie>{cookie.value}</cookie>;
+ //this.logger.log(2, "Saving cookie: "+cookie.host+":"+cookie.name+" until: "+cookie.expiry);
+ xml. at name = cookie.name;
+ xml. at host = cookie.host;
+ xml. at path = cookie.path;
+ if (cookie.isSecure)
+ xml. at isSecure = 1;
+ if (cookie.isSession) {
+ xml. at isSession = 1;
+ // session cookies get fucked up expiry. Give it 1yr if
+ // the user wants to save their session cookies
+ xml. at expiry = Date.now()/1000 + 365*24*60*60;
+ } else {
+ xml. at expiry = cookie.expires;
+ }
+ if (cookie.isHttpOnly)
+ xml. at isHttpOnly = 1;
+ // Save either session or non-session cookies this time around:
+ cookiesAsXml.appendChild(xml);
+ }
+ this["protected-" + name] = cookiesAsXml;
+ }
this._cookiesFromFile = function(name) {
var file = getProfileFile("cookies-" + name + ".xml");
if (!file.exists())
--
1.5.6.5
More information about the tor-commits
mailing list