diff --git a/README.rdoc b/README.rdoc
new file mode 100644
index 0000000..3cd9a2c
--- /dev/null
+++ b/README.rdoc
@@ -0,0 +1,14 @@
+= restclient-fx-patched
+
+Patched version of Firefox addon called RESTClient (https://addons.mozilla.org/en-US/firefox/addon/9780/)
+
+== changes
+- field values recovering when Firefox crashes
+- fixed header deleting (now you can use delete key when editing header name or value)
+- fixed display of json data (I've just moved css file to right place)
+- added ability to select and copy text from response (by adding right css style, that doesn't work always properly)
+- field values storing when Firefox is shutting down by user
+
+== todo
+- switch from TabRestored to TabRestoring for tab recovering
+- bind refresh key to send request action
diff --git a/chrome.manifest b/chrome.manifest
index c6636c1..db4ba78 100644
--- a/chrome.manifest
+++ b/chrome.manifest
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
content restclient jar:chrome/restclient.jar!/content/
locale restclient en-US jar:chrome/restclient.jar!/locale/en-US/
@@ -5,6 +6,13 @@ locale restclient zh-CN jar:chrome/restclient.jar!/locale/zh-CN/
locale restclient fr-FR jar:chrome/restclient.jar!/locale/fr-FR/
skin restclient classic/1.0 jar:chrome/restclient.jar!/skin/
+=======
+content restclient content/
+skin restclient classic/1.0 skin/
+locale restclient en-US locale/en-US/
+locale restclient fr-FR locale/fr-FR/
+locale restclient zh-CN locale/zh-CN/
+>>>>>>> d8e0f25c9b460181c151a203e810df78219c8574
overlay chrome://browser/content/browser.xul chrome://restclient/content/restclientOverlay.xul
style chrome://global/content/customizeToolbar.xul chrome://restclient/skin/overlay.css
\ No newline at end of file
diff --git a/content/JSONPrettyPrint.css b/content/JSONPrettyPrint.css
new file mode 100644
index 0000000..647a2cd
--- /dev/null
+++ b/content/JSONPrettyPrint.css
@@ -0,0 +1,69 @@
+/* The top-level container for all the formatted json or the error message if there is one */
+.json-content {
+ background-color: white;
+ border: 1px solid #999999;
+ margin-right: 10px;
+ padding: 10px 10px 10px 0;
+}
+
+.json-string {
+ color: green;
+ white-space: pre;
+}
+
+.json-null {
+ color: red;
+}
+
+.json-numeric {
+ color: red;
+}
+
+.json-bool {
+ color: blue;
+}
+
+/*
+ An object or an array
+*/
+.json-object {
+ padding-left: 10px;
+}
+
+/*
+ A member of an array or object.
+ - a member of an array is just a value
+ - a member of an object is a name/value pair
+*/
+.json-member {
+ padding-left: 10px;
+}
+
+/*
+ The label, for example:
+ {
+ validated: true
+ ^^^^^^^^^
+ }
+*/
+.json-label {
+ font-weight: bold;
+}
+
+/*
+ The braces for objects and arrays, ie {} or []
+*/
+.json-brace {
+ font-weight: bold;
+}
+
+/* The part that says there was an error, eg "There was an error" */
+.json-error-title {
+ font-weight: bold;
+}
+
+/* The actual error message, eg "Missing left bracket on line 6" */
+.json-error-message {
+
+}
+
diff --git a/content/XMLPrettyPrint.xsl b/content/XMLPrettyPrint.xsl
new file mode 100644
index 0000000..ba8450e
--- /dev/null
+++ b/content/XMLPrettyPrint.xsl
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+ <
+
+
+ />
+
+
+
+
+
+ <
+
+
+ >
+
+
+
+ </
+
+ >
+
+
+
+
+
+
+
+
+ <
+
+
+ >
+
+
+
+ </
+
+ >
+
+
+
+
+
+
+
+
+
+ =
+
+
+ "
+ #
+ attribute-href
+ setRequestUrl('');
+
+ "
+
+
+ ""
+
+
+
+
+
+
+
+
+
+
+
+
+ <?
+
+
+
+ ?>
+
+
+
+
+
+
+
+
+ <?
+
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ −
+
+
+
diff --git a/content/about.xul b/content/about.xul
new file mode 100644
index 0000000..5facb3c
--- /dev/null
+++ b/content/about.xul
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/base64.js b/content/base64.js
new file mode 100644
index 0000000..f392f0a
--- /dev/null
+++ b/content/base64.js
@@ -0,0 +1,142 @@
+/**
+*
+* Base64 encode / decode
+* http://www.webtoolkit.info/
+*
+**/
+
+var Base64 = {
+
+ // private property
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+ // public method for encoding
+ encode : function (input) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = Base64._utf8_encode(input);
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output = output +
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+
+ }
+
+ return output;
+ },
+
+ // public method for decoding
+ decode : function (input) {
+ var output = "";
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ while (i < input.length) {
+
+ enc1 = this._keyStr.indexOf(input.charAt(i++));
+ enc2 = this._keyStr.indexOf(input.charAt(i++));
+ enc3 = this._keyStr.indexOf(input.charAt(i++));
+ enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output = output + String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output = output + String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output = output + String.fromCharCode(chr3);
+ }
+
+ }
+
+ output = Base64._utf8_decode(output);
+
+ return output;
+
+ },
+
+ // private method for UTF-8 encoding
+ _utf8_encode : function (string) {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ },
+
+ // private method for UTF-8 decoding
+ _utf8_decode : function (utftext) {
+ var string = "";
+ var i = 0;
+ var c = c1 = c2 = 0;
+
+ while ( i < utftext.length ) {
+
+ c = utftext.charCodeAt(i);
+
+ if (c < 128) {
+ string += String.fromCharCode(c);
+ i++;
+ }
+ else if((c > 191) && (c < 224)) {
+ c2 = utftext.charCodeAt(i+1);
+ string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+ i += 2;
+ }
+ else {
+ c2 = utftext.charCodeAt(i+1);
+ c3 = utftext.charCodeAt(i+2);
+ string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ i += 3;
+ }
+
+ }
+
+ return string;
+ }
+
+}
\ No newline at end of file
diff --git a/content/header.xul b/content/header.xul
new file mode 100644
index 0000000..3729dc4
--- /dev/null
+++ b/content/header.xul
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/content/json2xul.js b/content/json2xul.js
new file mode 100644
index 0000000..2056879
--- /dev/null
+++ b/content/json2xul.js
@@ -0,0 +1,159 @@
+var json2xul = {
+
+ prettyPrintJSON: function(outputDiv, text){
+ // The box for output at the top-level
+ var jsonContent = document.createElement("vbox");
+ jsonContent.setAttribute("class", "json-content");
+
+ try {
+ // Parse the JSON
+ var parsedObj = JSON.parse(text);
+ // Turn the Javascript object into XUL objects
+ if (typeof parsedObj == 'object') {
+ var asXul = this.getXulObject(parsedObj);
+ jsonContent.appendChild(asXul);
+ } else {
+ var ex = {name: "JSON Parse error",
+ message: "JSON is invalid or top level element is not a JSON object"};
+ this.showParseError(jsonContent, ex);
+ }
+ } catch (e) {
+ this.showParseError(jsonContent, e);
+ }
+
+ outputDiv.appendChild(jsonContent);
+ },
+
+ showParseError: function(jsonContent, ex) {
+ var title = document.createElement("label");
+ title.setAttribute("value", "There was an error parsing the JSON document:");
+ title.setAttribute("class", "json-error-title");
+ jsonContent.appendChild(title);
+ if(ex) {
+ var message = document.createElement("label");
+ message.setAttribute("value", ex.name + ": " + ex.message);
+ message.setAttribute("class", "json-error-message");
+ jsonContent.appendChild(message);
+ }
+ },
+
+ getXulObject: function(value){
+ if (typeof value != 'object') {
+ return null;
+ }
+
+ // array
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+ var xulObj = document.createElement("vbox");
+ for (var i = 0; i < value.length; i ++) {
+ this.addXulChild(xulObj, value[i]);
+ }
+ return xulObj;
+ }
+
+ // object
+ var xulObj = document.createElement("vbox");
+ for (var prop in value) {
+ this.addXulChild(xulObj, value[prop], prop);
+ }
+
+ return xulObj;
+ },
+
+
+ addXulChild: function(xulObj, value, property){
+ var childIsObj = (typeof value == 'object' && value != null);
+ var childObj = childIsObj ? this.getXulObject(value) : this.getXulValue(value);
+
+ // If the value has a label (object properties will have labels)
+ if (property != null) {
+ var label = document.createElement("label");
+ label.setAttribute("class", "json-label");
+ label.setAttribute("value", property + ":");
+
+ // If the value is an object or array
+ if (childIsObj) {
+ var childIsArray = (Object.prototype.toString.apply(value) === '[object Array]');
+
+ var openBrace = document.createElement("label");
+ openBrace.setAttribute("value", childIsArray ? "[" : "{");
+ openBrace.setAttribute("class", "json-brace");
+ var closeBrace = document.createElement("label");
+ closeBrace.setAttribute("value", childIsArray ? "]" : "}");
+ closeBrace.setAttribute("class", "json-brace");
+
+ var xulMember = document.createElement("vbox");
+ xulMember.setAttribute("class", "json-object");
+
+ //
+ // Add it like this:
+ //
+ // label
+ // {
+ //
+ // }
+ //
+ xulMember.appendChild(label);
+ xulMember.appendChild(openBrace);
+ xulMember.appendChild(childObj);
+ xulMember.appendChild(closeBrace);
+ }
+ else {
+ // If the value is not an object or array, just add the label/value horizontally, ie
+ // label:
+ var xulMember = document.createElement("hbox");
+ xulMember.setAttribute("class", "json-member");
+ xulMember.appendChild(label);
+ xulMember.appendChild(childObj);
+ }
+ xulObj.appendChild(xulMember);
+ } else {
+ // If the value doesn't have a label, just add it directly
+ childObj.setAttribute("class", childObj.getAttribute("class") + " json-member");
+ xulObj.appendChild(childObj);
+ }
+ },
+ testCount: 0,
+ getXulValue: function(value){
+ var xulObj = document.createElement("description");
+ switch (typeof value) {
+ case 'object':
+ // null
+ if (!value) {
+ xulObj.setAttribute("value", 'null');
+ xulObj.setAttribute("class", "json-null");
+ return xulObj;
+ }
+ return null;
+
+ // string
+ case 'string':
+ xulObj.appendChild( document.createTextNode(String(value)) );
+ xulObj.setAttribute("class", "json-string");
+ return xulObj;
+
+ // number
+ case 'number':
+ xulObj.setAttribute("value", isFinite(value) ? String(value) : 'null');
+ xulObj.setAttribute("class", "json-numeric");
+ return xulObj;
+
+ // bool
+ case 'boolean':
+ xulObj.setAttribute("value", String(value));
+ xulObj.setAttribute("class", "json-bool");
+ return xulObj;
+
+ // At the time of writing, 'null' will never be returned by typeof,
+ // but one day the specification for the typeof function might be fixed
+ // so that it does.
+ case 'null':
+ xulObj.setAttribute("value", String(value));
+ xulObj.setAttribute("class", "json-null");
+ return xulObj;
+ }
+
+ return null;
+ }
+}
+
diff --git a/content/login.js b/content/login.js
new file mode 100644
index 0000000..7920f8e
--- /dev/null
+++ b/content/login.js
@@ -0,0 +1,161 @@
+function $(el) {
+ return document.getElementById(el);
+}
+
+function init(aEvent) {
+
+ var save = util.getBoolPref("restclient.save", false);
+ if(save){
+ $('securitySchemeRadio').selectedIndex = util.getIntPref("restclient.securityScheme", "");
+
+ $('login').value = util.getStrPref("restclient.login", "");
+ $('password').value = util.getStrPref("restclient.password", "");
+
+ $('signatureMethod').selectedIndex = util.getIntPref("restclient.sigMethodIndex", "");
+ $('consumerKey').value = util.getStrPref("restclient.consumerKey", "");
+ $('consumerSecret').value = util.getStrPref("restclient.consumerSecret", "");
+ $('accessorSecret').value = util.getStrPref("restclient.accessorSecret", "");
+ $('token').value = util.getStrPref("restclient.token", "");
+ $('tokenSecret').value = util.getStrPref("restclient.tokenSecret", "");
+ $('nonce').value = util.getStrPref("restclient.nonce", "");
+ $('version').value = util.getStrPref("restclient.version", "");
+ $('timestamp').value = util.getStrPref("restclient.timestamp", "");
+
+ $('autoNonce').checked = util.getBoolPref("restclient.autoNonce", "");
+ $('autoVersion').checked = util.getBoolPref("restclient.autoVersion", "");
+ $('autoTimestamp').checked = util.getBoolPref("restclient.autoTimestamp", "");
+
+ $('save').checked = true;
+ } else {
+ var args = window.arguments[0];
+
+ function valueIfNull(arg, value) { return arg == null ? value : arg};
+ function blankIfNull(arg) { return arg == null ? "" : arg; }
+
+ $('securitySchemeRadio').selectedIndex = valueIfNull(args.securityScheme, 0);
+
+ $('login').value = args.login;
+ $('password').value = args.password;
+
+ $('signatureMethod').selectedIndex = valueIfNull(args.sigMethodIndex, 0);
+
+ $('consumerKey').value = blankIfNull(args.consumerKey);
+ $('consumerSecret').value = blankIfNull(args.consumerSecret);
+ $('accessorSecret').value = blankIfNull(args.accessorSecret);
+ $('token').value = blankIfNull(args.token);
+ $('tokenSecret').value = blankIfNull(args.tokenSecret);
+ $('nonce').value = blankIfNull(args.nonce);
+ $('version').value = valueIfNull(args.version, "1.0");
+ $('timestamp').value = valueIfNull(args.timestamp, (new Date().getTime() / 1000));
+
+ $('autoNonce').checked = valueIfNull(args.autoNonce, true);
+ $('autoVersion').checked = valueIfNull(args.autoVersion, true);
+ $('autoTimestamp').checked = valueIfNull(args.autoTimestamp, true);
+ }
+
+ $('securitySchemeRadio').addEventListener('command', updateSecuritySchemeVisibility, false);
+ updateSecuritySchemeVisibility();
+
+ $('timestamp').addEventListener('change', updateTimestamp, false);
+ updateTimestamp();
+
+ $('autoNonce').addEventListener('command', autoNonceOnClick, false);
+ $('autoVersion').addEventListener('command', autoVersionOnClick, false);
+ $('autoTimestamp').addEventListener('command', autoTimestampOnClick, false);
+
+ autoNonceOnClick();
+ autoVersionOnClick();
+ autoTimestampOnClick();
+}
+
+function updateSecuritySchemeVisibility() {
+ var showBasic = ($('securitySchemeRadio').selectedIndex == 0);
+ $('securitySchemeBasic').style.display = showBasic ? '' : 'none';
+ $('securitySchemeOAuth').style.display = showBasic ? 'none' : '';
+}
+
+function autoNonceOnClick() { $('nonce').disabled = $('autoNonce').checked; };
+function autoVersionOnClick() { $('version').disabled = $('autoVersion').checked; };
+function autoTimestampOnClick() { $('timestamp').disabled = $('autoTimestamp').checked; };
+
+function updateTimestamp() {
+ var millis = $('timestamp').value * 1000;
+ var date = new Date();
+ date.setTime(millis);
+ $('timestampAsDate').value = date;
+}
+
+function saveChange() {
+ var save = $('save').checked;
+}
+
+function doOK() {
+ window.arguments[0].securityScheme = $('securitySchemeRadio').selectedIndex;
+
+ window.arguments[0].login = $('login').value;
+ window.arguments[0].password = $('password').value;
+
+ var sigMethodIndex = $('signatureMethod').selectedIndex;
+ var sigMethodText = 'HMAC-SHA1';
+ switch(sigMethodIndex) {
+ case 1:
+ sigMethodText = 'PLAINTEXT';
+ break;
+ /* Not supported by the oauth.js library
+ case 2:
+ sigMethodText = 'RSA-SHA1';
+ break;
+ */
+ }
+
+ window.arguments[0].sigMethodIndex = sigMethodIndex;
+ window.arguments[0].signatureMethod = sigMethodText;
+
+ window.arguments[0].consumerKey = $('consumerKey').value;
+ window.arguments[0].consumerSecret = $('consumerSecret').value;
+ window.arguments[0].accessorSecret = $('accessorSecret').value;
+ window.arguments[0].token = $('token').value;
+ window.arguments[0].tokenSecret = $('tokenSecret').value;
+ window.arguments[0].nonce = $('nonce').value;
+ window.arguments[0].version = getVersionString($('version').value);
+ window.arguments[0].timestamp = $('timestamp').value;
+
+ window.arguments[0].autoNonce = $('autoNonce').checked;
+ window.arguments[0].autoVersion = $('autoVersion').checked;
+ window.arguments[0].autoTimestamp = $('autoTimestamp').checked;
+
+ window.arguments[0].returnVal = true;
+
+ var save = $('save').checked;
+ if(save){
+ util.setIntPref("restclient.securityScheme", $('securitySchemeRadio').selectedIndex);
+
+ util.setStrPref("restclient.login", $('login').value);
+ util.setStrPref("restclient.password", $('password').value);
+ util.setBoolPref("restclient.save", true);
+
+ util.setIntPref("restclient.sigMethodIndex", $('signatureMethod').selectedIndex);
+ util.setStrPref("restclient.consumerKey", $('consumerKey').value);
+ util.setStrPref("restclient.consumerSecret", $('consumerSecret').value);
+ util.setStrPref("restclient.accessorSecret", $('accessorSecret').value);
+ util.setStrPref("restclient.token", $('token').value);
+ util.setStrPref("restclient.tokenSecret", $('tokenSecret').value);
+ util.setStrPref("restclient.nonce", $('nonce').value);
+ util.setStrPref("restclient.version", $('version').value);
+ util.setStrPref("restclient.timestamp", $('timestamp').value);
+
+ util.setBoolPref("restclient.autoNonce", $('autoNonce').checked);
+ util.setBoolPref("restclient.autoVersion", $('autoVersion').checked);
+ util.setBoolPref("restclient.autoTimestamp", $('autoTimestamp').checked);
+ }
+
+ return true;
+}
+
+function getVersionString(versionNum) {
+ if(versionNum.indexOf('.') > 0) {
+ return versionNum;
+ }
+ return versionNum + ".0";
+}
+
diff --git a/content/login.xul b/content/login.xul
new file mode 100644
index 0000000..671e81b
--- /dev/null
+++ b/content/login.xul
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/content/oauth.js b/content/oauth.js
new file mode 100644
index 0000000..55a7672
--- /dev/null
+++ b/content/oauth.js
@@ -0,0 +1,515 @@
+/*
+ * Copyright 2008 Netflix, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Here's some JavaScript software for implementing OAuth.
+
+ This isn't as useful as you might hope. OAuth is based around
+ allowing tools and websites to talk to each other. However,
+ JavaScript running in web browsers is hampered by security
+ restrictions that prevent code running on one website from
+ accessing data stored or served on another.
+
+ Before you start hacking, make sure you understand the limitations
+ posed by cross-domain XMLHttpRequest.
+
+ On the bright side, some platforms use JavaScript as their
+ language, but enable the programmer to access other web sites.
+ Examples include Google Gadgets, and Microsoft Vista Sidebar.
+ For those platforms, this library should come in handy.
+*/
+
+// The HMAC-SHA1 signature method calls b64_hmac_sha1, defined by
+// http://pajhome.org.uk/crypt/md5/sha1.js
+
+/* An OAuth message is represented as an object like this:
+ {method: "GET", action: "http://server.com/path", parameters: ...}
+
+ The parameters may be either a map {name: value, name2: value2}
+ or an Array of name-value pairs [[name, value], [name2, value2]].
+ The latter representation is more powerful: it supports parameters
+ in a specific sequence, or several parameters with the same name;
+ for example [["a", 1], ["b", 2], ["a", 3]].
+
+ Parameter names and values are NOT percent-encoded in an object.
+ They must be encoded before transmission and decoded after reception.
+ For example, this message object:
+ {method: "GET", action: "http://server/path", parameters: {p: "x y"}}
+ ... can be transmitted as an HTTP request that begins:
+ GET /path?p=x%20y HTTP/1.0
+ (This isn't a valid OAuth request, since it lacks a signature etc.)
+ Note that the object "x y" is transmitted as x%20y. To encode
+ parameters, you can call OAuth.addToURL, OAuth.formEncode or
+ OAuth.getAuthorization.
+
+ This message object model harmonizes with the browser object model for
+ input elements of an form, whose value property isn't percent encoded.
+ The browser encodes each value before transmitting it. For example,
+ see consumer.setInputs in example/consumer.js.
+ */
+var OAuth; if (OAuth == null) OAuth = {};
+
+OAuth.setProperties = function setProperties(into, from) {
+ if (into != null && from != null) {
+ for (var key in from) {
+ into[key] = from[key];
+ }
+ }
+ return into;
+}
+
+OAuth.setProperties(OAuth, // utility functions
+{
+ percentEncode: function percentEncode(s) {
+ if (s == null) {
+ return "";
+ }
+ if (s instanceof Array) {
+ var e = "";
+ for (var i = 0; i < s.length; ++s) {
+ if (e != "") e += '&';
+ e += percentEncode(s[i]);
+ }
+ return e;
+ }
+ s = encodeURIComponent(s);
+ // Now replace the values which encodeURIComponent doesn't do
+ // encodeURIComponent ignores: - _ . ! ~ * ' ( )
+ // OAuth dictates the only ones you can ignore are: - _ . ~
+ // Source: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:encodeURIComponent
+ s = s.replace(/\!/g, "%21");
+ s = s.replace(/\*/g, "%2A");
+ s = s.replace(/\'/g, "%27");
+ s = s.replace(/\(/g, "%28");
+ s = s.replace(/\)/g, "%29");
+ return s;
+ }
+,
+ decodePercent: function decodePercent(s) {
+ if (s != null) {
+ // Handle application/x-www-form-urlencoded, which is defined by
+ // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
+ s = s.replace(/\+/g, " ");
+ }
+ return decodeURIComponent(s);
+ }
+,
+ /** Convert the given parameters to an Array of name-value pairs. */
+ getParameterList: function getParameterList(parameters) {
+ if (parameters == null) {
+ return [];
+ }
+ if (typeof parameters != "object") {
+ return decodeForm(parameters + "");
+ }
+ if (parameters instanceof Array) {
+ return parameters;
+ }
+ var list = [];
+ for (var p in parameters) {
+ list.push([p, parameters[p]]);
+ }
+ return list;
+ }
+,
+ /** Convert the given parameters to a map from name to value. */
+ getParameterMap: function getParameterMap(parameters) {
+ if (parameters == null) {
+ return {};
+ }
+ if (typeof parameters != "object") {
+ return getParameterMap(decodeForm(parameters + ""));
+ }
+ if (parameters instanceof Array) {
+ var map = {};
+ for (var p = 0; p < parameters.length; ++p) {
+ var key = parameters[p][0];
+ if (map[key] === undefined) { // first value wins
+ map[key] = parameters[p][1];
+ }
+ }
+ return map;
+ }
+ return parameters;
+ }
+,
+ getParameter: function getParameter(parameters, name) {
+ if (parameters instanceof Array) {
+ for (var p = 0; p < parameters.length; ++p) {
+ if (parameters[p][0] == name) {
+ return parameters[p][1]; // first value wins
+ }
+ }
+ } else {
+ return OAuth.getParameterMap(parameters)[name];
+ }
+ return null;
+ }
+,
+ formEncode: function formEncode(parameters) {
+ var form = "";
+ var list = OAuth.getParameterList(parameters);
+ for (var p = 0; p < list.length; ++p) {
+ var value = list[p][1];
+ if (value == null) value = "";
+ if (form != "") form += '&';
+ form += OAuth.percentEncode(list[p][0])
+ +'='+ OAuth.percentEncode(value);
+ }
+ return form;
+ }
+,
+ decodeForm: function decodeForm(form) {
+ var list = [];
+ var nvps = form.split('&');
+ for (var n = 0; n < nvps.length; ++n) {
+ var nvp = nvps[n];
+ if (nvp == "") {
+ continue;
+ }
+ var equals = nvp.indexOf('=');
+ var name;
+ var value;
+ if (equals < 0) {
+ name = OAuth.decodePercent(nvp);
+ value = null;
+ } else {
+ name = OAuth.decodePercent(nvp.substring(0, equals));
+ value = OAuth.decodePercent(nvp.substring(equals + 1));
+ }
+ list.push([name, value]);
+ }
+ return list;
+ }
+,
+ setParameter: function setParameter(message, name, value) {
+ var parameters = message.parameters;
+ if (parameters instanceof Array) {
+ for (var p = 0; p < parameters.length; ++p) {
+ if (parameters[p][0] == name) {
+ if (value === undefined) {
+ parameters.splice(p, 1);
+ } else {
+ parameters[p][1] = value;
+ value = undefined;
+ }
+ }
+ }
+ if (value !== undefined) {
+ parameters.push([name, value]);
+ }
+ } else {
+ parameters = OAuth.getParameterMap(parameters);
+ parameters[name] = value;
+ message.parameters = parameters;
+ }
+ }
+,
+ setParameters: function setParameters(message, parameters) {
+ var list = OAuth.getParameterList(parameters);
+ for (var i = 0; i < list.length; ++i) {
+ OAuth.setParameter(message, list[i][0], list[i][1]);
+ }
+ }
+,
+ /** Fill in parameters to help construct a request message.
+ This function doesn't fill in every parameter.
+ The accessor object should be like:
+ {consumerKey:'foo', consumerSecret:'bar', accessorSecret:'nurn', token:'krelm', tokenSecret:'blah'}
+ The accessorSecret property is optional.
+ */
+ completeRequest: function completeRequest(message, accessor) {
+ if (message.method == null) {
+ message.method = "GET";
+ }
+
+ var map = OAuth.getParameterMap(message.parameters);
+ if (map.oauth_consumer_key == null) {
+ OAuth.setParameter(message, "oauth_consumer_key", accessor.consumerKey || "");
+ }
+ if (map.oauth_token == null && accessor.token != null) {
+ OAuth.setParameter(message, "oauth_token", accessor.token);
+ }
+ if (map.oauth_version == null) {
+ OAuth.setParameter(message, "oauth_version", "1.0");
+ }
+ if (map.oauth_timestamp == null) {
+ OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
+ }
+ if (map.oauth_nonce == null) {
+ OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
+ }
+ OAuth.SignatureMethod.sign(message, accessor);
+ }
+,
+ setTimestampAndNonce: function setTimestampAndNonce(message) {
+ OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
+ OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
+ }
+,
+ addToURL: function addToURL(url, parameters) {
+ newURL = url;
+ if (parameters != null) {
+ var toAdd = OAuth.formEncode(parameters);
+ if (toAdd.length > 0) {
+ var q = url.indexOf('?');
+ if (q < 0) newURL += '?';
+ else newURL += '&';
+ newURL += toAdd;
+ }
+ }
+ return newURL;
+ }
+,
+ /** Construct the value of the Authorization header for an HTTP request. */
+ getAuthorizationHeader: function getAuthorizationHeader(realm, parameters) {
+ var header = 'OAuth realm="' + OAuth.percentEncode(realm) + '"';
+ var list = OAuth.getParameterList(parameters);
+ for (var p = 0; p < list.length; ++p) {
+ var parameter = list[p];
+ var name = parameter[0];
+ if (name.indexOf("oauth_") == 0) {
+ header += ',' + OAuth.percentEncode(name) + '="' + OAuth.percentEncode(parameter[1]) + '"';
+ }
+ }
+ return header;
+ }
+,
+ timestamp: function timestamp() {
+ var d = new Date();
+ return Math.floor(d.getTime()/1000);
+ }
+,
+ nonce: function nonce(length) {
+ var chars = OAuth.nonce.CHARS;
+ var result = "";
+ for (var i = 0; i < length; ++i) {
+ var rnum = Math.floor(Math.random() * chars.length);
+ result += chars.substring(rnum, rnum+1);
+ }
+ return result;
+ }
+});
+
+OAuth.nonce.CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+
+/** Define a constructor function,
+ without causing trouble to anyone who was using it as a namespace.
+ That is, if parent[name] already existed and had properties,
+ copy those properties into the new constructor.
+ */
+OAuth.declareClass = function declareClass(parent, name, newConstructor) {
+ var previous = parent[name];
+ parent[name] = newConstructor;
+ if (newConstructor != null && previous != null) {
+ for (var key in previous) {
+ if (key != "prototype") {
+ newConstructor[key] = previous[key];
+ }
+ }
+ }
+ return newConstructor;
+}
+
+/** An abstract algorithm for signing messages. */
+OAuth.declareClass(OAuth, "SignatureMethod", function OAuthSignatureMethod(){});
+
+OAuth.setProperties(OAuth.SignatureMethod.prototype, // instance members
+{
+ /** Add a signature to the message. */
+ sign: function sign(message) {
+ var baseString = OAuth.SignatureMethod.getBaseString(message);
+ var signature = this.getSignature(baseString);
+ OAuth.setParameter(message, "oauth_signature", signature);
+ return signature; // just in case someone's interested
+ }
+,
+ /** Set the key string for signing. */
+ initialize: function initialize(name, accessor) {
+ var consumerSecret;
+ if (accessor.accessorSecret != null
+ && name.length > 9
+ && name.substring(name.length-9) == "-Accessor")
+ {
+ consumerSecret = accessor.accessorSecret;
+ } else {
+ consumerSecret = accessor.consumerSecret;
+ }
+ this.key = OAuth.percentEncode(consumerSecret)
+ +"&"+ OAuth.percentEncode(accessor.tokenSecret);
+ }
+});
+
+/* SignatureMethod expects an accessor object to be like this:
+ {tokenSecret: "lakjsdflkj...", consumerSecret: "QOUEWRI..", accessorSecret: "xcmvzc..."}
+ The accessorSecret property is optional.
+ */
+// Class members:
+OAuth.setProperties(OAuth.SignatureMethod, // class members
+{
+ sign: function sign(message, accessor) {
+ var name = OAuth.getParameterMap(message.parameters).oauth_signature_method;
+ if (name == null || name == "") {
+ name = "HMAC-SHA1";
+ OAuth.setParameter(message, "oauth_signature_method", name);
+ }
+ OAuth.SignatureMethod.newMethod(name, accessor).sign(message);
+ }
+,
+ /** Instantiate a SignatureMethod for the given method name. */
+ newMethod: function newMethod(name, accessor) {
+ var impl = OAuth.SignatureMethod.REGISTERED[name];
+ if (impl != null) {
+ var method = new impl();
+ method.initialize(name, accessor);
+ return method;
+ }
+ var err = new Error("signature_method_rejected");
+ var acceptable = "";
+ for (var r in OAuth.SignatureMethod.REGISTERED) {
+ if (acceptable != "") acceptable += '&';
+ acceptable += OAuth.percentEncode(r);
+ }
+ err.oauth_acceptable_signature_methods = acceptable;
+ throw err;
+ }
+,
+ /** A map from signature method name to constructor. */
+ REGISTERED : {}
+,
+ /** Subsequently, the given constructor will be used for the named methods.
+ The constructor will be called with no parameters.
+ The resulting object should usually implement getSignature(baseString).
+ You can easily define such a constructor by calling makeSubclass, below.
+ */
+ registerMethodClass: function registerMethodClass(names, classConstructor) {
+ for (var n = 0; n < names.length; ++n) {
+ OAuth.SignatureMethod.REGISTERED[names[n]] = classConstructor;
+ }
+ }
+,
+ /** Create a subclass of OAuth.SignatureMethod, with the given getSignature function. */
+ makeSubclass: function makeSubclass(getSignatureFunction) {
+ var superClass = OAuth.SignatureMethod;
+ var subClass = function() {
+ superClass.call(this);
+ };
+ subClass.prototype = new superClass();
+ // Delete instance variables from prototype:
+ // delete subclass.prototype... There aren't any.
+ subClass.prototype.getSignature = getSignatureFunction;
+ subClass.prototype.constructor = subClass;
+ return subClass;
+ }
+,
+ getBaseString: function getBaseString(message) {
+ var URL = message.action;
+ var q = URL.indexOf('?');
+ var parameters;
+ if (q < 0) {
+ parameters = message.parameters;
+ } else {
+ // Combine the URL query string with the other parameters:
+ parameters = OAuth.decodeForm(URL.substring(q + 1));
+ var toAdd = OAuth.getParameterList(message.parameters);
+ for (var a = 0; a < toAdd.length; ++a) {
+ parameters.push(toAdd[a]);
+ }
+ }
+ return OAuth.percentEncode(message.method.toUpperCase())
+ +'&'+ OAuth.percentEncode(OAuth.SignatureMethod.normalizeUrl(URL))
+ +'&'+ OAuth.percentEncode(OAuth.SignatureMethod.normalizeParameters(parameters));
+ }
+,
+ normalizeUrl: function normalizeUrl(url) {
+ var uri = OAuth.SignatureMethod.parseUri(url);
+ var scheme = uri.protocol.toLowerCase();
+ var authority = uri.authority.toLowerCase();
+ var dropPort = (scheme == "http" && uri.port == 80)
+ || (scheme == "https" && uri.port == 443);
+ if (dropPort) {
+ // find the last : in the authority
+ var index = authority.lastIndexOf(":");
+ if (index >= 0) {
+ authority = authority.substring(0, index);
+ }
+ }
+ var path = uri.path;
+ if (!path) {
+ path = "/"; // conforms to RFC 2616 section 3.2.2
+ }
+ // we know that there is no query and no fragment here.
+ return scheme + "://" + authority + path;
+ }
+,
+ parseUri: function parseUri (str) {
+ /* This function was adapted from parseUri 1.2.1
+ http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
+ */
+ var o = {key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
+ parser: {strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/ }};
+ var m = o.parser.strict.exec(str);
+ var uri = {};
+ var i = 14;
+ while (i--) uri[o.key[i]] = m[i] || "";
+ return uri;
+ }
+,
+ normalizeParameters: function normalizeParameters(parameters) {
+ if (parameters == null) {
+ return "";
+ }
+ var list = OAuth.getParameterList(parameters);
+ var sortable = [];
+ for (var p = 0; p < list.length; ++p) {
+ var nvp = list[p];
+ if (nvp[0] != "oauth_signature") {
+ sortable.push([ OAuth.percentEncode(nvp[0])
+ + " " // because it comes before any character that can appear in a percentEncoded string.
+ + OAuth.percentEncode(nvp[1])
+ , nvp]);
+ }
+ }
+ sortable.sort(function(a,b) {
+ if (a[0] < b[0]) return -1;
+ if (a[0] > b[0]) return 1;
+ return 0;
+ });
+ var sorted = [];
+ for (var s = 0; s < sortable.length; ++s) {
+ sorted.push(sortable[s][1]);
+ }
+ return OAuth.formEncode(sorted);
+ }
+});
+
+OAuth.SignatureMethod.registerMethodClass(["PLAINTEXT", "PLAINTEXT-Accessor"],
+ OAuth.SignatureMethod.makeSubclass(
+ function getSignature(baseString) {
+ return this.key;
+ }
+ ));
+
+OAuth.SignatureMethod.registerMethodClass(["HMAC-SHA1", "HMAC-SHA1-Accessor"],
+ OAuth.SignatureMethod.makeSubclass(
+ function getSignature(baseString) {
+ util.mlog('key:'+this.key);
+ util.mlog('base string:'+baseString);
+ b64pad = '=';
+ var signature = b64_hmac_sha1(this.key, baseString);
+ return signature;
+ }
+ ));
+
diff --git a/content/restclient.js b/content/restclient.js
new file mode 100644
index 0000000..3af1972
--- /dev/null
+++ b/content/restclient.js
@@ -0,0 +1,656 @@
+const HTMLNS = "http://www.w3.org/1999/xhtml";
+
+
+var restclient = {
+ passwordObject: null,
+ _stringBundle: null,
+
+ checkEnterKeyPress: function(evt){
+ switch( evt.keyCode ){
+ case 13:
+ restclient.doRequest();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+ },
+
+ checkDeleteKeyPress: function(evt){
+ switch( evt.keyCode ){
+ case 46:
+ restclient.deleteSelectedHeader();
+ break;
+ default:
+ break;
+ }
+ },
+
+ deleteSelectedHeader: function(){
+ var headerList = document.getElementById('headerList');
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+ if (headerList.view.selection.count > 0 && headerList.editingRow < 0) {
+ for (var i=reqHeaderChilds.childNodes.length-1 ; i>=0 ; i--) {
+ if (headerList.view.selection.isSelected(i))
+ reqHeaderChilds.removeChild(reqHeaderChilds.childNodes[i]);
+ }
+ }
+ },
+
+ clearRequestHeader: function(){
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+ for (var i=reqHeaderChilds.childNodes.length-1 ; i>=0 ; i--) {
+ reqHeaderChilds.removeChild(reqHeaderChilds.childNodes[i]);
+ }
+ },
+
+ init: function(){
+ var controller = new TabController();
+ controller.tbRequestUrl = "dupa tam";
+
+ this._stringBundle = document.getElementById("string-bundle");
+ this.updateSaveButton();
+ var that = this;
+ var requestMethodDropdown = document.getElementById('requestMethod');
+ var requestUrlDropdown = document.getElementById('tbRequestUrl');
+ requestMethodDropdown.addEventListener('command', function() { that.updateOAuthAuthorizationHeader(); }, false);
+ },
+
+ updateLogin: function(){
+ var login = document.getElementById("login-icon");
+ if( ! this.isAuthorizationHeaderSet() ){
+ login.label = this._stringBundle.getString("restclient.login");
+ login.checked = false;
+ }else{
+ login.label = this._stringBundle.getString("restclient.logout");
+ login.checked = true;
+ }
+ },
+
+ isAuthorizationHeaderSet: function() {
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+ for (var i=reqHeaderChilds.childNodes.length-1 ; i>=0 ; i--) {
+ if(reqHeaderChilds.childNodes[i].childNodes[0].childNodes[0].getAttribute('label') == "Authorization") {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ doLogin: function(){
+ var login = document.getElementById("login-icon");
+
+ // If the login button is already checked, clear the Authorization header and uncheck the button
+ if(login.checked) {
+ this.oAuthPasswordObject = null;
+ this.removeHttpRequestHeader("Authorization");
+ this.updateLogin();
+ return;
+ }
+
+ // If the login button is not already checked, display the login dialog
+ var passwordObject = new Object();
+ passwordObject.login = "";
+ passwordObject.password = "";
+ passwordObject.returnVal = false;
+ window.openDialog("chrome://restclient/content/login.xul", "login", "chrome,modal,dialog,resizable,centerscreen", passwordObject);
+
+ // If the user pressed cancel on the dialog, return
+ if (!passwordObject.returnVal) {
+ return;
+ }
+
+
+ // Basic authentication
+ if(passwordObject.securityScheme == 0) {
+ util.mlog("login[" + passwordObject.login + "] pass[" + passwordObject.password + "]");
+ var auth = "Basic " + Base64.encode(passwordObject.login + ':' + passwordObject.password);
+ util.mlog(auth);
+ this.setHttpRequestHeader("Authorization", auth);
+
+ // oAuth authentication
+ } else {
+ this.oAuthPasswordObject = passwordObject;
+ this.setOAuthAuthorizationHeader(passwordObject);
+ }
+
+ this.updateLogin();
+ },
+
+ updateOAuthAuthorizationHeader: function() {
+ // If the Authorization header and the oAuth credentials are already set,
+ // update the Authorization header.
+ if( this.isAuthorizationHeaderSet() && this.oAuthPasswordObject != null ) {
+ this.setOAuthAuthorizationHeader(this.oAuthPasswordObject);
+ }
+ },
+
+ setOAuthAuthorizationHeader: function(passwordObject) {
+ var parameters = { oauth_signature_method: passwordObject.signatureMethod };
+
+ var nullIfEmpty = function(str) { return (str == '') ? null : str; };
+ var accessor = { consumerKey: nullIfEmpty(passwordObject.consumerKey),
+ consumerSecret: nullIfEmpty(passwordObject.consumerSecret),
+ accessorSecret: nullIfEmpty(passwordObject.accessorSecret),
+ token: nullIfEmpty(passwordObject.token),
+ tokenSecret: nullIfEmpty(passwordObject.tokenSecret)
+ };
+
+
+ var action = document.getElementById('tbRequestUrl').value;
+ var message = { action: action, parameters: parameters };
+ message.method = document.getElementById('requestMethod').value;
+
+ parameters.oauth_version = passwordObject.autoVersion ? null : passwordObject.version;
+ parameters.oauth_nonce = passwordObject.autoNonce ? null : passwordObject.nonce;
+ parameters.oauth_timestamp = passwordObject.autoTimestamp ? null : passwordObject.timestamp;
+ OAuth.completeRequest(message, accessor);
+
+ // The realm is just the URL with the parameters and anchor removed
+ var realm = action;
+ if(realm.indexOf('?') >= 0) {
+ realm = realm.substring(0, realm.indexOf('?'));
+ }
+ if(realm.indexOf('#') >= 0) {
+ realm = realm.substring(0, realm.indexOf('#'));
+ }
+
+ var auth = OAuth.getAuthorizationHeader(realm, message.parameters);
+ this.setHttpRequestHeader("Authorization", auth);
+ },
+
+ addRequestHeader: function(){
+ var headerObject = new Object();
+ headerObject.name = "";
+ headerObject.value = "";
+ headerObject.returnVal = false;
+ window.openDialog("chrome://restclient/content/header.xul", "header", "chrome,modal,dialog,resizable,centerscreen", headerObject);
+
+ if (headerObject.returnVal) {
+ this.addHttpRequestHeader(headerObject.name, headerObject.value);
+ }
+ },
+
+ setHttpRequestHeader: function(headerKey, headerValue){
+ var header = this.getHttpRequestHeader(headerKey);
+ if(header != null) {
+ header.firstChild.childNodes[1].setAttribute('label', headerValue);
+ } else {
+ this.addHttpRequestHeader(headerKey, headerValue);
+ }
+ },
+
+ addHttpRequestHeader: function(headerKey, headerValue){
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+ var item = document.createElement('treeitem');
+ var row = document.createElement('treerow');
+ var c1 = document.createElement('treecell');
+ var c2 = document.createElement('treecell');
+ c1.setAttribute('label', headerKey);
+ c2.setAttribute('label', headerValue);
+ row.appendChild(c1);
+ row.appendChild(c2);
+ item.appendChild(row);
+ reqHeaderChilds.appendChild(item);
+ return (reqHeaderChilds.childNodes.length-1);
+ },
+
+ removeHttpRequestHeader: function(headerKey){
+ var header = this.getHttpRequestHeader(headerKey);
+ if(header != null) {
+ header.parentNode.removeChild(header);
+ }
+ },
+
+ getHttpRequestHeader: function(headerKey){
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+ for (var i=reqHeaderChilds.childNodes.length-1 ; i>=0 ; i--) {
+ if(reqHeaderChilds.childNodes[i].childNodes[0].childNodes[0].getAttribute('label') == headerKey) {
+ return reqHeaderChilds.childNodes[i];
+ }
+ }
+
+ return null;
+ },
+
+
+ saveHistory: function(strName, strUrl){
+ var gFormHistory = Components.classes["@mozilla.org/satchel/form-history;1"].getService(Components.interfaces.nsIFormHistory ?
+ Components.interfaces.nsIFormHistory :
+ Components.interfaces.nsIFormHistory2);
+ gFormHistory.addEntry(strName, strUrl);
+ //alert(gFormHistory.rowCount);
+ },
+
+ doRequest: function(){
+ var requestUrl = document.getElementById("tbRequestUrl").value;
+ var requestMethod = document.getElementById("requestMethod").selectedItem.getAttribute('label');
+ var requestBody = document.getElementById("tbRequestBody").value;
+ var headerList = document.getElementById('headerList');
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+
+ if(!util.isURL(requestUrl)){
+ alert('URL Error!');
+ return;
+ }
+
+ // Update the OAuth Authorization header.
+ // We need to do this here so that if the timestamp is set automatically it
+ // will be set at the time the request is sent, not at the time the Authorization
+ // request header is added
+ this.updateOAuthAuthorizationHeader();
+
+ this.saveHistory("rc-search-history", requestUrl);
+ util.mlog("Send request: method[" + requestMethod + "] Url[" + requestUrl + "]");
+ util.mlog("Body[" + requestMethod + "] Url[" + requestUrl + "]");
+ try {
+ var meter = document.getElementById("meter");
+ meter.mode = "undetermined";
+ meter.value="50%";
+ var xmlHttpRequest = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
+ xmlHttpRequest.open(requestMethod, requestUrl, true);
+ xmlHttpRequest.setRequestHeader("Accept-Language", null);
+
+ for(var i=reqHeaderChilds.childNodes.length-1 ; i>=0 ; i--){
+ var headerKey = reqHeaderChilds.childNodes[i].childNodes[0].childNodes[0].getAttribute('label')
+ var headerValue = reqHeaderChilds.childNodes[i].childNodes[0].childNodes[1].getAttribute('label')
+ util.mlog(headerKey);
+ util.mlog(headerValue);
+ xmlHttpRequest.setRequestHeader(headerKey, headerValue);
+ }
+
+ xmlHttpRequest.onerror = function() { restclient.doErrorResponse(this); };
+ xmlHttpRequest.onload = function() { restclient.doResponse(this); };
+ xmlHttpRequest.send(requestBody);
+ }
+ catch (e) {
+ util.mlog("getResource INFO:" + e.name + ": " + e.message);
+ }
+ },
+
+ doPostResponse: function(xmlHttpRequest) {
+ var meter = document.getElementById("meter");
+ meter.value="100%";
+ meter.mode = "determined";
+ restclient.clearResult();
+ },
+
+ doErrorResponse: function(xmlHttpRequest) {
+ restclient.doPostResponse();
+ restclient.addHttpHeader("Error", "Could not connect to server");
+ },
+
+ doResponse: function(xmlHttpRequest) {
+ restclient.doPostResponse();
+
+ var responseBody = document.getElementById('responseBody');
+ try {
+ var responseHeaderString = xmlHttpRequest.status + " " + xmlHttpRequest.statusText + "";
+ restclient.addHttpHeader("Status Code", responseHeaderString);
+
+ var headersText = xmlHttpRequest.getAllResponseHeaders();
+ var responseHeaders = headersText.split("\n");
+ for (i=0; i 0){
+ key = head.substring(0, fieldNameEnding);
+ headValue = head.substring(fieldNameEnding + 2, head.length);
+ headValue = headValue.replace(/\s$/, "");
+ restclient.addHttpHeader(key, headValue);
+ }
+ }
+ responseBody.value = xmlHttpRequest.responseText;
+
+ if (xmlHttpRequest.getResponseHeader("Content-Type").indexOf("json") >= 0) {
+ var outputDiv = document.getElementById("xmlContent");
+ json2xul.prettyPrintJSON(outputDiv, xmlHttpRequest.responseText);
+ return;
+ }
+
+ var xmlDoc = xmlHttpRequest.responseXML;
+ if(xmlDoc == null)
+ return;
+ var xslDocument = document.implementation.createDocument("", "dummy", null);
+ xslDocument.onload = function (evt) {
+ var xsltProcessor = new XSLTProcessor();
+ xsltProcessor.importStylesheet(xslDocument);
+ var resultFragment = xsltProcessor.transformToFragment(xmlDoc, document);
+ var oDiv = document.getElementById("xmlContent");
+ oDiv.appendChild(resultFragment);
+ };
+ xslDocument.load("chrome://restclient/content/XMLPrettyPrint.xsl");
+
+ }
+ catch (e) {
+ util.mlog("doResponse INFO:" + e.name + ": " + e.message);
+ }
+ },
+
+ clearRequest: function(){
+ var requestUrl = document.getElementById('tbRequestUrl');
+ var requestBody = document.getElementById('tbRequestBody');
+ var requestMethod = document.getElementById('requestMethod');
+ requestUrl.value = "";
+ requestBody.value = "";
+ requestMethod.selectedIndex = 0;
+ this.oAuthPasswordObject = null;
+ restclient.clearResult();
+ this.updateLogin();
+ this.requestBodyChange();
+ this.clearRequestHeader();
+ },
+
+ storeRestClientTab: function (theTab) {
+ var store = Components.classes["@mozilla.org/browser/sessionstore;1"].
+ getService(Components.interfaces.nsISessionStore);
+
+ //var theTab = aEvent.originalTarget;
+ //var theTabBrowser = gBrowser.getBrowserForTab(theTab);
+ //var tabDocument = theTabBrowser.contentDocument.wrappedJSObject;
+ var tabDocument = document;
+
+ var requestUrl = tabDocument.getElementById("tbRequestUrl").value;
+ var requestMethod = tabDocument.getElementById("requestMethod").selectedItem.getAttribute('label');
+ var requestBody = tabDocument.getElementById("tbRequestBody").value;
+ var reqHeaderChilds = tabDocument.getElementById('reqHeaderChilds');
+ var requestHeaderList = {};
+
+ for (var i=reqHeaderChilds.childNodes.length-1 ; i>=0 ; i--){
+ var headerKey = reqHeaderChilds.childNodes[i].childNodes[0].childNodes[0].getAttribute('label')
+ var headerValue = reqHeaderChilds.childNodes[i].childNodes[0].childNodes[1].getAttribute('label')
+
+ requestHeaderList[headerKey] = headerValue;
+ }
+
+ var tabController = new TabController();
+ tabController.requestUrl = requestUrl;
+ tabController.requestMethod = requestMethod;
+ tabController.requestBody = requestBody;
+ tabController.headerList = requestHeaderList;
+ store.setTabValue(theTab, "tab-controller", tabController.toString());
+ },
+
+ restoreRestClientTab: function (theTab) {
+ var store = Components.classes["@mozilla.org/browser/sessionstore;1"].
+ getService(Components.interfaces.nsISessionStore);
+
+ //var theTabBrowser = gBrowser.getBrowserForTab(theTab);
+
+ var tbRequestBody = document.getElementById('tbRequestBody');
+ var tbRequestUrl = document.getElementById('tbRequestUrl');
+ var requestMethod = document.getElementById('requestMethod');
+ var reqMethodChilds = document.getElementById('requestMethod').childNodes[0].childNodes;
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+ if (tbRequestBody != null) {
+ var data = store.getTabValue(theTab, "tab-controller");
+ var tabController = new TabController();
+ if (data != "undefined") {
+ tabController.fromString(data);
+ }
+
+ setRequestBody(tabController.requestBody);
+ setRequestUrl(tabController.requestUrl);
+
+ var reqHeaderList = tabController.headerList;
+ for (headerKey in reqHeaderList) {
+ var headerValue = reqHeaderList[headerKey];
+
+ this.addHttpRequestHeader(headerKey, headerValue);
+ }
+
+ setRequestMethod(tabController.requestMethod);
+ }
+ },
+
+
+ clearResult: function(){
+ restclient.initHttpHeader();
+ restclient.initHttpResponse();
+ },
+
+ initHttpHeader: function(){
+ var headerChilds = document.getElementById('headerChilds');
+ for (var i=headerChilds.childNodes.length-1 ; i>=0 ; i--)
+ headerChilds.removeChild(headerChilds.childNodes[i]);
+ },
+
+ initHttpResponse: function(){
+ var responseBody = document.getElementById('responseBody');
+ responseBody.value="";
+ var xmlContent = document.getElementById('xmlContent');
+ for (var i=xmlContent.childNodes.length-1 ; i>=0 ; i--)
+ xmlContent.removeChild(xmlContent.childNodes[i]);
+ },
+
+ addHttpHeader: function(headerKey, headerValue){
+ var headerChilds = document.getElementById('headerChilds');
+ var item = document.createElement('treeitem');
+ var row = document.createElement('treerow');
+ var c1 = document.createElement('treecell');
+ if(headerKey == "Status Code") {
+ if(util.startsWith(headerValue, "2")){
+ row.setAttribute('properties', "statusOk");
+ c1.setAttribute('properties', "statusOk");
+ }else{
+ row.setAttribute('properties', "statusError");
+ c1.setAttribute('properties', "statusError");
+ }
+ } else if(headerKey == "Error") {
+ row.setAttribute('properties', "statusError");
+ c1.setAttribute('properties', "statusError");
+ }
+
+ if(util.startsWith(headerKey.toLowerCase(),"location")){
+ util.mlog("location" + headerValue);
+ c1.setAttribute('properties', "location");
+ }
+ c1.setAttribute('label', headerKey + ": " + headerValue);
+ row.appendChild(c1);
+ item.appendChild(row);
+ headerChilds.appendChild(item);
+ return (headerChilds.childNodes.length-1);
+ },
+
+ copyResult: function(){
+ var tbRequestBody = document.getElementById('tbRequestBody');
+ var responseBody = document.getElementById('responseBody');
+ tbRequestBody.value = responseBody.value;
+ this.requestBodyChange();
+ },
+
+ saveRequest: function(){
+ var saveBtn = document.getElementById('save-icon');
+ if(saveBtn.disabled) return;
+
+ var tbRequestBody = document.getElementById('tbRequestBody');
+ var data = tbRequestBody.value;
+ if(util.trim(data) == ""){
+ alert("Nothing to save");
+ return;
+ }
+
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+ fp.init(window, "Save As", nsIFilePicker.modeSave);
+ fp.appendFilters(nsIFilePicker.filterXML | nsIFilePicker.filterText);
+ var res = fp.show();
+ if (res == nsIFilePicker.returnOK){
+ var thefile = fp.file;
+ var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Components.interfaces.nsIFileOutputStream);
+
+ // use 0x02 | 0x10 to open file for appending.
+ foStream.init(thefile, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
+ foStream.write(data, data.length);
+ foStream.close();
+ }
+ },
+
+
+ saveEntireRequest: function(){
+
+ var requestUrl = document.getElementById("tbRequestUrl").value;
+ var requestMethod = document.getElementById("requestMethod").selectedItem.getAttribute('label');
+ var requestBody = document.getElementById("tbRequestBody").value;
+ var reqHeaderChilds = document.getElementById('reqHeaderChilds');
+
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+ fp.init(window, "Save As", nsIFilePicker.modeSave);
+ fp.appendFilters(nsIFilePicker.filterText);
+
+ var index = 0;
+ var outputArray = new Array();
+ outputArray[index++] = requestUrl;
+ outputArray[index++] = requestMethod;
+ outputArray[index++] = requestBody;
+
+ // Now save headers in pairs
+ for (var i = reqHeaderChilds.childNodes.length-1; i>=0; i--) {
+ var headerKey = reqHeaderChilds.childNodes[i].childNodes[0].childNodes[0].getAttribute('label')
+ var headerValue = reqHeaderChilds.childNodes[i].childNodes[0].childNodes[1].getAttribute('label')
+ outputArray[index++] = headerKey;
+ outputArray[index++] = headerValue;
+ }
+
+ var output = JSON.stringify(outputArray);
+
+ var res = fp.show();
+ if (res == nsIFilePicker.returnOK) {
+ var thefile = fp.file;
+ var path = thefile.path;
+ if (path.match("\.txt$") != ".txt") {
+ thefile = Components.classes["@mozilla.org/file/local;1"]
+ .createInstance(Components.interfaces.nsILocalFile);
+ thefile.initWithPath(path + ".txt")
+ }
+ var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Components.interfaces.nsIFileOutputStream);
+
+ // use 0x02 | 0x10 to open file for appending.
+ foStream.init(thefile, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
+ foStream.write(output, output.length);
+ foStream.close();
+ }
+ },
+
+
+ loadRequest: function(){
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+ fp.init(window, "Select a File", nsIFilePicker.modeOpen);
+ fp.appendFilters(nsIFilePicker.filterXML | nsIFilePicker.filterText);
+ var res = fp.show();
+ if (res == nsIFilePicker.returnOK){
+ var thefile = fp.file;
+ var data = "";
+ var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Components.interfaces.nsIFileInputStream);
+ var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(Components.interfaces.nsIScriptableInputStream);
+ fstream.init(thefile, -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();
+ setRequestBody(data);
+ }
+ this.requestBodyChange();
+ },
+
+
+ loadEntireRequest: function(){
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+ fp.init(window, "Select a File", nsIFilePicker.modeOpen);
+ fp.appendFilters(nsIFilePicker.filterText);
+ var res = fp.show();
+ if (res == nsIFilePicker.returnOK){
+ this.clearRequest();
+ var thefile = fp.file;
+ var data = "";
+ var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Components.interfaces.nsIFileInputStream);
+ var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(Components.interfaces.nsIScriptableInputStream);
+ fstream.init(thefile, -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();
+ var tokens = JSON.parse(data);
+
+ setRequestUrl(tokens[0]);
+ setRequestMethod(tokens[1]);
+ setRequestBody(tokens[2])
+
+ var headerPairs = (tokens.length - 3) / 2;
+ for (index = 0; index < headerPairs; index++) {
+ var tokenIndex = (index * 2) + 3;
+ this.addHttpRequestHeader(tokens[tokenIndex], tokens[tokenIndex + 1]);
+ }
+ }
+ this.requestBodyChange();
+ },
+
+ updateSaveButton: function(){
+ var tbRequestBody = document.getElementById('tbRequestBody');
+ var saveBtn = document.getElementById('save-icon');
+ if(util.trim(tbRequestBody.value) == ""){
+ saveBtn.disabled = true;
+ }else
+ saveBtn.disabled = false;
+ },
+
+ requestBodyChange: function(ev){
+ util.mlog("input:");
+ this.updateSaveButton();
+ }
+}
+
+function setRequestUrl(strUrl){
+ var requestUrl = document.getElementById("tbRequestUrl");
+ requestUrl.value = strUrl;
+ //alert(strUrl);
+}
+
+function setRequestMethod(requestMethod){
+ var reqMethodSelect = document.getElementById('requestMethod');
+ var reqMethodChilds = reqMethodSelect.childNodes[0].childNodes;
+
+ var child = null;
+ for (childIndex in reqMethodChilds) {
+ child = reqMethodChilds[childIndex];
+ if (typeof child == 'object' && child.getAttribute('label') == requestMethod) {
+ break;
+ }
+ }
+ if (child != null) {
+ reqMethodSelect.selectedItem = child;
+ }
+}
+
+function setRequestBody(body){
+ document.getElementById('tbRequestBody').value = body;
+}
+
+window.addEventListener("load", function() {restclient.init();}, false);
diff --git a/content/restclient.xul b/content/restclient.xul
new file mode 100644
index 0000000..4ca6f14
--- /dev/null
+++ b/content/restclient.xul
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/restclientOverlay.js b/content/restclientOverlay.js
new file mode 100644
index 0000000..9e105c1
--- /dev/null
+++ b/content/restclientOverlay.js
@@ -0,0 +1,64 @@
+function restoreRestClientTab(aEvent) {
+ var theTab = aEvent.originalTarget;
+ var theTabBrowser = gBrowser.getBrowserForTab(theTab);
+ var tabWindow = gBrowser.getBrowserForTab(theTab).contentWindow.wrappedJSObject;
+
+ if (typeof tabWindow.restclient != "undefined") {
+ tabWindow.restclient.restoreRestClientTab(theTab);
+
+ // bring back the icon
+ var func = function () { gBrowser.setIcon(theTab, "chrome://restclient/skin/logo16.png"); };
+ setTimeout(func, 500);
+ }
+}
+document.addEventListener("SSTabRestored", restoreRestClientTab, false);
+
+
+function storeRestClientTab(aEvent) {
+ var theTab = aEvent.originalTarget;
+ var theTabBrowser = gBrowser.getBrowserForTab(theTab);
+ var tabWindow = gBrowser.getBrowserForTab(theTab).contentWindow.wrappedJSObject;
+
+ if (typeof tabWindow.restclient != "undefined") {
+ tabWindow.restclient.storeRestClientTab(theTab);
+ }
+}
+document.addEventListener("SSTabClosing", storeRestClientTab, false);
+
+
+function ShutdownObserver() {}
+ShutdownObserver.prototype = {
+ observe: function(subject, topic, data) {
+
+ var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindow);
+ var container = mainWindow.getBrowser().tabContainer;
+ for (var i=0; i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/sha1.js b/content/sha1.js
new file mode 100644
index 0000000..618dfda
--- /dev/null
+++ b/content/sha1.js
@@ -0,0 +1,203 @@
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+/*
+ * 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_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+ return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << (24 - len % 32);
+ x[((len + 64 >> 9) << 4) + 15] = len;
+
+ var w = Array(80);
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+ var e = -1009589776;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+ var olde = e;
+
+ for(var j = 0; j < 80; j++)
+ {
+ if(j < 16) w[j] = x[i + j];
+ else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+ var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+ safe_add(safe_add(e, w[j]), sha1_kt(j)));
+ e = d;
+ d = c;
+ c = rol(b, 30);
+ b = a;
+ a = t;
+ }
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ e = safe_add(e, olde);
+ }
+ return Array(a, b, c, d, e);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+ if(t < 20) return (b & c) | ((~b) & d);
+ if(t < 40) return b ^ c ^ d;
+ if(t < 60) return (b & c) | (b & d) | (c & d);
+ return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
+ (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Calculate the HMAC-SHA1 of a key and some data
+ */
+function core_hmac_sha1(key, data)
+{
+ var bkey = str2binb(key);
+ if(bkey.length > 16) bkey = core_sha1(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_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
+ return core_sha1(opad.concat(hash), 512 + 160);
+}
+
+/*
+ * 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 rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert an 8-bit or 16-bit string to an array of big-endian words
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
+ */
+function str2binb(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) << (32 - chrsz - i%32);
+ return bin;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2str(bin)
+{
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
+ return str;
+}
+
+/*
+ * Convert an array of big-endian words to a hex string.
+ */
+function binb2hex(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] >> ((3 - i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+/*
+ * Convert an array of big-endian words to a base-64 string
+ */
+function binb2b64(binarray)
+{
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * (3 - (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;
+}
+
diff --git a/content/tabcontroller.js b/content/tabcontroller.js
new file mode 100644
index 0000000..3670e7a
--- /dev/null
+++ b/content/tabcontroller.js
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Object used to store information on a per tab basis. This should be passed
+ * into the TabListener as the func argument.
+ *
+ * http://richwklein.com/2009/07/21/tab-listener/
+ *
+ * @version 1.0
+ ******************************************************************************/
+function TabController() {}
+TabController.prototype = {
+
+ /**
+ * IMPORTANT!!! Add the properties here that you need to keep track of.
+ */
+ requestUrl: null,
+ requestMethod: null,
+ requestBody: null,
+ headerList: null,
+
+
+
+ /**
+ * Called when a tab is being restored so that we restore the controllers state.
+ *
+ * @param data A string of json data stored in the session store.
+ */
+ fromString: function TabController_fromString(data) {
+ var json = window.JSON.parse(data);
+ for (var property in json)
+ this[property] = json[property];
+ },
+
+ /**
+ * Called when a tab is being closed so that we can store the controllers state.
+ *
+ * @returns A string of json data stored in the session store.
+ */
+ toString: function TabController_toString() {
+ var json = {};
+ for (var property in this)
+ json[property] = this[property]
+ return window.JSON.stringify(json);
+ }
+};
diff --git a/content/util.js b/content/util.js
new file mode 100644
index 0000000..5d77926
--- /dev/null
+++ b/content/util.js
@@ -0,0 +1,216 @@
+var util = {
+
+ //-----------------------------------------------------------------------------
+
+ mlog : function(text) {
+ Components.classes["@mozilla.org/consoleservice;1"]
+ .getService(Components.interfaces.nsIConsoleService)
+ .logStringMessage("RESTClient: "+text);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ addEventListener : function(obj, type, listener) {
+ if (typeof(obj) == "string") obj = document.getElementById(obj);
+ if (obj) obj.addEventListener(type, listener, false);
+ },
+
+ removeEventListener : function(obj, type, listener) {
+ if (typeof(obj) == "string") obj = document.getElementById(obj);
+ if (obj) obj.removeEventListener(type, listener, false);
+ },
+
+ addEventListenerByTagName : function(tag, type, listener) {
+ var objs = document.getElementsByTagName(tag);
+ for (var i = 0; i < objs.length; i++) {
+ objs[i].addEventListener(type, listener, false);
+ }
+ },
+
+ removeEventListenerByTagName : function(tag, type, listener) {
+ var objs = document.getElementsByTagName(tag);
+ for (var i = 0; i < objs.length; i++) {
+ objs[i].removeEventListener(type, listener, false);
+ }
+ },
+
+ //-----------------------------------------------------------------------------
+
+ hookCode : function(orgFunc, orgCode, myCode) {
+ if (orgFunc == "") return;
+ switch (orgCode) {
+ case "{":
+ orgCode = /{/;
+ myCode = "{"+myCode;
+ break;
+ case "}":
+ orgCode = /}$/;
+ myCode = myCode+"}";
+ break;
+ default:
+ }
+ try { eval(orgFunc + "=" + eval(orgFunc).toString().replace(orgCode, myCode)); }catch(e){ util.mlog("Failed to hook function: "+orgFunc); }
+ },
+
+ hookAttr : function(parentNode, attrName, myFunc) {
+ if (typeof(parentNode) == "string") parentNode = document.getElementById(parentNode);
+ try { parentNode.setAttribute(attrName, myFunc + parentNode.getAttribute(attrName)); }catch(e){ util.mlog("Failed to hook attribute: "+attrName); }
+ },
+
+ hookProp : function(parentNode, propName, myGetter, mySetter) {
+ var oGetter = parentNode.__lookupGetter__(propName);
+ var oSetter = parentNode.__lookupSetter__(propName);
+ if (oGetter && myGetter) myGetter = oGetter.toString().replace(/{/, "{"+myGetter.toString().replace(/^.*{/,"").replace(/.*}$/,""));
+ if (oSetter && mySetter) mySetter = oSetter.toString().replace(/{/, "{"+mySetter.toString().replace(/^.*{/,"").replace(/.*}$/,""));
+ if (!myGetter) myGetter = oGetter;
+ if (!mySetter) mySetter = oSetter;
+ if (myGetter) try { eval('parentNode.__defineGetter__(propName, '+ myGetter.toString() +');'); }catch(e){ util.mlog("Failed to hook property Getter: "+propName); }
+ if (mySetter) try { eval('parentNode.__defineSetter__(propName, '+ mySetter.toString() +');'); }catch(e){ util.mlog("Failed to hook property Setter: "+propName); }
+ },
+
+ //-----------------------------------------------------------------------------
+
+ trim : function(s) {
+ if (s) return s.replace(/^\s+/g,"").replace(/\s+$/g,""); else return "";
+ },
+
+ startsWith : function(s, prefix) {
+ if (s) return( (s.substring(0, prefix.length) == prefix) ); else return false;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ getBoolPref : function(prefName, defval) {
+ var result = defval;
+ var prefservice = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ var prefs = prefservice.getBranch("extensions.porphyry.");
+ if (prefs.getPrefType(prefName) == prefs.PREF_BOOL) {
+ try { result = prefs.getBoolPref(prefName); }catch(e){}
+ }
+ return(result);
+ },
+
+ getIntPref : function(prefName, defval) {
+ var result = defval;
+ var prefservice = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ var prefs = prefservice.getBranch("extensions.porphyry.");
+ if (prefs.getPrefType(prefName) == prefs.PREF_INT) {
+ try { result = prefs.getIntPref(prefName); }catch(e){}
+ }
+ return(result);
+ },
+
+ getStrPref : function(prefName, defval) {
+ var result = defval;
+ var prefservice = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ var prefs = prefservice.getBranch("extensions.porphyry.");
+ if (prefs.getPrefType(prefName) == prefs.PREF_STRING) {
+ try { result = prefs.getComplexValue(prefName, Components.interfaces.nsISupportsString).data; }catch(e){}
+ }
+ return(result);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ setBoolPref : function(prefName, value) {
+ var prefservice = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ var prefs = prefservice.getBranch("extensions.porphyry.");
+ try { prefs.setBoolPref(prefName, value); } catch(e){}
+ },
+
+ setIntPref : function(prefName, value) {
+ var prefservice = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ var prefs = prefservice.getBranch("extensions.porphyry.");
+ try { prefs.setIntPref(prefName, value); } catch(e){}
+ },
+
+ setStrPref : function(prefName, value) {
+ var prefservice = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ var prefs = prefservice.getBranch("extensions.porphyry.");
+ var sString = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
+ sString.data = value;
+ try { prefs.setComplexValue(prefName, Components.interfaces.nsISupportsString, sString); } catch(e){}
+ },
+
+ //-----------------------------------------------------------------------------
+
+ getDefaultCharset : function(defval) {
+ var charset = util.getStrPref("porphyry.intl.charset.default", "");
+ if (charset.length) return charset;
+ var gPrefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
+ if(gPrefs.prefHasUserValue("intl.charset.default")) {
+ return gPrefs.getCharPref("intl.charset.default");
+ } else {
+ var strBundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
+ var intlMess = strBundle.createBundle("chrome://global-platform/locale/intl.properties");
+ try {
+ return intlMess.GetStringFromName("intl.charset.default");
+ } catch(e) {
+ return defval;
+ }
+ }
+ },
+
+ convertToUTF8 : function(data, charset) {
+ try {
+ data = decodeURI(data);
+ }catch(e){
+ if (!charset) charset = gporphyry.getDefaultCharset();
+ if (charset) {
+ var uc = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+ try {
+ uc.charset = charset;
+ data = uc.ConvertToUnicode(unescape(data));
+ data = decodeURI(data);
+ }catch(e){}
+ uc.Finish();
+ }
+ }
+ return data;
+ },
+
+ convertToASCII : function(data, charset) {
+ if (!charset) charset = gporphyry.getDefaultCharset();
+ if (charset) {
+ var uc = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+ uc.charset = charset;
+ try {
+ data = uc.ConvertFromUnicode(data);
+ }catch(e){
+ data = uc.ConvertToUnicode(unescape(data));
+ data = decodeURI(data);
+ data = uc.ConvertFromUnicode(data);
+ }
+ uc.Finish();
+ }
+ return data;
+ },
+
+ //-----------------------------------------------------------------------------
+ isURL : function (url) {
+ /*var rx = new RegExp("http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-\\+ ./?%:&=#\\[\\]]*)?");
+ var matches = rx.exec(url);
+ return (matches != null && url == matches[0]); */
+ var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
+ return regexp.test(url);
+ },
+
+ getUrlDomain : function(url) {
+ if (url && !gporphyry.startsWith(url, "about:")) {
+ if (/^file:\/\/.*/.test(url)) return url;
+ var matches = url.match(/^([A-Za-z]+:\/+)*([^\:^\/]+):?(\d*)(\/.*)*/);
+ if (matches) url = matches[1]+matches[2]+(matches[3]==""?"":":"+matches[3])+"/";
+ }
+ return url;
+ },
+
+ getUrlHost : function(url) {
+ if (url && !gporphyry.startsWith(url, "about:")) {
+ if (/^file:\/\/.*/.test(url)) return url;
+ var matches = url.match(/^([A-Za-z]+:\/+)*([^\:^\/]+):?(\d*)(\/.*)*/);
+ if (matches) url = matches[2];
+ }
+ return url;
+ }
+//-----------------------------------------------------------------------------
+}
\ No newline at end of file
diff --git a/install.rdf b/install.rdf
index d1460ec..6c5c2fc 100644
--- a/install.rdf
+++ b/install.rdf
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
-
\ No newline at end of file
+
+=======
+
+
+
+
+
+
+
+>>>>>>> d8e0f25c9b460181c151a203e810df78219c8574
diff --git a/locale/en-US/header.dtd b/locale/en-US/header.dtd
new file mode 100644
index 0000000..1558027
--- /dev/null
+++ b/locale/en-US/header.dtd
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/locale/en-US/login.dtd b/locale/en-US/login.dtd
new file mode 100644
index 0000000..0cfbea1
--- /dev/null
+++ b/locale/en-US/login.dtd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/locale/en-US/restclient.dtd b/locale/en-US/restclient.dtd
new file mode 100644
index 0000000..3f5a9be
--- /dev/null
+++ b/locale/en-US/restclient.dtd
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/locale/en-US/restclient.properties b/locale/en-US/restclient.properties
new file mode 100644
index 0000000..6bb5533
--- /dev/null
+++ b/locale/en-US/restclient.properties
@@ -0,0 +1,2 @@
+restclient.login = Login
+restclient.logout = Logout
\ No newline at end of file
diff --git a/locale/fr-FR/header.dtd b/locale/fr-FR/header.dtd
new file mode 100644
index 0000000..ac62586
--- /dev/null
+++ b/locale/fr-FR/header.dtd
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/locale/fr-FR/login.dtd b/locale/fr-FR/login.dtd
new file mode 100644
index 0000000..d70fd64
Binary files /dev/null and b/locale/fr-FR/login.dtd differ
diff --git a/locale/fr-FR/restclient.dtd b/locale/fr-FR/restclient.dtd
new file mode 100644
index 0000000..ee5192f
--- /dev/null
+++ b/locale/fr-FR/restclient.dtd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/locale/fr-FR/restclient.properties b/locale/fr-FR/restclient.properties
new file mode 100644
index 0000000..0411f07
--- /dev/null
+++ b/locale/fr-FR/restclient.properties
@@ -0,0 +1,2 @@
+restclient.login = Se_connecter
+restclient.logout = Se_Déconnecter
diff --git a/locale/zh-CN/header.dtd b/locale/zh-CN/header.dtd
new file mode 100644
index 0000000..a1412de
--- /dev/null
+++ b/locale/zh-CN/header.dtd
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/locale/zh-CN/login.dtd b/locale/zh-CN/login.dtd
new file mode 100644
index 0000000..906e358
--- /dev/null
+++ b/locale/zh-CN/login.dtd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/locale/zh-CN/restclient.dtd b/locale/zh-CN/restclient.dtd
new file mode 100644
index 0000000..5208396
--- /dev/null
+++ b/locale/zh-CN/restclient.dtd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/locale/zh-CN/restclient.properties b/locale/zh-CN/restclient.properties
new file mode 100644
index 0000000..9345b3e
--- /dev/null
+++ b/locale/zh-CN/restclient.properties
@@ -0,0 +1,2 @@
+restclient.login = 登录
+restclient.logout = 登出
\ No newline at end of file
diff --git a/skin/JSONPrettyPrint.css b/skin/JSONPrettyPrint.css
new file mode 100644
index 0000000..6b8912a
--- /dev/null
+++ b/skin/JSONPrettyPrint.css
@@ -0,0 +1,74 @@
+/* The top-level container for all the formatted json or the error message if there is one */
+.json-content {
+ background-color: white;
+ border: 1px solid #999999;
+ margin-right: 10px;
+ padding: 10px 10px 10px 0;
+}
+
+.json-string {
+ color: green;
+ white-space: pre;
+}
+
+.json-null {
+ color: red;
+}
+
+.json-numeric {
+ color: red;
+}
+
+.json-bool {
+ color: blue;
+}
+
+/*
+ An object or an array
+*/
+.json-object {
+ padding-left: 10px;
+}
+
+/*
+ A member of an array or object.
+ - a member of an array is just a value
+ - a member of an object is a name/value pair
+*/
+.json-member {
+ padding-left: 10px;
+}
+
+/*
+ The label, for example:
+ {
+ validated: true
+ ^^^^^^^^^
+ }
+*/
+.json-label {
+ font-weight: bold;
+}
+
+/*
+ The braces for objects and arrays, ie {} or []
+*/
+.json-brace {
+ font-weight: bold;
+}
+
+/* The part that says there was an error, eg "There was an error" */
+.json-error-title {
+ font-weight: bold;
+}
+
+/* The actual error message, eg "Missing left bracket on line 6" */
+.json-error-message {
+
+}
+
+#xmlContent description {
+ -moz-user-select: text;
+}
+
+
diff --git a/skin/Thumbs.db b/skin/Thumbs.db
new file mode 100644
index 0000000..f25cf11
Binary files /dev/null and b/skin/Thumbs.db differ
diff --git a/skin/XMLPrettyPrint.css b/skin/XMLPrettyPrint.css
new file mode 100644
index 0000000..08e3f45
--- /dev/null
+++ b/skin/XMLPrettyPrint.css
@@ -0,0 +1,163 @@
+@charset "utf-8";
+/* ***** 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 Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Blake Ross
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+@namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
+
+
+#viewsource {
+ font-family: -moz-fixed;
+ font-weight: normal;
+ color: black;
+ white-space: pre;
+}
+#viewsource.wrap {
+ white-space: -moz-pre-wrap;
+}
+pre {
+ font: inherit;
+ color: inherit;
+ white-space: inherit;
+ margin: 0;
+}
+.start-tag {
+ color: purple;
+ font-weight: bold;
+}
+.end-tag {
+ color: purple;
+ font-weight: bold;
+}
+.comment {
+ color: green;
+ font-style: italic;
+}
+.cdata {
+ color: #CC0066;
+}
+.doctype {
+ color: steelblue;
+ font-style: italic;
+}
+.pi {
+ color: orchid;
+ font-style: italic;
+}
+.entity {
+ color:#FF4500;
+ font-weight: normal;
+}
+.text {
+ -moz-user-select: text;
+ font-weight: normal;
+}
+.attribute-name {
+ color: black;
+ font-weight: bold;
+}
+.attribute-value {
+ color: blue;
+ font-weight: normal;
+}
+.summary {
+ display: block;
+ background-color: #FFFFCC;
+ width: 90%;
+ border: solid;
+ border-width: 1pt;
+ font-family: sans-serif;
+}
+.popup {
+ font-weight: normal;
+}
+.markupdeclaration {
+ color: steelblue;
+ font-style: italic;
+}
+.error, .error > .start-tag, .error > .end-tag,
+.error > .comment, .error > .cdata, .error > .doctype,
+.error > .pi, .error > .entity, .error > .attribute-name,
+.error > .attribute-value {
+ color: red;
+ font-weight: bold;
+}
+
+
+#header {
+ background-color: #ccc;
+ border-bottom: 3px solid black;
+ padding: 0.5em;
+ margin-bottom: 1em;
+}
+
+table {
+ border-spacing: 0;
+ margin: 0;
+}
+
+td {
+ padding: 0;
+}
+
+.indent {
+ margin-left: 1em;
+}
+
+.spacer {
+ width: 1em;
+}
+
+.expander {
+ cursor: pointer;
+ -moz-user-select: none;
+ vertical-align: top;
+ text-align: center;
+}
+
+.expander-closed > * > .expander-content {
+ display: none;
+}
+
+.comment {
+ font-family: monospace;
+ white-space: pre;
+}
+
+.attribute-href {
+ color: blue;
+ font-weight: normal;
+}
\ No newline at end of file
diff --git a/skin/logo16.png b/skin/logo16.png
new file mode 100644
index 0000000..0dcfe32
Binary files /dev/null and b/skin/logo16.png differ
diff --git a/skin/logo24.png b/skin/logo24.png
new file mode 100644
index 0000000..e2516c4
Binary files /dev/null and b/skin/logo24.png differ
diff --git a/skin/logo32.png b/skin/logo32.png
new file mode 100644
index 0000000..d9f9ea2
Binary files /dev/null and b/skin/logo32.png differ
diff --git a/skin/logo48.png b/skin/logo48.png
new file mode 100644
index 0000000..2d92430
Binary files /dev/null and b/skin/logo48.png differ
diff --git a/skin/overlay.css b/skin/overlay.css
new file mode 100644
index 0000000..83a78e0
--- /dev/null
+++ b/skin/overlay.css
@@ -0,0 +1,11 @@
+#restclient-button {
+ list-style-image : url("chrome://restclient/skin/logo24.png");
+}
+
+toolbar[iconsize="small"] #restclient-button {
+ list-style-image : url("chrome://restclient/skin/logo16.png");
+}
+
+#restclienttoolsmenu {
+ list-style-image : url("chrome://restclient/skin/logo16.png");
+}
\ No newline at end of file
diff --git a/skin/restclient.css b/skin/restclient.css
new file mode 100644
index 0000000..9377f63
--- /dev/null
+++ b/skin/restclient.css
@@ -0,0 +1,80 @@
+.overflow_01 {overflow: auto;}
+.overflow_02 {overflow: -moz-scrollbars-horizontal;}
+.overflow_03 {overflow: -moz-scrollbars-vertical;}
+
+#open-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/document-open.png');
+}
+#open-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/document-open.png');
+}
+
+#open-entire-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/document-open.png');
+}
+#open-entire-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/document-open.png');
+}
+
+#save-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/document-save.png');
+}
+#save-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/document-save.png');
+}
+
+#save-entire-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/document-save.png');
+}
+#save-entire-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/document-save.png');
+}
+
+#copy-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/edit-copy.png');
+}
+#copy-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/edit-copy.png');
+}
+
+#clear-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/edit-clear.png');
+}
+#clear-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/edit-clear.png');
+}
+
+#header-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/list-add.png');
+}
+#header-icon[disabled="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons_disabled/list-add.png');
+}
+
+#login-icon {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/start-here.png');
+}
+#login-icon[checked="true"] {
+list-style-image:url('chrome://restclient/skin/toolbar/icons/system-log-out.png');
+}
+treechildren::-moz-tree-row(statusOk)
+{
+ background-color: #00FF00;
+ color:black;
+}
+treechildren::-moz-tree-row(statusError)
+{
+ background-color: #800000;
+ color:black;
+}
+treechildren::-moz-tree-cell-text(statusError){
+ color: white;
+}
+treechildren::-moz-tree-cell-text(statusError, selected){
+ color: white;
+}
+treechildren::-moz-tree-cell-text(location){
+ color: blue;
+ font-weight: normal;
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/skin/toolbar/icons/Thumbs.db b/skin/toolbar/icons/Thumbs.db
new file mode 100644
index 0000000..96e7f61
Binary files /dev/null and b/skin/toolbar/icons/Thumbs.db differ
diff --git a/skin/toolbar/icons/document-open.png b/skin/toolbar/icons/document-open.png
new file mode 100644
index 0000000..7c4ee79
Binary files /dev/null and b/skin/toolbar/icons/document-open.png differ
diff --git a/skin/toolbar/icons/document-save.png b/skin/toolbar/icons/document-save.png
new file mode 100644
index 0000000..a94e0ea
Binary files /dev/null and b/skin/toolbar/icons/document-save.png differ
diff --git a/skin/toolbar/icons/edit-clear.png b/skin/toolbar/icons/edit-clear.png
new file mode 100644
index 0000000..bbc77eb
Binary files /dev/null and b/skin/toolbar/icons/edit-clear.png differ
diff --git a/skin/toolbar/icons/edit-copy.png b/skin/toolbar/icons/edit-copy.png
new file mode 100644
index 0000000..345b2f1
Binary files /dev/null and b/skin/toolbar/icons/edit-copy.png differ
diff --git a/skin/toolbar/icons/list-add.png b/skin/toolbar/icons/list-add.png
new file mode 100644
index 0000000..306d3d8
Binary files /dev/null and b/skin/toolbar/icons/list-add.png differ
diff --git a/skin/toolbar/icons/start-here.png b/skin/toolbar/icons/start-here.png
new file mode 100644
index 0000000..fc9b049
Binary files /dev/null and b/skin/toolbar/icons/start-here.png differ
diff --git a/skin/toolbar/icons/system-log-out.png b/skin/toolbar/icons/system-log-out.png
new file mode 100644
index 0000000..28ac66f
Binary files /dev/null and b/skin/toolbar/icons/system-log-out.png differ
diff --git a/skin/toolbar/icons/view-refresh.png b/skin/toolbar/icons/view-refresh.png
new file mode 100644
index 0000000..cab4d02
Binary files /dev/null and b/skin/toolbar/icons/view-refresh.png differ
diff --git a/skin/toolbar/icons_disabled/Thumbs.db b/skin/toolbar/icons_disabled/Thumbs.db
new file mode 100644
index 0000000..36e8ffd
Binary files /dev/null and b/skin/toolbar/icons_disabled/Thumbs.db differ
diff --git a/skin/toolbar/icons_disabled/document-open.png b/skin/toolbar/icons_disabled/document-open.png
new file mode 100644
index 0000000..9a5bcfe
Binary files /dev/null and b/skin/toolbar/icons_disabled/document-open.png differ
diff --git a/skin/toolbar/icons_disabled/document-save.png b/skin/toolbar/icons_disabled/document-save.png
new file mode 100644
index 0000000..a52a9f2
Binary files /dev/null and b/skin/toolbar/icons_disabled/document-save.png differ
diff --git a/skin/toolbar/icons_disabled/edit-clear.png b/skin/toolbar/icons_disabled/edit-clear.png
new file mode 100644
index 0000000..b5e3ffc
Binary files /dev/null and b/skin/toolbar/icons_disabled/edit-clear.png differ
diff --git a/skin/toolbar/icons_disabled/edit-copy.png b/skin/toolbar/icons_disabled/edit-copy.png
new file mode 100644
index 0000000..345b2f1
Binary files /dev/null and b/skin/toolbar/icons_disabled/edit-copy.png differ
diff --git a/skin/toolbar/icons_disabled/list-add.png b/skin/toolbar/icons_disabled/list-add.png
new file mode 100644
index 0000000..306d3d8
Binary files /dev/null and b/skin/toolbar/icons_disabled/list-add.png differ
diff --git a/skin/toolbar/icons_disabled/start-here.png b/skin/toolbar/icons_disabled/start-here.png
new file mode 100644
index 0000000..93979ab
Binary files /dev/null and b/skin/toolbar/icons_disabled/start-here.png differ
diff --git a/skin/toolbar/icons_disabled/system-log-out.png b/skin/toolbar/icons_disabled/system-log-out.png
new file mode 100644
index 0000000..27ac370
Binary files /dev/null and b/skin/toolbar/icons_disabled/system-log-out.png differ
diff --git a/skin/toolbar/icons_disabled/view-refresh.png b/skin/toolbar/icons_disabled/view-refresh.png
new file mode 100644
index 0000000..d0dec2f
Binary files /dev/null and b/skin/toolbar/icons_disabled/view-refresh.png differ