فهرست منبع

working on password function for #15:
- asking again if password is wrong
- display error if user cancels dialog
- use password to encrypt comments, too (password is "stored" in the
password field)
- store password in sessionStorage when posting a comment so, that it
doesn't have to typed in again, but clear sessionStorage as soon as
password is retrieved

El RIDO 11 سال پیش
والد
کامیت
9fdbba76ce
1فایلهای تغییر یافته به همراه75 افزوده شده و 32 حذف شده
  1. 75 32
      js/zerobin.js

+ 75 - 32
js/zerobin.js

@@ -13,10 +13,10 @@
 sjcl.random.startCollectors();
 sjcl.random.startCollectors();
 
 
 /**
 /**
- *  Converts a duration (in seconds) into human readable format.
+ * Converts a duration (in seconds) into human readable format.
  *
  *
- *  @param int seconds
- *  @return string
+ * @param int seconds
+ * @return string
  */
  */
 function secondsToHuman(seconds)
 function secondsToHuman(seconds)
 {
 {
@@ -37,7 +37,7 @@ function secondsToHuman(seconds)
  */
  */
 function hashToParameterString(associativeArray)
 function hashToParameterString(associativeArray)
 {
 {
-  var parameterString = ""
+  var parameterString = "";
   for (key in associativeArray)
   for (key in associativeArray)
   {
   {
     if( parameterString === "" )
     if( parameterString === "" )
@@ -80,7 +80,7 @@ function parameterStringToHash(parameterString)
  * Get an associative array of the parameters found in the anchor
  * Get an associative array of the parameters found in the anchor
  *
  *
  * @return object
  * @return object
- **/
+ */
 function getParameterHash()
 function getParameterHash()
 {
 {
   var hashIndex = window.location.href.indexOf("#");
   var hashIndex = window.location.href.indexOf("#");
@@ -116,58 +116,80 @@ function decompress(data) {
  * @return encrypted string data
  * @return encrypted string data
  */
  */
 function zeroCipher(key, message) {
 function zeroCipher(key, message) {
-    if ($('input#passwordinput').val().length == 0) {
+    if ($('#passwordinput').val().length == 0) {
         return sjcl.encrypt(key, compress(message));
         return sjcl.encrypt(key, compress(message));
     }
     }
-    return sjcl.encrypt(key + sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash($("input#passwordinput").val())), compress(message));
+    return sjcl.encrypt(key + sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash($("#passwordinput").val())), compress(message));
 }
 }
 
 
 /**
 /**
- *  Decrypt message with key, then decompress.
+ * Decrypt message with key, then decompress.
  *
  *
- *  @param key
- *  @param encrypted string data
- *  @return string readable message
+ * @param string key
+ * @param encrypted string data
+ * @return string readable message
  */
  */
 function zeroDecipher(key, data) {
 function zeroDecipher(key, data) {
     if (data != undefined) {
     if (data != undefined) {
         try {
         try {
             return decompress(sjcl.decrypt(key, data));
             return decompress(sjcl.decrypt(key, data));
         } catch (err) {
         } catch (err) {
-            var password = prompt("Please enter the password for this paste:", "");
-            return decompress(sjcl.decrypt(key + sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(password)), data));
+            try {
+                if ($('#passwordinput').val().length > 0) {
+                    password = $('#passwordinput').val();
+                } else {
+                    password = prompt("Please enter the password for this paste:", "");
+                    if (password == null) return null;
+                }
+                data = decompress(sjcl.decrypt(key + sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(password)), data));
+                $('#passwordinput').val(password);
+                return data;
+            } catch (err) {
+                return zeroDecipher(key, data);
+            }
         }
         }
     }
     }
 }
 }
 
 
 /**
 /**
- * @return the current script location (without search or hash part of the URL).
- *   eg. http://server.com/zero/?aaaa#bbbb --> http://server.com/zero/
+ * Get the current script location (without search or hash part of the URL).
+ * eg. http://server.com/zero/?aaaa#bbbb --> http://server.com/zero/
+ * 
+ * @return string current script location
  */
  */
 function scriptLocation() {
 function scriptLocation() {
   var scriptLocation = window.location.href.substring(0,window.location.href.length
   var scriptLocation = window.location.href.substring(0,window.location.href.length
     - window.location.search.length - window.location.hash.length);
     - window.location.search.length - window.location.hash.length);
   var hashIndex = scriptLocation.indexOf("#");
   var hashIndex = scriptLocation.indexOf("#");
   if (hashIndex !== -1) {
   if (hashIndex !== -1) {
-    scriptLocation = scriptLocation.substring(0, hashIndex)
+    scriptLocation = scriptLocation.substring(0, hashIndex);
   }
   }
-  return scriptLocation
+  return scriptLocation;
 }
 }
 
 
 /**
 /**
- * @return the paste unique identifier from the URL
- *   eg. 'c05354954c49a487'
+ * Get the pastes unique identifier from the URL
+ * eg. http://server.com/zero/?c05354954c49a487#xxx --> c05354954c49a487
+ * 
+ * @return string unique identifier
  */
  */
 function pasteID() {
 function pasteID() {
     return window.location.search.substring(1);
     return window.location.search.substring(1);
 }
 }
 
 
+/**
+ * Convert all applicable characters to HTML entities
+ * 
+ * @param string str
+ * @returns string encoded string
+ */
 function htmlEntities(str) {
 function htmlEntities(str) {
     return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
     return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
 }
 }
 /**
 /**
  * Set text of a DOM element (required for IE)
  * Set text of a DOM element (required for IE)
  * This is equivalent to element.text(text)
  * This is equivalent to element.text(text)
+ * 
  * @param object element : a DOM element.
  * @param object element : a DOM element.
  * @param string text : the text to enter.
  * @param string text : the text to enter.
  */
  */
@@ -191,8 +213,14 @@ function setElementText(element, text) {
  * @param array comments : Array of messages to display (items = array with keys ('data','meta')
  * @param array comments : Array of messages to display (items = array with keys ('data','meta')
  */
  */
 function displayMessages(key, comments) {
 function displayMessages(key, comments) {
+    // restore password if set in previous visit, then clear the session
+    if (window.sessionStorage && sessionStorage.getItem(pageKey())) {
+        $('#passwordinput').val(sessionStorage.getItem(pageKey()));
+        sessionStorage.clear();
+    }
     try { // Try to decrypt the paste.
     try { // Try to decrypt the paste.
         var cleartext = zeroDecipher(key, comments[0].data);
         var cleartext = zeroDecipher(key, comments[0].data);
+        if (cleartext == null) throw "password prompt canceled";
     } catch(err) {
     } catch(err) {
         $('#cleartext').addClass('hidden');
         $('#cleartext').addClass('hidden');
         $('#prettymessage').addClass('hidden');
         $('#prettymessage').addClass('hidden');
@@ -217,7 +245,7 @@ function displayMessages(key, comments) {
     // If the discussion is opened on this paste, display it.
     // If the discussion is opened on this paste, display it.
     if (comments[0].meta.opendiscussion) {
     if (comments[0].meta.opendiscussion) {
         $('#comments').html('');
         $('#comments').html('');
-        // For each comment.
+        // iterate over comments
         for (var i = 1; i < comments.length; i++) {
         for (var i = 1; i < comments.length; i++) {
             var comment=comments[i];
             var comment=comments[i];
             var cleartext="[Could not decrypt comment ; Wrong key ?]";
             var cleartext="[Could not decrypt comment ; Wrong key ?]";
@@ -226,7 +254,7 @@ function displayMessages(key, comments) {
             } catch(err) { }
             } catch(err) { }
             var place = $('#comments');
             var place = $('#comments');
             // If parent comment exists, display below (CSS will automatically shift it right.)
             // If parent comment exists, display below (CSS will automatically shift it right.)
-            var cname = '#comment_'+comment.meta.parentid
+            var cname = '#comment_'+comment.meta.parentid;
 
 
             // If the element exists in page
             // If the element exists in page
             if ($(cname).length) {
             if ($(cname).length) {
@@ -249,7 +277,7 @@ function displayMessages(key, comments) {
 
 
             // If an avatar is available, display it.
             // If an avatar is available, display it.
             if (comment.meta.vizhash) {
             if (comment.meta.vizhash) {
-                divComment.find('span.nickname').before('<img src="' + comment.meta.vizhash + '" class="vizhash" title="Anonymous avatar (Vizhash of the IP address)" />');
+                divComment.find('span.nickname').before('<img src="' + comment.meta.vizhash + '" class="vizhash" title="Anonymous avatar (Vizhash of the IP address)" /> ');
             }
             }
 
 
             place.append(divComment);
             place.append(divComment);
@@ -261,6 +289,7 @@ function displayMessages(key, comments) {
 
 
 /**
 /**
  * Open the comment entry when clicking the "Reply" button of a comment.
  * Open the comment entry when clicking the "Reply" button of a comment.
+ * 
  * @param object source : element which emitted the event.
  * @param object source : element which emitted the event.
  * @param string commentid = identifier of the comment we want to reply to.
  * @param string commentid = identifier of the comment we want to reply to.
  */
  */
@@ -282,6 +311,7 @@ function open_reply(source, commentid) {
 
 
 /**
 /**
  * Send a reply in a discussion.
  * Send a reply in a discussion.
+ * 
  * @param string parentid : the comment identifier we want to send a reply to.
  * @param string parentid : the comment identifier we want to send a reply to.
  */
  */
 function send_comment(parentid) {
 function send_comment(parentid) {
@@ -310,6 +340,10 @@ function send_comment(parentid) {
     .success(function(data) {
     .success(function(data) {
         if (data.status == 0) {
         if (data.status == 0) {
             showStatus('Comment posted.');
             showStatus('Comment posted.');
+            // store password temporarily between page loads
+            if ($('#passwordinput').val().length > 0 && window.sessionStorage) {
+                sessionStorage.setItem(pageKey(), $('#passwordinput').val());
+            }
             location.reload();
             location.reload();
         }
         }
         else if (data.status==1) {
         else if (data.status==1) {
@@ -323,7 +357,7 @@ function send_comment(parentid) {
 
 
 
 
 /**
 /**
- *  Send a new paste to server
+ * Send a new paste to server
  */
  */
 function send_data() {
 function send_data() {
     // Do not send if no data.
     // Do not send if no data.
@@ -381,20 +415,22 @@ function send_data() {
     });
     });
 }
 }
 
 
-/** Text range selection.
- *  From: http://stackoverflow.com/questions/985272/jquery-selecting-text-in-an-element-akin-to-highlighting-with-your-mouse
- *  @param string element : Indentifier of the element to select (id="").
+/**
+ * Text range selection.
+ * From: http://stackoverflow.com/questions/985272/jquery-selecting-text-in-an-element-akin-to-highlighting-with-your-mouse
+ * 
+ * @param string element : Indentifier of the element to select (id="").
  */
  */
 function selectText(element) {
 function selectText(element) {
     var doc = document
     var doc = document
         , text = doc.getElementById(element)
         , text = doc.getElementById(element)
         , range, selection
         , range, selection
     ;
     ;
-    if (doc.body.createTextRange) { //ms
+    if (doc.body.createTextRange) { // MS
         range = doc.body.createTextRange();
         range = doc.body.createTextRange();
         range.moveToElementText(text);
         range.moveToElementText(text);
         range.select();
         range.select();
-    } else if (window.getSelection) { //all others
+    } else if (window.getSelection) { // all others
         selection = window.getSelection();
         selection = window.getSelection();
         range = doc.createRange();
         range = doc.createRange();
         range.selectNodeContents(text);
         range.selectNodeContents(text);
@@ -451,8 +487,9 @@ function stateExistingPaste() {
     $('#prettymessage').removeClass('hidden');
     $('#prettymessage').removeClass('hidden');
 }
 }
 
 
-/** Return raw text
-  */
+/**
+ * Return raw text
+ */
 function rawText()
 function rawText()
 {
 {
     var paste = $('#cleartext').html();
     var paste = $('#cleartext').html();
@@ -488,7 +525,11 @@ function newPaste() {
  * (We use the same function for paste and reply to comments)
  * (We use the same function for paste and reply to comments)
  */
  */
 function showError(message) {
 function showError(message) {
-    $('#status').addClass('errorMessage').text(message);
+    if ($('#status').length) {
+        $('#status').addClass('errorMessage').text(message);
+    } else {
+        $('#errormessage').removeClass('hidden').append(message);
+    }
     $('#replystatus').addClass('errorMessage').text(message);
     $('#replystatus').addClass('errorMessage').text(message);
 }
 }
 
 
@@ -529,7 +570,6 @@ function showStatus(message, spin) {
  * </code>
  * </code>
  *
  *
  * @param object element : a jQuery DOM element.
  * @param object element : a jQuery DOM element.
- * @FIXME: add ppa & apt links.
  */
  */
 function urls2links(element) {
 function urls2links(element) {
     var re = /((http|https|ftp):\/\/[\w?=&.\/-;#@~%+-]+(?![\w\s?&.\/;#~%"=-]*>))/ig;
     var re = /((http|https|ftp):\/\/[\w?=&.\/-;#@~%+-]+(?![\w\s?&.\/;#~%"=-]*>))/ig;
@@ -560,6 +600,9 @@ function pageKey() {
     return key;
     return key;
 }
 }
 
 
+/**
+ * main application start, called when DOM is fully loaded
+ */
 $(function() {
 $(function() {
     // hide "no javascript" message
     // hide "no javascript" message
     $('#noscript').hide();
     $('#noscript').hide();