wok view zerobin/stuff/zerobin.js @ rev 12906

move zerobin from undigest
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue May 29 17:26:27 2012 +0200 (2012-05-29)
parents
children
line source
1 /* ZeroBin 0.11 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
3 // Compress a message (deflate compression). Returns base64 encoded data.
4 function compress(message) { return Base64.toBase64(RawDeflate.deflate(Base64.utob(message))); }
6 // Decompress a message compressed with compress().
7 function decompress(data) { return Base64.btou(RawDeflate.inflate(Base64.fromBase64(data))) }
9 /*
10 Encrypt the message with a random key.
11 Output: An array with two items:
12 'data' (string) : json encoded data to store on server side (containing ciphertext,iv and salt)
13 'key' (string: the key (encoded in base64) to be kept on client side.
15 Example:
16 c = randomCipher("Hello, world !");
17 document.write("Data for server side: ");
18 document.write(c.data);
19 document.write('<br>Key at client side: ');
20 document.write(c.key);
21 Output:
22 Data for server side: {"iv":"a6ZEUEtK2jNcGsdIsKKj9g","salt":"/7wDPD4JRik","ct":"qdD97HChan6B9OShjfBDmQKbw8/1ehdO1u/KbC/r85c"}
23 Key at client side: VjxODsAaUwar6LJOcc0yaknnUr5XHeg/m7Sn5UF+TC4=
24 */
25 function randomCipher(message)
26 {
27 var randomkey = (window.location.hash.length > 2) ?
28 // force key
29 window.location.hash.substring(1) :
30 // Generate a random 256 bits key, encoded in base64:
31 sjcl.codec.base64.fromBits(sjcl.random.randomWords(8,0),0);
32 var data = sjcl.encrypt(sjcl.misc.pbkdf2(randomkey,0),compress(message));
33 return {'data':data,'key':randomkey};
34 }
36 // Decrypts data encrypted with randomCipher()
37 function randomDecipher(key,data)
38 {
39 return decompress(sjcl.decrypt(sjcl.misc.pbkdf2(key,0),data));
40 }
42 // Returns the current script location (without search or hash part of the URL).
43 // eg. http://server.com/zero/?aaaa#bbbb --> http://server.com/zero/
44 function scriptLocation()
45 {
46 return window.location.href.substring(0,window.location.href.length
47 -window.location.search.length -window.location.hash.length);
48 }
50 // Show decrypted text in the display area
51 function displayCleartext(text)
52 {
53 if ($('#oldienotice').is(":visible")) // For IE<10.
54 {
55 // IE<10 do not support white-space:pre-wrap; so we have to do this BIG UGLY STINKING THING.
56 $('#cleartext').text(text.replace(/\n/ig,'{BIG_UGLY_STINKING_THING__OH_GOD_I_HATE_IE}'));
57 $('#cleartext').html($('#cleartext').text().replace(/{BIG_UGLY_STINKING_THING__OH_GOD_I_HATE_IE}/ig,"\r\n<br>"));
58 }
59 else // for other (sane) browsers:
60 {
61 $('#cleartext').text(text);
62 }
63 urls2links($('#cleartext')); // Convert URLs to clickable links.
64 }
66 // Send data to server
67 function send_data()
68 {
69 if ($('#message').val().length==0) return; // Do not send if no data.
70 showStatus('Sending data...');
71 var c=randomCipher($('#message').val());
72 $.post(scriptLocation(), { data:c.data,expire:$('select#pasteExpiration').val() },'json' )
73 .error( function() { showError('Data could not be sent.'); } )
74 .success(function(data)
75 {
76 var jdata = jQuery.parseJSON(data);
77 if (data.status==0)
78 {
79 stateExistingPaste();
80 var url=scriptLocation()+"?"+data.id+'#'+c.key;
81 showStatus('');
82 $('#pastelink').html('Your paste is <a href="'+url+'">'+url+'</a>');
83 $('#pastelink').append('&nbsp;&nbsp;<button id="shortenbutton" onclick="document.location=\''+shortenUrl(url)+'\'"><img src="lib/icon_shorten.png#" width="13" height="15" />Shorten URL</button>');
84 $('#pastelink').show();
85 displayCleartext($('#message').val());
86 }
87 else if (data.status==1)
88 {
89 showError('Could not create paste: '+data.message);
90 }
91 else
92 {
93 showError('Could not create paste.');
94 }
95 }
96 );
97 }
99 // Put the screen in "New paste" mode.
100 function stateNewPaste()
101 {
102 sjcl.random.startCollectors();
103 $('#sendbutton').show();
104 $('#clonebutton').hide();
105 $('#expiration').show();
106 $('#language').hide(); // $('#language').show();
107 $('#password').hide(); //$('#password').show();
108 $('#newbutton').show();
109 $('#pastelink').hide();
110 $('#message').text('');
111 $('#message').show();
112 $('#cleartext').hide();
113 $('#hashes').hide();
114 $('#message').focus();
115 }
117 // Put the screen in "Existing paste" mode.
118 function stateExistingPaste()
119 {
120 sjcl.random.startCollectors();
121 $('#sendbutton').hide();
122 if (!$('#oldienotice').is(":visible")) $('#clonebutton').show(); // Not "clone" for IE<10.
123 $('#expiration').hide();
124 $('#language').hide();
125 $('#password').hide();
126 $('#newbutton').show();
127 $('#pastelink').hide();
128 $('#message').hide();
129 $('#cleartext').show();
130 $('#hashes').show();
131 }
133 // Clone the current paste.
134 function clonePaste()
135 {
136 stateNewPaste();
137 showStatus('');
138 $('#message').text($('#cleartext').text());
139 }
141 // Create a new paste.
142 function newPaste()
143 {
144 stateNewPaste();
145 showStatus('');
146 $('#message').text('');
147 }
149 // Display an error message
150 function showError(message)
151 {
152 $('#status').addClass('errorMessage').text(message);
153 }
155 // Display status
156 function showStatus(message)
157 {
158 $('#status').removeClass('errorMessage');
159 if (!message) { $('#status').html('&nbsp'); return; }
160 if (message=='') { $('#status').html('&nbsp'); return; }
161 $('#status').text(message);
162 }
164 // Generate link to URL shortener.
165 function shortenUrl(url)
166 {
167 return 'http://snipurl.com/site/snip?link='+encodeURIComponent(url);
168 }
170 // Convert URLs to clickable links.
171 // Input: element : a jQuery DOM element.
172 // Example URLs to handle:
173 // magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7
174 // http://localhost:8800/zero/?6f09182b8ea51997#WtLEUO5Epj9UHAV9JFs+6pUQZp13TuspAUjnF+iM+dM=
175 // http://user:password@localhost:8800/zero/?6f09182b8ea51997#WtLEUO5Epj9UHAV9JFs+6pUQZp13TuspAUjnF+iM+dM=
176 // FIXME: add ppa & apt links.
177 function urls2links(element)
178 {
179 var re = /((http|https|ftp):\/\/[\w?=&.\/-;#@~%+-]+(?![\w\s?&.\/;#~%"=-]*>))/ig;
180 element.html(element.html().replace(re,'<a href="$1" rel="nofollow">$1</a>'));
181 var re = /((magnet):[\w?=&.\/-;#@~%+-]+)/ig;
182 element.html(element.html().replace(re,'<a href="$1">$1</a>'));
183 }
185 $(document).ready(function() {
186 if ($('#cipherdata').text().length>1) // Display an existing paste
187 {
188 if (window.location.hash.length==0) // Missing decryption key in URL ?
189 {
190 showError('Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector which strips part of the URL ?)');
191 return;
192 }
193 var data = $('#cipherdata').text();
194 try {
195 // Get key and decrypt data
196 var key = window.location.hash.substring(1);
197 // Strip &utm_source=... parameters added after the anchor by some stupid web 2.0 services.
198 // We simply strip everything after &
199 i = key.indexOf('&'); if (i>-1) { key = key.substring(0,i); }
200 if (key.charAt(key.length-1)!=='=') key+='='; // Add trailing = if missing.
201 var cleartext = randomDecipher(key,data);
202 stateExistingPaste(); // Show proper elements on screen.
203 displayCleartext(cleartext);
204 } catch(err) {
205 showError('Could not decrypt data (Wrong key ?)');
206 }
207 }
208 else if ($('#errormessage').text().length>1) // Display error message from php code.
209 {
210 showError($('#errormessage').text());
211 }
212 else // Create a new paste.
213 {
214 newPaste();
215 }
216 });