summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz
authorGiulio Cesare Solaroli <giulio.cesare@clipperz.com>2013-08-30 15:56:53 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@clipperz.com>2013-08-30 21:23:42 (UTC)
commit20bea94ab6b91c85b171dcf86baba0a64169d508 (patch) (unidiff)
tree6e38e91498dcdb861620eba1e237d1026fe79cc5 /frontend/delta/js/Clipperz
parentbde3c7b98523112ade9c5bbf7390c4ecb494cd2e (diff)
downloadclipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.zip
clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.gz
clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.bz2
First release of /delta version
Diffstat (limited to 'frontend/delta/js/Clipperz') (more/less context) (show whitespace changes)
-rw-r--r--frontend/delta/js/Clipperz/Async.js707
-rw-r--r--frontend/delta/js/Clipperz/Base.js514
-rw-r--r--frontend/delta/js/Clipperz/ByteArray.js1459
-rw-r--r--frontend/delta/js/Clipperz/CSVProcessor.js344
-rw-r--r--frontend/delta/js/Clipperz/Crypto/AES.js859
-rw-r--r--frontend/delta/js/Clipperz/Crypto/AES_2.js843
-rw-r--r--frontend/delta/js/Clipperz/Crypto/Base.js1847
-rw-r--r--frontend/delta/js/Clipperz/Crypto/BigInt.js1754
-rw-r--r--frontend/delta/js/Clipperz/Crypto/BigInt_scoped.js1644
-rw-r--r--frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js500
-rw-r--r--frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js519
-rw-r--r--frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Point.js62
-rw-r--r--frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Value.js379
-rw-r--r--frontend/delta/js/Clipperz/Crypto/ECC/StandardCurves.js229
-rw-r--r--frontend/delta/js/Clipperz/Crypto/PRNG.js841
-rw-r--r--frontend/delta/js/Clipperz/Crypto/RSA.js146
-rw-r--r--frontend/delta/js/Clipperz/Crypto/SHA.js296
-rw-r--r--frontend/delta/js/Clipperz/Crypto/SRP.js316
-rw-r--r--frontend/delta/js/Clipperz/DOM.js134
-rw-r--r--frontend/delta/js/Clipperz/Date.js297
-rw-r--r--frontend/delta/js/Clipperz/KeePassExportProcessor.js191
-rw-r--r--frontend/delta/js/Clipperz/KeyValueObjectStore.js166
-rw-r--r--frontend/delta/js/Clipperz/Logging.js32
-rw-r--r--frontend/delta/js/Clipperz/PM/BookmarkletProcessor.js191
-rw-r--r--frontend/delta/js/Clipperz/PM/Connection.js636
-rw-r--r--frontend/delta/js/Clipperz/PM/Crypto.js546
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js1086
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js120
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js101
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js192
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js542
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js350
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js186
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js328
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/Record.js891
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js182
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js117
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js48
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js685
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js53
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.js827
-rw-r--r--frontend/delta/js/Clipperz/PM/Date.js196
-rw-r--r--frontend/delta/js/Clipperz/PM/PIN.js132
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy.js186
-rwxr-xr-xfrontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js86
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js793
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js420
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.MemoryDataStore.js643
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.js72
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Test.js161
-rw-r--r--frontend/delta/js/Clipperz/PM/Strings.js285
-rw-r--r--frontend/delta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js384
-rw-r--r--frontend/delta/js/Clipperz/PM/Strings/Strings_defaults.js385
-rw-r--r--frontend/delta/js/Clipperz/PM/Strings/Strings_en-US.js1336
-rw-r--r--frontend/delta/js/Clipperz/PM/Toll.js189
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js142
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/CardList.js161
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/ErrorPage.js46
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js150
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js122
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/PageTemplate.js33
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js240
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/DirectLoginController.js256
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/MainController.js491
-rw-r--r--frontend/delta/js/Clipperz/Set.js162
-rw-r--r--frontend/delta/js/Clipperz/Signal.js66
-rw-r--r--frontend/delta/js/Clipperz/Style.js89
-rw-r--r--frontend/delta/js/Clipperz/Visual.js363
-rw-r--r--frontend/delta/js/Clipperz/YUI/DomHelper.js471
-rw-r--r--frontend/delta/js/Clipperz/YUI/DomQuery.js709
-rw-r--r--frontend/delta/js/Clipperz/YUI/Utils.js93
71 files changed, 30022 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/Async.js b/frontend/delta/js/Clipperz/Async.js
new file mode 100644
index 0000000..971fde5
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Async.js
@@ -0,0 +1,707 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//Clipperz.Async = MochiKit.Async;
25
26
27if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
28if (typeof(Clipperz.Async) == 'undefined') { Clipperz.Async = {}; }
29
30Clipperz.Async.VERSION = "0.1";
31Clipperz.Async.NAME = "Clipperz.Async";
32
33Clipperz.Async.Deferred = function(aName, args) {
34 args = args || {};
35
36 Clipperz.Async.Deferred.superclass.constructor.call(this, args.canceller);
37
38 this._args = args;
39 this._name = aName || "Anonymous deferred";
40 this._count = 0;
41 this._shouldTrace = ((CLIPPERZ_DEFERRED_TRACING_ENABLED === true) || (args.trace === true));
42 this._vars = null;
43
44 return this;
45}
46
47//=============================================================================
48
49Clipperz.Base.extend(Clipperz.Async.Deferred, MochiKit.Async.Deferred, {
50
51 'name': function () {
52 return this._name;
53 },
54
55 'args': function () {
56 return this._args;
57 },
58
59 //-----------------------------------------------------------------------------
60
61 'callback': function (aValue) {
62 if (this._shouldTrace) {
63 Clipperz.log("CALLBACK " + this._name, aValue);
64 }
65
66 if (this.chained == false) {
67 var message;
68
69 message = "ERROR [" + this._name + "]";
70 this.addErrback(function(aResult) {
71 if (! (aResult instanceof MochiKit.Async.CancelledError)) {
72 Clipperz.log(message, aResult);
73 }
74 return aResult;
75 });
76
77 if (this._shouldTrace) {
78 var resultMessage;
79
80 resultMessage = "RESULT " + this._name + " <==";
81 // this.addCallback(function(aResult) {
82 Clipperz.Async.Deferred.superclass.addCallback.call(this, function(aResult) {
83 Clipperz.log(resultMessage, aResult);
84 return aResult;
85 });
86 }
87 }
88
89 if (CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED === true) {
90 Clipperz.log("callback " + this._name, this);
91 }
92
93 return Clipperz.Async.Deferred.superclass.callback.apply(this, arguments);
94 },
95
96 //-----------------------------------------------------------------------------
97
98 'addCallback': function () {
99 var message;
100
101 if (this._shouldTrace) {
102 this._count ++;
103 message = "[" + this._count + "] " + this._name + " ";
104 // this.addBoth(function(aResult) {Clipperz.log(message + "-->", aResult); return aResult;});
105 this.addCallbacks(
106 function(aResult) {Clipperz.log("-OK- " + message + "-->"/*, aResult*/); return aResult;},
107 function(aResult) {Clipperz.log("FAIL " + message + "-->"/*, aResult*/); return aResult;}
108 );
109 }
110
111 Clipperz.Async.Deferred.superclass.addCallback.apply(this, arguments);
112
113 if (this._shouldTrace) {
114 // this.addBoth(function(aResult) {Clipperz.log(message + "<--", aResult); return aResult;});
115 this.addCallbacks(
116 function(aResult) {Clipperz.log("-OK- " + message + "<--", aResult); return aResult;},
117 function(aResult) {Clipperz.log("FAIL " + message + "<--", aResult); return aResult;}
118 );
119 }
120 },
121
122 //=============================================================================
123
124 'addCallbackPass': function() {
125 var passFunction;
126
127 passFunction = MochiKit.Base.partial.apply(null, arguments);
128
129 this.addCallback(function() {
130 var result;
131
132 result = arguments[arguments.length -1];
133 passFunction();
134
135 return result;
136 });
137 },
138
139 //-----------------------------------------------------------------------------
140
141 'addErrbackPass': function() {
142 var passFunction;
143
144 passFunction = MochiKit.Base.partial.apply(null, arguments);
145
146 this.addErrback(function() {
147 var result;
148
149 result = arguments[arguments.length -1];
150 passFunction();
151
152 return result;
153 });
154 },
155
156 //-----------------------------------------------------------------------------
157
158 'addBothPass': function() {
159 var passFunction;
160
161 passFunction = MochiKit.Base.partial.apply(null, arguments);
162
163 this.addBoth(function() {
164 var result;
165
166 result = arguments[arguments.length -1];
167 passFunction();
168
169 return result;
170 });
171 },
172
173 //-----------------------------------------------------------------------------
174
175 'addIf': function (aThenBlock, anElseBlock) {
176 this.addCallback(MochiKit.Base.bind(function (aValue) {
177 var deferredResult;
178
179 if (!MochiKit.Base.isUndefinedOrNull(aValue) && aValue) {
180 deferredResult = Clipperz.Async.callbacks(this._name + " <then>", aThenBlock, null, aValue);
181 } else {
182 deferredResult = Clipperz.Async.callbacks(this._name + " <else>", anElseBlock, null, aValue);
183 }
184
185 return deferredResult;
186 }))
187 },
188
189 //-----------------------------------------------------------------------------
190
191 'addMethod': function () {
192 this.addCallback(MochiKit.Base.method.apply(this, arguments));
193 },
194
195 //-----------------------------------------------------------------------------
196
197 'addMethodcaller': function () {
198 this.addCallback(MochiKit.Base.methodcaller.apply(this, arguments));
199 },
200
201 //=============================================================================
202
203 'addLog': function (aLog) {
204 if (CLIPPERZ_DEFERRED_LOGGING_ENABLED) {
205 this.addBothPass(function(res) {Clipperz.log(aLog + " ", res);});
206 }
207 },
208
209 //=============================================================================
210
211 'acquireLock': function (aLock) {
212 // this.addCallback(function (aResult) {
213 // return Clipperz.Async.callbacks("Clipperz.Async.acquireLock", [
214 // MochiKit.Base.method(aLock, 'acquire'),
215 // MochiKit.Base.partial(MochiKit.Async.succeed, aResult)
216 // ], {trace:false});
217 // });
218
219 this.addCallback(MochiKit.Base.method(aLock, 'acquire'));
220 },
221
222 'releaseLock': function (aLock) {
223 // this.addCallback(function (aResult) {
224 // return Clipperz.Async.callbacks("Clipperz.Async.release <ok>", [
225 // MochiKit.Base.method(aLock, 'release'),
226 // MochiKit.Base.partial(MochiKit.Async.succeed, aResult)
227 // ], {trace:false});
228 // });
229 // this.addErrback(function (aResult) {
230///Clipperz.log("releaseLock.addErrback:", aResult);
231 // return Clipperz.Async.callbacks("Clipperz.Async.release <fail>", [
232 // MochiKit.Base.method(aLock, 'release'),
233 // MochiKit.Base.partial(MochiKit.Async.fail, aResult)
234 // ], {trace:false});
235 // });
236
237 // this.addBothPass(MochiKit.Base.method(aLock, 'release'));
238 this.addCallbackPass(MochiKit.Base.method(aLock, 'release'));
239 this.addErrback(function (anError) {
240 aLock.release();
241
242 return anError;
243 });
244 },
245
246 //=============================================================================
247
248 'collectResults': function (someRequests) {
249 this.addCallback(Clipperz.Async.collectResults(this._name + " <collect results>", someRequests, this._args));
250 },
251
252 'addCallbackList': function (aRequestList) {
253 this.addCallback(Clipperz.Async.callbacks, this._name + " <callback list>", aRequestList, this._args);
254 },
255
256 //=============================================================================
257
258 'vars': function () {
259 if (this._vars == null) {
260 this._vars = {}
261 }
262
263 return this._vars;
264 },
265
266 'setValue': function (aKey) {
267 this.addCallback(MochiKit.Base.bind(function (aValue) {
268 this.vars()[aKey] = aValue;
269 return aValue;
270 }, this));
271 },
272
273 'getValue': function (aKey) {
274 this.addCallback(MochiKit.Base.bind(function () {
275 return this.vars()[aKey];
276 }, this));
277 },
278
279 //=============================================================================
280
281 'wait': function (someSeconds) {
282 this.addCallback(MochiKit.Async.wait, someSeconds);
283 },
284
285 //=============================================================================
286
287 __syntaxFix__: "syntax fix"
288});
289
290//#############################################################################
291
292Clipperz.Async.DeferredSynchronizer = function(aName, someMethods) {
293 this._name = aName || "Anonymous deferred Synchronizer";
294 this._methods = someMethods;
295
296 this._numberOfMethodsDone= 0;
297 this._methodResults = [];
298
299 this._result = new Clipperz.Async.Deferred("Clipperz.Async.DeferredSynchronizer # " + this.name(), {trace:false});
300 this._result.addMethod(this, 'methodResults');
301 this._result.addCallback(function(someResults) {
302 varcancels;
303 var errors;
304 var result;
305
306 cancels = MochiKit.Base.filter(function(aResult) { return (aResult instanceof MochiKit.Async.CancelledError)}, someResults);
307
308 if (cancels.length == 0) {
309 errors = MochiKit.Base.filter(function(aResult) { return (aResult instanceof Error)}, someResults);
310
311 if (errors.length == 0) {
312 // result = MochiKit.Async.succeed(someResults);
313 result = someResults;
314 } else {
315 result = MochiKit.Async.fail(someResults);
316 }
317 } else {
318 result = MochiKit.Async.fail(cancels[0]);
319 }
320
321 return result;
322 }/*, this._methodResults */);
323
324 return this;
325}
326
327MochiKit.Base.update(Clipperz.Async.DeferredSynchronizer.prototype, {
328
329 //-----------------------------------------------------------------------------
330
331 'name': function() {
332 return this._name;
333 },
334
335 //-----------------------------------------------------------------------------
336
337 'methods': function() {
338 return this._methods;
339 },
340
341 'methodResults': function() {
342 return this._methodResults;
343 },
344
345 //-----------------------------------------------------------------------------
346
347 'result': function() {
348 return this._result;
349 },
350
351 //-----------------------------------------------------------------------------
352
353 'numberOfMethodsDone':function() {
354 return this._numberOfMethodsDone;
355 },
356
357 'incrementNumberOfMethodsDone': function() {
358 this._numberOfMethodsDone ++;
359 },
360
361 //-----------------------------------------------------------------------------
362
363 'run': function(args, aValue) {
364 var deferredResults;
365 var i, c;
366
367 deferredResults = [];
368 args = args || {};
369
370 c = this.methods().length;
371 for (i=0; i<c; i++) {
372 var deferredResult;
373 varmethodCalls;
374 var ii, cc;
375
376//Clipperz.log("TYPEOF", typeof(this.methods()[i]));
377 if (typeof(this.methods()[i]) == 'function') {
378 methodCalls = [ this.methods()[i] ];
379 } else {
380 methodCalls = this.methods()[i];
381 }
382
383 cc = methodCalls.length;
384 deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.DeferredSynchronizer.run => " + this.name() + "[" + i + "]", args);
385 for (ii=0; ii<cc; ii++) {
386 deferredResult.addCallback(methodCalls[ii]);
387 }
388 deferredResult.addBoth(MochiKit.Base.method(this, 'handleMethodCallDone', i));
389
390 deferredResults.push(deferredResult);
391 }
392
393 for (i=0; i<c; i++) {
394 deferredResults[i].callback(aValue);
395 }
396
397 return this.result();
398 },
399
400 //-----------------------------------------------------------------------------
401
402 'handleMethodCallDone': function(anIndexValue, aResult) {
403 this.incrementNumberOfMethodsDone();
404 this.methodResults()[anIndexValue] = aResult;
405
406 if (this.numberOfMethodsDone() < this.methods().length) {
407 //nothing to do here other than possibly log something
408 } else if (this.numberOfMethodsDone() == this.methods().length) {
409 this.result().callback();
410 } else if (this.numberOfMethodsDone() > this.methods().length) {
411 alert("Clipperz.Async.Deferred.handleMethodCallDone -> WTF!");
412 //WTF!!! :(
413 }
414
415 },
416
417 //-----------------------------------------------------------------------------
418
419 __syntaxFix__: "syntax fix"
420});
421
422//#############################################################################
423
424MochiKit.Base.update(Clipperz.Async, {
425
426 'callbacks': function (aName, someFunctions, someArguments, aCallbackValue) {
427 var deferredResult;
428 var i, c;
429
430 deferredResult = new Clipperz.Async.Deferred(aName, someArguments);
431 c = someFunctions.length;
432 for (i=0; i<c; i++) {
433 deferredResult.addCallback(someFunctions[i]);
434 }
435 deferredResult.callback(aCallbackValue);
436
437 return deferredResult;
438 },
439
440 //-------------------------------------------------------------------------
441
442 'forkAndJoin': function (aName, someMethods, args) {
443 return MochiKit.Base.partial(function (aName, someMethods, args, aValue) {
444 var synchronizer;
445 varresult;
446
447 args = args || {};
448 synchronizer = new Clipperz.Async.DeferredSynchronizer(aName, someMethods);
449 result = synchronizer.run(args, aValue);
450
451 return result;
452 }, aName, someMethods, args);
453 },
454
455 //-------------------------------------------------------------------------
456
457 'collectResults': function(aName, someRequests, args) {
458 return MochiKit.Base.partial(function(aName, someRequests, args, aValue) {
459 var deferredResult;
460 var requestKeys;
461 var methods;
462
463 requestKeys = MochiKit.Base.keys(someRequests);
464 methods = MochiKit.Base.values(someRequests);
465
466 deferredResult = new Clipperz.Async.Deferred(aName, args);
467 deferredResult.addCallback(Clipperz.Async.forkAndJoin(aName + " [inner forkAndJoin]", methods, args));
468 deferredResult.addBoth(function(someResults) {
469 var returnFunction;
470 var results;
471 var i,c;
472 var result;
473
474 if (someResults instanceof MochiKit.Async.CancelledError) {
475 returnFunction = MochiKit.Async.fail;
476 result = someResults;
477 } else {
478 if (someResults instanceof Error) {
479 returnFunction = MochiKit.Async.fail;
480 results = someResults['message'];
481 } else {
482 returnFunction = MochiKit.Async.succeed;
483 results = someResults;
484 }
485
486 result = {};
487
488 c = requestKeys.length;
489 for (i=0; i<c; i++) {
490 result[requestKeys[i]] = results[i];
491 }
492 }
493
494 return returnFunction.call(null, result);
495 });
496 deferredResult.callback(aValue);
497
498 return deferredResult;
499 }, aName, someRequests, args);
500 },
501
502 //-------------------------------------------------------------------------
503
504 'collectAll': function (someDeferredObjects) {
505 var deferredResult;
506
507 deferredResult = new MochiKit.Async.DeferredList(someDeferredObjects, false, false, false);
508 deferredResult.addCallback(function (aResultList) {
509 return MochiKit.Base.map(function (aResult) {
510 if (aResult[0]) {
511 return aResult[1];
512 } else {
513 throw aResult[1];
514 }
515 }, aResultList);
516 });
517
518 return deferredResult;
519 },
520
521 //-------------------------------------------------------------------------
522
523 'setItem': function (anObject, aKey, aValue) {
524 anObject[aKey] = aValue;
525
526 return anObject;
527 },
528
529 'setItemOnObject': function (aKey, aValue, anObject) {
530 anObject[aKey] = aValue;
531
532 return anObject;
533 },
534
535 'setDeferredItemOnObject': function (aKey, aDeferredFunction, anObject) {
536 return Clipperz.Async.callbacks("Clipperz.Async.setDeferredItemOnObject", [
537 aDeferredFunction,
538 MochiKit.Base.partial(Clipperz.Async.setItem, anObject, aKey)
539 ], {trace:false}, anObject);
540 },
541
542 //-------------------------------------------------------------------------
543
544 'deferredIf': function (aName, aThenBlock, anElseBlock) {
545 return function (aValue) {
546 var deferredResult;
547
548 if (!MochiKit.Base.isUndefinedOrNull(aValue) && aValue) {
549 deferredResult = Clipperz.Async.callbacks(aName + " <then>", aThenBlock, null, aValue);
550 } else {
551 deferredResult = Clipperz.Async.callbacks(aName + " <else>", anElseBlock, null, aValue);
552 }
553
554 return deferredResult;
555 }
556 },
557
558 //-------------------------------------------------------------------------
559
560 'log': function(aMessage, aResult) {
561 if (CLIPPERZ_DEFERRED_LOGGING_ENABLED) {
562 Clipperz.log(aMessage + " ", aResult);
563 }
564
565 return aResult;
566 },
567
568 //=========================================================================
569
570 'deferredCompare': function (aComparator, aDeferred, bDeferred) {
571 var deferredResult;
572
573 deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredCompare", {trace:false});
574 deferredResult.addCallback(Clipperz.Async.collectAll, [aDeferred, bDeferred]);
575 deferredResult.addCallback(function (someResults) {
576 var result;
577
578 if (aComparator(someResults[0], someResults[1]) > 0) {
579 result = MochiKit.Async.succeed();
580 } else {
581 result = MochiKit.Async.fail();
582 };
583
584 return result;
585 });
586 deferredResult.callback();
587
588 return deferredResult;
589 },
590
591 //-------------------------------------------------------------------------
592
593 'insertIntoSortedArray': function (anObject, aDeferredComparator, aSortedResult) {
594 var deferredResult;
595 var i, c;
596
597 if (aSortedResult.length == 0) {
598 deferredResult = MochiKit.Async.succeed([anObject]);
599 } else {
600 deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.insertIntoSortedArray", {trace:false});
601 c = aSortedResult.length + 1;
602 for (i=0; i<c; i++) {
603 deferredResult.addCallback(function (aDeferredComparator, aObject, bObject, aContext) {
604 var innerDeferredResult;
605
606 innerDeferredResult = new Clipperz.Async.Deferred("Clipperz.Async.insertIntoSortedArray <inner compare>", {trace:false});
607 innerDeferredResult.addCallback(aDeferredComparator, aObject, bObject);
608 innerDeferredResult.addErrback(MochiKit.Async.fail, aContext);
609 innerDeferredResult.callback();
610
611 return innerDeferredResult;
612 }, aDeferredComparator, anObject, aSortedResult[i], i);
613 }
614 deferredResult.addMethod(aSortedResult, 'push', anObject);
615 deferredResult.addErrback(function (anError) {
616 aSortedResult.splice(anError.message, 0, anObject);
617 })
618 deferredResult.addBoth(MochiKit.Async.succeed, aSortedResult);
619 deferredResult.callback();
620 }
621
622 return deferredResult;
623 },
624
625 //-------------------------------------------------------------------------
626
627 'deferredSort': function (aDeferredComparator, someObjects) {
628 var deferredResult;
629 var i, c;
630
631 deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredSort", {trace:false});
632 c = someObjects.length;
633 for (i=0; i<c; i++) {
634 deferredResult.addCallback(Clipperz.Async.insertIntoSortedArray, someObjects[i], aDeferredComparator);
635 if ((i % 50) == 0) {
636 //Clipperz.log("######### sort wait ##########");
637 deferredResult.addCallback(MochiKit.Async.wait, 0.5);
638 }
639 }
640 deferredResult.callback([]);
641
642 return deferredResult;
643 },
644
645 //=========================================================================
646
647 'deferredFilter': function (aFunction, someObjects) {
648 vardeferredResult;
649 vari, c;
650
651 deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredFilter", {trace:false});
652 c = someObjects.length;
653 for (i=0; i<c; i++) {
654 deferredResult.addCallback(function (aFunction, anObject, anIndex, aResult) {
655 var innerDeferredResult;
656
657 innerDeferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredFilter <inner - " + anIndex + ">", {trace:false});
658 innerDeferredResult.addCallback(aFunction, anObject);
659 innerDeferredResult.addCallback(function (aFilterResult) {
660 if (aFilterResult) {
661 aResult.push(anObject);
662 };
663 });
664 innerDeferredResult.addBoth(MochiKit.Async.succeed, aResult);
665 innerDeferredResult.callback();
666
667 return innerDeferredResult;
668 }, aFunction, someObjects[i], i);
669 }
670 deferredResult.callback([]);
671
672 return deferredResult;
673 },
674
675 'forEach': function (aFunction) {
676 return MochiKit.Base.partial(function (aFunction, anIterable) {
677 MochiKit.Iter.forEach(anIterable, aFunction);
678 }, aFunction);
679 },
680
681 //=========================================================================
682
683 'or': function (someValues) {
684 return Clipperz.Async.callbacks("Clipperz.Async.or", [
685 MochiKit.Base.values,
686 MochiKit.Base.flattenArguments,
687//function (aValue) { Clipperz.log("Record.hasAnyCleanTextData - flatten", aValue); return aValue; },
688 function(someInnerValues) {
689 return MochiKit.Iter.some(someInnerValues, MochiKit.Base.operator.identity);
690 }
691 ], {trace:false}, someValues);
692 },
693
694 //=========================================================================
695
696 'clearResult': function () {},
697
698 //=========================================================================
699 __syntaxFix__: "syntax fix"
700});
701
702
703//#############################################################################
704
705CLIPPERZ_DEFERRED_LOGGING_ENABLED = true;
706CLIPPERZ_DEFERRED_TRACING_ENABLED = false;
707CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED = false;
diff --git a/frontend/delta/js/Clipperz/Base.js b/frontend/delta/js/Clipperz/Base.js
new file mode 100644
index 0000000..84b2172
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Base.js
@@ -0,0 +1,514 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Base) == 'undefined') { Clipperz.Base = {}; }
26
27Clipperz.Base.VERSION = "0.2";
28Clipperz.Base.NAME = "Clipperz.Base";
29
30MochiKit.Base.update(Clipperz.Base, {
31
32 //-------------------------------------------------------------------------
33
34 '__repr__': function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36 },
37
38 //-------------------------------------------------------------------------
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-------------------------------------------------------------------------
45
46 'itemgetter': function (aKeyPath) {
47 // return MochiKit.Base.compose.apply(null, [MochiKit.Base.itemgetter('key3')]);
48 return MochiKit.Base.compose.apply(null,
49 MochiKit.Base.map(
50 MochiKit.Base.itemgetter,
51 MochiKit.Iter.reversed(
52 aKeyPath.split('.')
53 )
54 )
55 );
56 },
57
58 //-------------------------------------------------------------------------
59
60 'isUrl': function (aValue) {
61 return (MochiKit.Base.urlRegExp.test(aValue));
62 },
63
64 'isEmail': function (aValue) {
65 return (MochiKit.Base.emailRegExp.test(aValue));
66 },
67
68 //-------------------------------------------------------------------------
69
70 'caseInsensitiveCompare': function (a, b) {
71 return MochiKit.Base.compare(a.toLowerCase(), b.toLowerCase());
72 },
73
74 'reverseComparator': function (aComparator) {
75 return MochiKit.Base.compose(function(aResult) { return -aResult; }, aComparator);
76 },
77
78 'caseInsensitiveKeyComparator': function (aKey) {
79 return function (a, b) {
80 return MochiKit.Base.compare(a[aKey].toLowerCase(), b[aKey].toLowerCase());
81 }
82 },
83 //-------------------------------------------------------------------------
84/*
85 'dependsOn': function(module, deps) {
86 if (!(module in Clipperz)) {
87 MochiKit[module] = {};
88 }
89
90 if (typeof(dojo) != 'undefined') {
91 dojo.provide('Clipperz.' + module);
92 }
93 for (var i = 0; i < deps.length; i++) {
94 if (typeof(dojo) != 'undefined') {
95 dojo.require('Clipperz.' + deps[i]);
96 }
97 if (typeof(JSAN) != 'undefined') {
98 JSAN.use('Clipperz.' + deps[i], []);
99 }
100 if (!(deps[i] in Clipperz)) {
101 throw 'Clipperz.' + module + ' depends on Clipperz.' + deps[i] + '!'
102 }
103 }
104 },
105*/
106 //-------------------------------------------------------------------------
107
108 'trim': function (aValue) {
109 return aValue.replace(/^\s+|\s+$/g, "");
110 },
111
112 //-------------------------------------------------------------------------
113
114 'stringToByteArray': function (aValue) {
115 varresult;
116 var i, c;
117
118 result = [];
119
120 c = aValue.length;
121 for (i=0; i<c; i++) {
122 result[i] = aValue.charCodeAt(i);
123 }
124
125 return result;
126 },
127
128 //.........................................................................
129
130 'byteArrayToString': function (anArrayOfBytes) {
131 varresult;
132 var i, c;
133
134 result = "";
135
136 c = anArrayOfBytes.length;
137 for (i=0; i<c; i++) {
138 result += String.fromCharCode(anArrayOfBytes[i]);
139 }
140
141 return result;
142 },
143
144 //-------------------------------------------------------------------------
145
146 'getValueForKeyInFormContent': function (aFormContent, aKey) {
147 return aFormContent[1][MochiKit.Base.find(aFormContent[0], aKey)];
148 },
149
150 //-------------------------------------------------------------------------
151
152 'indexOfObjectInArray': function(anObject, anArray) {
153 varresult;
154 vari, c;
155
156 result = -1;
157
158 c = anArray.length;
159 for (i=0; ((i<c) && (result < 0)); i++) {
160 if (anArray[i] === anObject) {
161 result = i;
162 }
163 }
164
165 return result;
166 },
167
168 //-------------------------------------------------------------------------
169
170 'removeObjectAtIndexFromArray': function(anIndex, anArray) {
171 anArray.splice(anIndex, 1);
172 },
173
174 //-------------------------------------------------------------------------
175
176 'removeObjectFromArray': function(anObject, anArray) {
177 varobjectIndex;
178
179 objectIndex = Clipperz.Base.indexOfObjectInArray(anObject, anArray);
180 if (objectIndex > -1) {
181 Clipperz.Base.removeObjectAtIndexFromArray(objectIndex, anArray);
182 } else {
183 Clipperz.log("Trying to remove an object not present in the array");
184 throw Clipperz.Base.exception.ObjectNotFound;
185 }
186 },
187
188 'removeFromArray': function(anArray, anObject) {
189 return Clipperz.Base.removeObjectFromArray(anObject, anArray);
190 },
191
192 //-------------------------------------------------------------------------
193
194 'splitStringAtFixedTokenSize': function(aString, aTokenSize) {
195 var result;
196 varstringToProcess;
197
198 stringToProcess = aString;
199 result = [];
200 if (stringToProcess != null) {
201 while (stringToProcess.length > aTokenSize) {
202 result.push(stringToProcess.substring(0, aTokenSize));
203 stringToProcess = stringToProcess.substring(aTokenSize);
204 }
205
206 result.push(stringToProcess);
207 }
208
209 return result;
210 },
211
212 //-------------------------------------------------------------------------
213
214 'objectType': function(anObject) {
215 var result;
216
217 if (anObject == null) {
218 result = null;
219 } else {
220 result = typeof(anObject);
221
222 if (result == "object") {
223 if (anObject instanceof Array) {
224 result = 'array'
225 } else if (anObject.constructor == Boolean) {
226 result = 'boolean'
227 } else if (anObject instanceof Date) {
228 result = 'date'
229 } else if (anObject instanceof Error) {
230 result = 'error'
231 } else if (anObject instanceof Function) {
232 result = 'function'
233 } else if (anObject.constructor == Number) {
234 result = 'number'
235 } else if (anObject.constructor == String) {
236 result = 'string'
237 } else if (anObject instanceof Object) {
238 result = 'object'
239 } else {
240 throw Clipperz.Base.exception.UnknownType;
241 }
242 }
243 }
244
245 return result;
246 },
247
248 //-------------------------------------------------------------------------
249
250 'escapeHTML': function(aValue) {
251 var result;
252
253 result = aValue;
254 result = result.replace(/</g, "&lt;");
255 result = result.replace(/>/g, "&gt;");
256
257 return result;
258 },
259
260 //-------------------------------------------------------------------------
261
262 'deepClone': function(anObject) {
263 var result;
264
265 result = Clipperz.Base.evalJSON(Clipperz.Base.serializeJSON(anObject));
266
267 return result;
268 },
269
270 //-------------------------------------------------------------------------
271
272 //'deepCompare': function (aObject, bObject) {
273 // return (Clipperz.Base.serializeJSON(aObject) == Clipperz.Base.serializeJSON(bObject));
274 //},
275
276 //-------------------------------------------------------------------------
277
278 'evalJSON': function(aString) {
279 return JSON.parse(aString);
280 },
281
282 'serializeJSON': function(anObject) {
283 return JSON.stringify(anObject);
284 },
285
286 'formatJSON': function (anObject, sIndent) {
287 var realTypeOf = function (v) {
288 if (typeof(v) == "object") {
289 if (v === null) return "null";
290 if (v.constructor == (new Array).constructor) return "array";
291 if (v.constructor == (new Date).constructor) return "date";
292 if (v.constructor == (new RegExp).constructor) return "regex";
293 return "object";
294 }
295 return typeof(v);
296 };
297
298 //function FormatJSON(oData, sIndent) {
299 if (arguments.length < 2) {
300 var sIndent = "";
301 }
302 // var sIndentStyle = " ";
303 var sIndentStyle = " ";
304 var sDataType = realTypeOf(anObject);
305
306 // open object
307 if (sDataType == "array") {
308 if (anObject.length == 0) {
309 return "[]";
310 }
311 var sHTML = "[";
312 } else if (sDataType == "object") {
313 var sHTML = "{";
314 } else {
315 return "{}";
316 }
317 // } else {
318 // var iCount = 0;
319 // $.each(anObject, function() {
320 // iCount++;
321 // return;
322 // });
323 // if (iCount == 0) { // object is empty
324 // return "{}";
325 // }
326 // var sHTML = "{";
327 // }
328
329 // loop through items
330 var iCount = 0;
331 // $.each(anObject, function(sKey, vValue) {
332 MochiKit.Iter.forEach(MochiKit.Base.keys(anObject), function(sKey) {
333 var vValue = anObject[sKey];
334
335 if (iCount > 0) {
336 sHTML += ",";
337 }
338 if (sDataType == "array") {
339 sHTML += ("\n" + sIndent + sIndentStyle);
340 } else {
341 sHTML += ("\n" + sIndent + sIndentStyle + "\"" + sKey + "\"" + ": ");
342 }
343
344 // display relevant data type
345 switch (realTypeOf(vValue)) {
346 case "array":
347 case "object":
348 sHTML += Clipperz.Base.formatJSON(vValue, (sIndent + sIndentStyle));
349 break;
350 case "boolean":
351 case "number":
352 sHTML += vValue.toString();
353 break;
354 case "null":
355 sHTML += "null";
356 break;
357 case "string":
358 sHTML += ("\"" + vValue + "\"");
359 break;
360 default:
361 sHTML += ("TYPEOF: " + typeof(vValue));
362 }
363
364 // loop
365 iCount++;
366 });
367
368 // close object
369 if (sDataType == "array") {
370 sHTML += ("\n" + sIndent + "]");
371 } else {
372 sHTML += ("\n" + sIndent + "}");
373 }
374
375 // return
376 return sHTML;
377 },
378
379 //-------------------------------------------------------------------------
380
381 'mergeItems': function (anArrayOfValues) {
382 var result;
383 var i, c;
384
385 result = {};
386
387 c = anArrayOfValues.length;
388 for (i=0; i<c; i++) {
389 result[anArrayOfValues[i][0]] = anArrayOfValues[i][1];
390 }
391
392 return result;
393 },
394
395 //-------------------------------------------------------------------------
396
397 'map': function (fn, lstObj/*, lst... */) {
398 var result;
399
400 if (MochiKit.Base.isArrayLike(lstObj)) {
401 result = MochiKit.Base.map.apply(this, arguments);
402 } else {
403 varkeys;
404 var values;
405 var computedValues;
406
407 keys = MochiKit.Base.keys(lstObj);
408 values = MochiKit.Base.values(lstObj);
409 computedValues = MochiKit.Base.map(fn, values);
410
411 result = Clipperz.Base.mergeItems(MochiKit.Base.zip(keys, computedValues));
412 }
413
414 return result;
415 },
416
417 //-------------------------------------------------------------------------
418
419 'sanitizeString': function(aValue) {
420 var result;
421
422 if (Clipperz.Base.objectType(aValue) == 'string') {
423 result = aValue;
424 result = result.replace(/</img,"&lt;");
425 result = result.replace(/>/img,"&gt;");
426 } else {
427 result = aValue;
428 }
429
430 return result;
431 },
432
433 //-------------------------------------------------------------------------
434
435 'module': function(aValue) {
436 // aValue = 'Clipperz.PM.Compact'
437//
438 // if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
439 // if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
440 // if (typeof(Clipperz.PM.UI.Common.Components) == 'undefined') { Clipperz.PM.UI.Common.Components = {}; }
441
442 var currentScope;
443 var pathElements;
444 var i,c;
445
446 currentScope = window;
447 pathElements = aValue.split('.');
448 c = pathElements.length;
449 for (i=0; i<c; i++) {
450 if (typeof(currentScope[pathElements[i]]) == 'undefined') {
451 currentScope[pathElements[i]] = {};
452 }
453
454 currentScope = currentScope[pathElements[i]];
455 }
456 },
457
458 //-------------------------------------------------------------------------
459
460 'exception': {
461 'AbstractMethod': new MochiKit.Base.NamedError("Clipperz.Base.exception.AbstractMethod"),
462 'UnknownType': new MochiKit.Base.NamedError("Clipperz.Base.exception.UnknownType"),
463 'VulnerabilityIssue':new MochiKit.Base.NamedError("Clipperz.Base.exception.VulnerabilityIssue"),
464 'MandatoryParameter':new MochiKit.Base.NamedError("Clipperz.Base.exception.MandatoryParameter"),
465 'ObjectNotFound': new MochiKit.Base.NamedError("Clipperz.Base.exception.ObjectNotFound"),
466 'raise': function (aName) {
467 throw Clipperz.Base.exception[aName];
468 }
469 },
470
471 //-------------------------------------------------------------------------
472
473 'extend': YAHOO.extendX,
474
475 //-------------------------------------------------------------------------
476 __syntaxFix__: "syntax fix"
477
478});
479
480 //Original regExp courtesy of John Gruber: http://daringfireball.net/2009/11/liberal_regex_for_matching_urls
481 //Updated to match Clipperz usage pattern.
482//MochiKit.Base.urlRegExp = new RegExp(/\b(([\w-]+:\/\/?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/)))/);
483MochiKit.Base.urlRegExp = new RegExp(/^((([\w-]+:\/\/?)|(www\.))[^\s()<>]+((?:\([\w\d]+\)|([^[:punct:]\s]|\/)))?)/);
484
485 //RegExp found here: http://www.tipsntracks.com/117/validate-an-email-address-using-regular-expressions.html
486MochiKit.Base.emailRegExp = new RegExp(/^([a-zA-Z0-9_\-\.]+)@(([a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))|(([01]?\d\d?|2[0-4]\d|25[0-5])\.){3}([01]?\d\d?|25[0-5]|2[0-4]\d))$/);
487
488
489MochiKit.Base.registerComparator('Object dummy comparator',
490 function(a, b) {
491 return ((a.constructor == Object) && (b.constructor == Object));
492 },
493 function(a, b) {
494 var result;
495 var aKeys;
496 var bKeys;
497
498 aKeys = MochiKit.Base.keys(a).sort();
499 bKeys = MochiKit.Base.keys(b).sort();
500 result = MochiKit.Base.compare(aKeys, bKeys);
501
502 if (result == 0) {
503 vari, c;
504
505 c = aKeys.length;
506 for (i=0; (i<c) && (result == 0); i++) {
507 result = MochiKit.Base.compare(a[aKeys[i]], b[bKeys[i]]);
508 }
509 }
510
511 return result;
512 },
513 true
514);
diff --git a/frontend/delta/js/Clipperz/ByteArray.js b/frontend/delta/js/Clipperz/ByteArray.js
new file mode 100644
index 0000000..22c7c6e
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/ByteArray.js
@@ -0,0 +1,1459 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25
26//=============================================================================
27
28Clipperz.ByteArray_abstract = function(args) {
29 return this;
30}
31
32Clipperz.ByteArray_abstract.prototype = MochiKit.Base.update(null, {
33
34 //-------------------------------------------------------------------------
35
36 'toString': function() {
37 return "Clipperz.ByteArray_abstract";
38 },
39
40 //-------------------------------------------------------------------------
41
42 'equals': function(aValue) {
43 return (this.compare(aValue) == 0);
44 },
45
46 //-------------------------------------------------------------------------
47
48 'compare': function(aValue) {
49 var result;
50 var i;
51
52 result = MochiKit.Base.compare(this.length(), aValue.length());
53 i = this.length();
54
55 while ((result == 0) && (i>0)) {
56 i--;
57 result = MochiKit.Base.compare(this.byteAtIndex(i), aValue.byteAtIndex(i));
58 }
59
60 return result;
61 },
62
63 //-------------------------------------------------------------------------
64
65 'clone': function() {
66 throw Clipperz.Base.exception.AbstractMethod;
67 },
68
69 //-------------------------------------------------------------------------
70
71 'newInstance': function() {
72 throw Clipperz.Base.exception.AbstractMethod;
73 },
74
75 //-------------------------------------------------------------------------
76
77 'reset': function() {
78 throw Clipperz.Base.exception.AbstractMethod;
79 },
80
81 //-------------------------------------------------------------------------
82
83 'length': function() {
84 throw Clipperz.Base.exception.AbstractMethod;
85 },
86
87 //-------------------------------------------------------------------------
88
89 'checkByteValue': function(aValue) {
90 if ((aValue & 0xff) != aValue) {
91 Clipperz.logError("Clipperz.ByteArray.appendByte: the provided value (0x" + aValue.toString(16) + ") is not a byte value.");
92 throw Clipperz.ByteArray.exception.InvalidValue;
93 }
94 },
95
96 //-------------------------------------------------------------------------
97
98 'xorMergeWithBlock': function(aBlock, anAllignment, paddingMode) {
99 var result;
100 var a, b;
101 var aLength;
102 var bLength;
103 var i, c;
104
105 if (this.length() > aBlock.length()) {
106 a = this;
107 b = aBlock;
108 } else {
109 a = aBlock;
110 b = this;
111 }
112
113 aLength = a.length();
114 bLength = b.length();
115
116 if (aLength != bLength) {
117 if (paddingMode == 'truncate') {
118 if (anAllignment == 'left') {
119 a = a.split(0, bLength);
120 } else {
121 a = a.split(aLength - bLength);
122 }
123 } else {
124 var ii, cc;
125 var padding;
126
127 // padding = new Clipperz.ByteArray();
128 padding = this.newInstance();
129 cc = aLength - bLength;
130 for (ii=0; ii<cc; ii++) {
131 padding.appendByte(0);
132 }
133
134 if (anAllignment == 'left') {
135 b = b.appendBlock(padding);
136 } else {
137 b = padding.appendBlock(b);
138 }
139 }
140 }
141
142 result = this.newInstance();
143 c = a.length();
144 for (i=0; i<c; i++) {
145 result.appendByte(a.byteAtIndex(i) ^ b.byteAtIndex(i));
146 }
147
148 return result;
149 },
150
151 //-------------------------------------------------------------------------
152
153 'appendBlock': function(aBlock) {
154 throw Clipperz.Base.exception.AbstractMethod;
155 },
156
157 //-------------------------------------------------------------------------
158
159 'appendByte': function(aValue) {
160 throw Clipperz.Base.exception.AbstractMethod;
161 },
162
163 'appendBytes': function(args) {
164 varvalues;
165 vari,c;
166
167 if (args.constructor == Array) {
168 values = args;
169 } else {
170 values = arguments;
171 }
172
173 c = values.length;
174 for (i=0; i<c; i++) {
175 this.appendByte(values[i]);
176 }
177
178 return this;
179 },
180
181 //-------------------------------------------------------------------------
182
183 'appendWord': function(aValue, isLittleEndian) {
184 var result;
185 var processAsLittleEndian;
186
187 processAsLittleEndian = isLittleEndian === true ? true : false;
188
189 if (processAsLittleEndian) {
190 result = this.appendBytes( (aValue) & 0xff, (aValue >> 8) & 0xff, (aValue >> 16) & 0xff, (aValue >> 24) & 0xff ); //little endian
191 } else {
192 result = this.appendBytes( (aValue >> 24) & 0xff, (aValue >> 16) & 0xff, (aValue >> 8) & 0xff, (aValue) & 0xff ); //big endian - DEFAULT
193 }
194
195 return result;
196 },
197
198 'appendWords': function(args) {
199 varvalues;
200 vari,c;
201
202 if (args.constructor == Array) {
203 values = args;
204 } else {
205 values = arguments;
206 }
207
208 c = values.length;
209 for (i=0; i<c; i++) {
210 this.appendWord(values[i], false);
211 }
212
213 return this;
214 },
215
216 //-------------------------------------------------------------------------
217
218 'appendBigEndianWords': function(args) {
219 varvalues;
220 vari,c;
221
222 if (args.constructor == Array) {
223 values = args;
224 } else {
225 values = arguments;
226 }
227
228 c = values.length;
229 for (i=0; i<c; i++) {
230 this.appendWord(values[i], true);
231 }
232
233 return this;
234 },
235
236 //-------------------------------------------------------------------------
237
238 'appendBinaryString': function (aBinaryString) {
239 var i,c;
240
241 c = aBinaryString.length;
242 for (i=0; i<c; i++) {
243 this.appendByte(aBinaryString.charCodeAt(i));
244 };
245
246 return this;
247 },
248
249 //-------------------------------------------------------------------------
250
251 'byteAtIndex': function(anIndex) {
252 throw Clipperz.Base.exception.AbstractMethod;
253 },
254
255 'setByteAtIndex': function(aValue, anIndex) {
256 throw Clipperz.Base.exception.AbstractMethod;
257 },
258
259 //-------------------------------------------------------------------------
260
261 'bitAtIndex': function(aBitPosition) {
262 var result;
263 varbytePosition;
264 var bitPositionInSelectedByte;
265 var selectedByte;
266 var selectedByteMask;
267
268 bytePosition = this.length() - Math.ceil((aBitPosition + 1)/ 8);
269 bitPositionInSelectedByte = aBitPosition % 8;
270 selectedByte = this.byteAtIndex(bytePosition);
271
272 if (bitPositionInSelectedByte > 0) {
273 selectedByteMask = (1 << bitPositionInSelectedByte);
274 } else {
275 selectedByteMask = 1;
276 }
277 result = selectedByte & selectedByteMask ? 1 : 0;
278
279 return result;
280 },
281
282 //-------------------------------------------------------------------------
283
284 'bitBlockAtIndexWithSize': function(aBitPosition, aSize) {
285 var result;
286 var bitValue;
287 var i,c;
288
289 result = 0;
290 c = aSize;
291 for (i=0; i<c; i++) {
292 bitValue = this.bitAtIndex(aBitPosition + i);
293 result = result | bitValue << i;
294 }
295
296 return result;
297 },
298
299 //-------------------------------------------------------------------------
300
301 'asString': function() {
302 varresult;
303 varlength;
304 vari;
305
306 result = [];
307
308 i = 0;
309 length = this.length();
310
311 while (i < length) {
312 varcurrentCharacter;
313 varcurrentByte;
314 varunicode;
315
316 currentByte = this.byteAtIndex(i);
317
318 if ((currentByte & 0x80) == 0x00 ) { //0xxxxxxx
319 unicode = currentByte;
320 currentCharacter = String.fromCharCode(unicode);
321 } else if ((currentByte & 0xe0) == 0xc0 ) { //110xxxxx 10xxxxxx
322 unicode = (currentByte & 0x1f) << 6;
323 i++; currentByte = this.byteAtIndex(i);
324 unicode = unicode | (currentByte & 0x3f);
325
326 currentCharacter = String.fromCharCode(unicode);
327 } else if ((currentByte & 0xf0) == 0xe0 ) { //1110xxxx 10xxxxxx 10xxxxxx
328 unicode = (currentByte & 0x0f) << (6+6);
329 i++; currentByte = this.byteAtIndex(i);
330 unicode = unicode | ((currentByte & 0x3f) << 6);
331 i++; currentByte = this.byteAtIndex(i);
332 unicode = unicode | (currentByte & 0x3f);
333
334 currentCharacter = String.fromCharCode(unicode);
335 } else { //11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
336 unicode = (currentByte & 0x07) << (6+6+6);
337 i++; currentByte = this.byteAtIndex(i);
338 unicode = unicode | ((currentByte & 0x3f) << (6+6));
339 i++; currentByte = this.byteAtIndex(i);
340 unicode = unicode | ((currentByte & 0x3f) << 6);
341 i++; currentByte = this.byteAtIndex(i);
342 unicode = unicode | (currentByte & 0x3f);
343
344 currentCharacter = String.fromCharCode(unicode);
345 }
346
347 result.push(currentCharacter);
348 i++;
349 }
350
351 return result.join("");
352 },
353
354 //-------------------------------------------------------------------------
355
356 'toHexString': function() {
357 throw Clipperz.Base.exception.AbstractMethod;
358 },
359
360 //-------------------------------------------------------------------------
361
362 'base64map': "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
363 'base64mapIndex': "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(''),
364
365 //-------------------------------------------------------------------------
366
367 'appendBase64String': function(aValue) {
368 var i;
369 var length;
370
371 length = aValue.length;
372
373 if ((length % 4) != 0) {
374 Clipperz.logError("the value passed to the 'ByteArray.setBase64Value' is not correct");
375 throw Clipperz.ByteArray.exception.InvalidValue;
376 }
377
378 i = 0;
379 while (i<length) {
380 var value1, value2, value3, value4;
381 var byte1, byte2, byte3;
382
383 value1 = this.base64map.indexOf(aValue.charAt(i));
384 value2 = this.base64map.indexOf(aValue.charAt(i+1));
385 value3 = this.base64map.indexOf(aValue.charAt(i+2));
386 value4 = this.base64map.indexOf(aValue.charAt(i+3));
387
388 byte1 = (value1 << 2) | ((value2 & 0x30) >> 4);
389 if (value3 != -1) {
390 byte2 = ((value2 & 0x0f) << 4) | ((value3 & 0x3c) >> 2);
391
392 if (value4 != -1) {
393 byte3 = ((value3 & 0x03) << 6) | (value4);
394 } else {
395 byte3 = null;
396 }
397 } else {
398 byte2 = null;
399 byte3 = null;
400 }
401
402 this.appendByte(byte1);
403 this.appendByte(byte2);
404 this.appendByte(byte3);
405
406 i += 4;
407 }
408
409 return this;
410 },
411
412 //-------------------------------------------------------------------------
413
414 'toBase64String': function() {
415 var result;
416 var length;
417 var i;
418 var byte1, byte2, byte3;
419 var char1, char2, char3, char4;
420
421 i = 0;
422 length = this.length();
423 result = new Array(Math.ceil(length/3));
424
425 while (i < length) {
426 byte1 = this.byteAtIndex(i);
427 if ((i+2) < length) {
428 byte2 = this.byteAtIndex(i+1);
429 byte3 = this.byteAtIndex(i+2);
430 } else if ((i+2) == length) {
431 byte2 = this.byteAtIndex(i+1);
432 byte3 = null;
433 } else {
434 byte2 = null;
435 byte3 = null;
436 }
437
438 char1 = this.base64mapIndex[byte1 >> 2];
439 if (byte2 != null) {
440 char2 = this.base64mapIndex[((byte1 & 0x03) << 4) | ((byte2 & 0xf0) >> 4)];
441 if (byte3 != null) {
442 char3 = this.base64mapIndex[((byte2 & 0x0f) << 2) | ((byte3 & 0xc0) >> 6)];
443 char4 = this.base64mapIndex[(byte3 & 0x3f)];
444 } else {
445 char3 = this.base64mapIndex[(byte2 & 0x0f) << 2];
446 char4 = "=";
447 }
448 } else {
449 char2 = this.base64mapIndex[(byte1 & 0x03) << 4];
450 char3 = "=";
451 char4 = "=";
452 }
453
454 result.push(char1 + char2 + char3 + char4);
455
456 i += 3;
457 }
458
459 return result.join("");
460 },
461
462 //-------------------------------------------------------------------------
463
464 'base32map': "0123456789abcdefghjkmnpqrstvwxyz",
465 'base32mapIndex': "0123456789abcdefghjkmnpqrstvwxyz".split(''),
466
467 //-------------------------------------------------------------------------
468
469 'appendBase32String': function(aValue) {
470 var value;
471 var i;
472 var length;
473 var value1, value2, value3, value4, value5, value6, value7, value8;
474 var byte1, byte2, byte3, byte4, byte5;
475
476 value = aValue.toLowerCase();
477 value = value.replace(/[\s\-]/g, '');
478 value = value.replace(/[0o]/g, '0');
479 value = value.replace(/[1il]/g, '1');
480
481 length = value.length;
482
483 if ((length % 8) != 0) {
484 Clipperz.logError("the value passed to the 'ByteArray.setBase32Value' is not correct");
485 throw Clipperz.ByteArray.exception.InvalidValue;
486 }
487
488 i = 0;
489 while (i<length) {
490 value1 = this.base32map.indexOf(value.charAt(i));
491 value2 = this.base32map.indexOf(value.charAt(i+1));
492 value3 = this.base32map.indexOf(value.charAt(i+2));
493 value4 = this.base32map.indexOf(value.charAt(i+3));
494 value5 = this.base32map.indexOf(value.charAt(i+4));
495 value6 = this.base32map.indexOf(value.charAt(i+5));
496 value7 = this.base32map.indexOf(value.charAt(i+6));
497 value8 = this.base32map.indexOf(value.charAt(i+7));
498
499 byte1 = byte2 = byte3 = byte4 = byte5 = null;
500
501 byte1 = (value1 << 3) | ((value2 & 0x1c) >> 2);
502 if (value3 != -1) {
503 byte2 = ((value2 & 0x03) << 6) | (value3 << 1) | ((value4 & 0x10) >> 4);
504 if (value5 != -1) {
505 byte3 = ((value4 & 0x0f) << 4) | ((value5 & 0x1e) >> 1);
506 if (value6 != -1) {
507 byte4 = ((value5 & 0x01) << 7) | (value6 << 2) | ((value7 & 0x18) >> 3);
508 if (value8 != -1) {
509 byte5 = ((value7 & 0x07) << 5) | (value8);
510 }
511 }
512 }
513 }
514
515 this.appendByte(byte1);
516 this.appendByte(byte2);
517 this.appendByte(byte3);
518 this.appendByte(byte4);
519 this.appendByte(byte5);
520
521 i += 8;
522 }
523
524 return this;
525 },
526
527 //-------------------------------------------------------------------------
528
529 'toBase32String': function() {
530 var result;
531 var length;
532 var i;
533 var byte1, byte2, byte3, byte4, byte5;
534 var char1, char2, char3, char4, char5, char6, char7, char8;
535
536 i = 0;
537 length = this.length();
538 result = new Array(Math.ceil(length/5));
539
540 while (i < length) {
541 byte1 = this.byteAtIndex(i);
542
543 if ((i+4) < length) {
544 byte2 = this.byteAtIndex(i+1);
545 byte3 = this.byteAtIndex(i+2);
546 byte4 = this.byteAtIndex(i+3);
547 byte5 = this.byteAtIndex(i+4);
548 } else if ((i+4) == length) {
549 byte2 = this.byteAtIndex(i+1);
550 byte3 = this.byteAtIndex(i+2);
551 byte4 = this.byteAtIndex(i+3);
552 byte5 = null;
553 } else if ((i+3) == length) {
554 byte2 = this.byteAtIndex(i+1);
555 byte3 = this.byteAtIndex(i+2);
556 byte4 = null;
557 byte5 = null;
558 } else if ((i+2) == length) {
559 byte2 = this.byteAtIndex(i+1);
560 byte3 = null;
561 byte4 = null;
562 byte5 = null;
563 } else {
564 byte2 = null;
565 byte3 = null;
566 byte4 = null;
567 byte5 = null;
568 }
569
570
571 char1 = this.base32mapIndex[byte1 >> 3];
572 char2 = char3 = char4 = char5 = char6 = char7 = char8 = "=";
573
574 if (byte2 != null) {
575 char2 = this.base32mapIndex[((byte1 & 0x07) << 2) | ((byte2 & 0xc0) >> 6)];
576 char3 = this.base32mapIndex[((byte2 & 0x3e) >> 1)];
577 if (byte3 != null) {
578 char4 = this.base32mapIndex[((byte2 & 0x01) << 4) | ((byte3 & 0xf0) >> 4)];
579 if (byte4 != null) {
580 char5 = this.base32mapIndex[((byte3 & 0x0f) << 1) | ((byte4 & 0x80) >> 7)];
581 char6 = this.base32mapIndex[(byte4 & 0x7c) >> 2];
582 if (byte5 != null) {
583 char7 = this.base32mapIndex[((byte4 & 0x03) << 3) | ((byte5 & 0xe0) >> 5)];
584 char8 = this.base32mapIndex[(byte5 & 0x1f)];
585 } else {
586 char7 = this.base32mapIndex[(byte4 & 0x03) << 3];
587 }
588 } else {
589 char5 = this.base32mapIndex[(byte3 & 0x0f) << 1];
590 }
591
592 } else {
593 char4 = this.base32mapIndex[(byte2 & 0x01) << 4];
594 }
595 } else {
596 char2 = this.base32mapIndex[(byte1 & 0x07) << 2];
597 }
598
599 result.push(char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8);
600 i += 5;
601 }
602
603 return result.join("");
604 },
605
606 //-------------------------------------------------------------------------
607
608 'toBinaryString': function () {
609 vari, c;
610 var result;
611
612 result = '';
613
614 c = this.length();
615 for (i=0; i<c; i++) {
616 result += String.fromCharCode(this.byteAtIndex(i));
617 }
618
619 return result;
620 },
621
622
623 //-------------------------------------------------------------------------
624
625 'split': function(aStartingIndex, anEndingIndex) {
626 throw Clipperz.Base.exception.AbstractMethod;
627 },
628
629 //-------------------------------------------------------------------------
630
631 'increment': function() {
632 var i;
633 var done;
634
635 done = false;
636 i = this.length() - 1;
637
638 while ((i>=0) && (done == false)) {
639 var currentByteValue;
640
641 currentByteValue = this.byteAtIndex(i);
642
643 if (currentByteValue == 0xff) {
644 this.setByteAtIndex(0, i);
645 if (i>= 0) {
646 i --;
647 } else {
648 done = true;
649 }
650 } else {
651 this.setByteAtIndex(currentByteValue + 1, i);
652 done = true;
653 }
654 }
655 },
656
657 //-------------------------------------------------------------------------
658
659 'arrayValues': function() {
660 throw Clipperz.Base.exception.AbstractMethod;
661 },
662
663 //-------------------------------------------------------------------------
664 __syntaxFix__: "syntax fix"
665
666});
667
668//=============================================================================
669//
670 //Clipperz.ByteArray_hex
671//
672//=============================================================================
673/*
674Clipperz.ByteArray_hex = function (args) {
675 this._value = "";
676
677 if (typeof(args) != 'undefined') {
678 if (args.constructor == Array) {
679 this.appendBytes(args);
680 } else if (args.constructor == String) {
681 if (args.indexOf("0x") == 0) {
682 varvalue;
683
684 value = args.substring(2).toLowerCase();
685 if (/[0123456789abcdef]* /.test(value)) { the space in the regexp shoud be removed if the code is activate
686 if ((value.length % 2) == 0) {
687 this._value = value;
688 } else {
689 this._value = "0" + value;
690 }
691 } else {
692Clipperz.logError("Clipperz.ByteArray should be inizialized with an hex string.");
693 throw Clipperz.ByteArray.exception.InvalidValue;
694 }
695 } else {
696 varvalue;
697 vari,c;
698
699 c = args.length;
700 value = new Array(c);
701 for (i=0; i<c; i++) {
702 value.push(Clipperz.ByteArray.unicodeToUtf8HexString(args.charCodeAt(i)));
703 }
704
705 this._value = value.join("");
706 }
707 } else {
708 this.appendBytes(MochiKit.Base.extend(null, arguments));
709 }
710 }
711 return this;
712}
713
714Clipperz.ByteArray_hex.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), {
715
716 //-------------------------------------------------------------------------
717
718 'toString': function() {
719 return "Clipperz.ByteArray_hex";
720 },
721
722 //-------------------------------------------------------------------------
723
724 'clone': function() {
725 var result;
726
727 result = this.newInstance();
728 result._value = this._value;
729
730 return result;
731 },
732
733 //-------------------------------------------------------------------------
734
735 'newInstance': function() {
736 return new Clipperz.ByteArray_hex();
737 },
738
739 //-------------------------------------------------------------------------
740
741 'reset': function() {
742 this._value = "";
743 },
744
745 //-------------------------------------------------------------------------
746
747 'length': function() {
748 return (this._value.length / 2);
749 },
750
751 //-------------------------------------------------------------------------
752
753 'appendBlock': function(aBlock) {
754 this._value = this._value += aBlock.toHexString().substring(2);
755
756 return this;
757 },
758
759 //-------------------------------------------------------------------------
760
761 'appendByte': function(aValue) {
762 if (aValue != null) {
763 this.checkByteValue(aValue);
764 this._value += Clipperz.ByteArray.byteToHex(aValue);
765 }
766
767 return this;
768 },
769
770 //-------------------------------------------------------------------------
771
772 'byteAtIndex': function(anIndex) {
773 return parseInt(this._value.substr(anIndex*2, 2), 16);
774 },
775
776 'setByteAtIndex': function(aValue, anIndex) {
777 varmissingBytes;
778
779 this.checkByteValue(aValue);
780
781 missingBytes = anIndex - this.length();
782
783 if (missingBytes < 0) {
784 varcurrentValue;
785 varfirstCutIndex;
786 var secondCutIndex;
787
788 firstCutIndex = anIndex * 2;
789 secondCutIndex = firstCutIndex + 2;
790 currentValue = this._value;
791 this._value =currentValue.substring(0, firstCutIndex) +
792 Clipperz.ByteArray.byteToHex(aValue) +
793 currentValue.substring(secondCutIndex);
794 } else if (missingBytes == 0) {
795 this.appendByte(aValue);
796 } else {
797 var i,c;
798
799 c = missingBytes;
800 for (i=0; i<c; i++) {
801 this.appendByte(0);
802 }
803
804 this.appendByte(aValue);
805 }
806 },
807
808 //-------------------------------------------------------------------------
809
810 'toHexString': function() {
811 return "0x" + this._value;
812 },
813
814 //-------------------------------------------------------------------------
815
816 'split': function(aStartingIndex, anEndingIndex) {
817 var result;
818 varstartingIndex;
819 var endingIndex;
820
821 result = this.newInstance();
822
823 startingIndex = aStartingIndex * 2;
824 if (typeof(anEndingIndex) != 'undefined') {
825 endingIndex = anEndingIndex * 2;
826 result._value = this._value.substring(startingIndex, endingIndex);
827 } else {
828 result._value = this._value.substring(startingIndex);
829 }
830
831 return result;
832 },
833
834 //-------------------------------------------------------------------------
835
836 'arrayValues': function() {
837 var result;
838 var i,c;
839
840 c = this.length();
841
842 result = new Array(c);
843 for (i=0; i<c; i++) {
844 result[i] = this.byteAtIndex(i);
845 }
846
847 return result;
848 },
849
850 //-------------------------------------------------------------------------
851 __syntaxFix__: "syntax fix"
852});
853*/
854
855//=============================================================================
856//
857 //Clipperz.ByteArray_array
858//
859//=============================================================================
860
861Clipperz.ByteArray_array = function (args) {
862 if (typeof(args) != 'undefined') {
863 if (args.constructor == Array) {
864 this._value = args.slice(0);
865 } else if (args.constructor == String) {
866 var result;
867 varvalue;
868 var i, c;
869
870 if (args.indexOf("0x") == 0) {
871
872 value = args.substring(2).toLowerCase();
873 if (/[0123456789abcdef]*/.test(value)) {
874 if ((value.length % 2) != 0) {
875 value = "0" + value;
876 }
877 } else {
878 Clipperz.logError("Clipperz.ByteArray should be inizialized with an hex string.");
879 throw Clipperz.ByteArray.exception.InvalidValue;
880 }
881
882 c = value.length / 2
883 result = new Array(c);
884 for (i=0; i<c; i++) {
885 result[i] = parseInt(value.substr(i*2, 2), 16);
886 }
887
888 } else {
889 var unicode;
890 result = [];
891 c = args.length;
892 for (i=0; i<c; i++) {
893 // Clipperz.ByteArray.pushUtf8BytesOfUnicodeChar(result, args.charCodeAt(i));
894
895 unicode = args.charCodeAt(i);
896 if (unicode <= 0x7f) { //0x00000000 - 0x0000007f -> 0xxxxxxx
897 result.push(unicode);
898 // } else if ((unicode >= 0x80) && (unicode <= 0x7ff)) { //0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
899 } else if (unicode <= 0x7ff) { //0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
900 result.push((unicode >> 6) | 0xc0);
901 result.push((unicode & 0x3F) | 0x80);
902 // } else if ((unicode >= 0x0800) && (unicode <= 0xffff)) { //0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
903 } else if (unicode <= 0xffff) { //0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
904 result.push((unicode >> 12) | 0xe0);
905 result.push(((unicode >> 6) & 0x3f) | 0x80);
906 result.push((unicode & 0x3f) | 0x80);
907 } else { //0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
908 result.push((unicode >> 18) | 0xf0);
909 result.push(((unicode >> 12) & 0x3f) | 0x80);
910 result.push(((unicode >> 6) & 0x3f) | 0x80);
911 result.push((unicode & 0x3f) | 0x80);
912 }
913 }
914 }
915
916
917 this._value = result;
918 } else {
919 this._value = [];
920 this.appendBytes(MochiKit.Base.extend(null, arguments));
921 }
922 } else {
923 this._value = [];
924 }
925
926 return this;
927}
928
929Clipperz.ByteArray_array.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), {
930
931 //-------------------------------------------------------------------------
932
933 'toString': function() {
934 return "Clipperz.ByteArray_array";
935 },
936
937 //-------------------------------------------------------------------------
938
939 'clone': function() {
940 var result;
941
942 result = this.newInstance();
943 result.appendBytes(this._value);
944
945 return result;
946 },
947
948 //-------------------------------------------------------------------------
949
950 'newInstance': function() {
951 return new Clipperz.ByteArray_array();
952 },
953
954 //-------------------------------------------------------------------------
955
956 'reset': function() {
957 this._value = [];
958 },
959
960 //-------------------------------------------------------------------------
961
962 'length': function() {
963 return (this._value.length);
964 },
965
966 //-------------------------------------------------------------------------
967
968 'appendBlock': function(aBlock) {
969 MochiKit.Base.extend(this._value, aBlock._value);
970
971 return this;
972 },
973
974 //-------------------------------------------------------------------------
975
976 'appendByte': function(aValue) {
977 if (aValue != null) {
978 this.checkByteValue(aValue);
979 this._value.push(aValue);
980 }
981
982 return this;
983 },
984
985 //-------------------------------------------------------------------------
986
987 'byteAtIndex': function(anIndex) {
988 return this._value[anIndex];
989 },
990
991 'setByteAtIndex': function(aValue, anIndex) {
992 varmissingBytes;
993
994 this.checkByteValue(aValue);
995
996 missingBytes = anIndex - this.length();
997
998 if (missingBytes < 0) {
999 this._value[anIndex] = aValue;
1000 } else if (missingBytes == 0) {
1001 this._value.push(aValue);
1002 } else {
1003 var i,c;
1004
1005 c = missingBytes;
1006 for (i=0; i<c; i++) {
1007 this._value.push(0);
1008 }
1009
1010 this._value.push(aValue);
1011 }
1012 },
1013
1014 //-------------------------------------------------------------------------
1015
1016 'toHexString': function() {
1017 var result;
1018 var i, c;
1019
1020 result = "0x";
1021 c = this.length();
1022 for (i=0; i<c; i++) {
1023 result += Clipperz.ByteArray.byteToHex(this._value[i]);
1024 }
1025
1026 return result;
1027 },
1028
1029 //-------------------------------------------------------------------------
1030
1031 'split': function(aStartingIndex, anEndingIndex) {
1032 var result;
1033
1034 result = this.newInstance();
1035 result._value = this._value.slice(aStartingIndex, anEndingIndex ? anEndingIndex : this.length());
1036
1037 return result;
1038 },
1039
1040 //-------------------------------------------------------------------------
1041
1042 'arrayValues': function() {
1043 return this._value.slice(0);
1044 },
1045
1046 //-------------------------------------------------------------------------
1047 __syntaxFix__: "syntax fix"
1048});
1049
1050
1051
1052
1053
1054//=============================================================================
1055//
1056 //Clipperz.ByteArray_string
1057//
1058//=============================================================================
1059/*
1060Clipperz.ByteArray_string = function (args) {
1061 this._value = "";
1062
1063 if (typeof(args) != 'undefined') {
1064 if (args.constructor == Array) {
1065 this.appendBytes(args);
1066 } else if (args.constructor == String) {
1067 var result;
1068 varvalue;
1069 var i, c;
1070
1071 if (args.indexOf("0x") == 0) {
1072
1073 value = args.substring(2).toLowerCase();
1074 if (/[0123456789abcdef]* /.test(value)) { the space in the regexp shoud be removed if the code is activated
1075 if ((value.length % 2) != 0) {
1076 value = "0" + value;
1077 }
1078 } else {
1079Clipperz.logError("Clipperz.ByteArray should be inizialized with an hex string.");
1080 throw Clipperz.ByteArray.exception.InvalidValue;
1081 }
1082 } else {
1083 value = "";
1084 c = args.length;
1085 for (i=0; i<c; i++) {
1086 value += Clipperz.ByteArray.unicodeToUtf8HexString(args.charCodeAt(i));
1087 }
1088 }
1089
1090 c = value.length / 2
1091 for (i=0; i<c; i++) {
1092 this.appendByte(parseInt(value.substr(i*2, 2), 16));
1093 }
1094 } else {
1095 this.appendBytes(MochiKit.Base.extend(null, arguments));
1096 }
1097 }
1098
1099 return this;
1100}
1101
1102Clipperz.ByteArray_string.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), {
1103
1104 //-------------------------------------------------------------------------
1105
1106 'toString': function() {
1107 return "Clipperz.ByteArray_string";
1108 },
1109
1110 //-------------------------------------------------------------------------
1111
1112 'clone': function() {
1113 var result;
1114
1115 result = this.newInstance();
1116 result._value = this._value;
1117
1118 return result;
1119 },
1120
1121 //-------------------------------------------------------------------------
1122
1123 'newInstance': function() {
1124 return new Clipperz.ByteArray_string();
1125 },
1126
1127 //-------------------------------------------------------------------------
1128
1129 'reset': function() {
1130 this._value = "";
1131 },
1132
1133 //-------------------------------------------------------------------------
1134
1135 'length': function() {
1136 return (this._value.length);
1137 },
1138
1139 //-------------------------------------------------------------------------
1140
1141 'appendBlock': function(aBlock) {
1142 this._value += aBlock._value;
1143
1144 return this;
1145 },
1146
1147 //-------------------------------------------------------------------------
1148
1149 'appendByte': function(aValue) {
1150 if (aValue != null) {
1151 this.checkByteValue(aValue);
1152 this._value += String.fromCharCode(aValue);
1153 }
1154
1155 return this;
1156 },
1157
1158 //-------------------------------------------------------------------------
1159
1160 'byteAtIndex': function(anIndex) {
1161 return this._value.charCodeAt(anIndex);
1162 },
1163
1164 'setByteAtIndex': function(aValue, anIndex) {
1165 varmissingBytes;
1166
1167 this.checkByteValue(aValue);
1168
1169 missingBytes = anIndex - this.length();
1170
1171 if (missingBytes < 0) {
1172 this._value = this._value.substring(0, anIndex) + String.fromCharCode(aValue) + this._value.substring(anIndex + 1);
1173 } else if (missingBytes == 0) {
1174 this.appendByte(aValue);
1175 } else {
1176 var i,c;
1177
1178 c = missingBytes;
1179 for (i=0; i<c; i++) {
1180 this.appendByte(0);
1181 }
1182
1183 this.appendByte(aValue);
1184 }
1185 },
1186
1187 //-------------------------------------------------------------------------
1188
1189 'toHexString': function() {
1190 var result;
1191 var i, c;
1192
1193 result = "0x";
1194 c = this.length();
1195 for (i=0; i<c; i++) {
1196 result += Clipperz.ByteArray.byteToHex(this.byteAtIndex(i));
1197 }
1198
1199 return result;
1200 },
1201
1202 //-------------------------------------------------------------------------
1203
1204 'split': function(aStartingIndex, anEndingIndex) {
1205 var result;
1206 result = this.newInstance();
1207 result._value = this._value.substring(aStartingIndex, anEndingIndex ? anEndingIndex : this.length());
1208
1209 return result;
1210 },
1211
1212 //-------------------------------------------------------------------------
1213
1214 'arrayValues': function() {
1215 var result;
1216 var i,c;
1217
1218 c = this.length();
1219
1220 result = new Array(c);
1221 for (i=0; i<c; i++) {
1222 result[i] = this.byteAtIndex(i);
1223 }
1224
1225 return result;
1226 },
1227
1228 //-------------------------------------------------------------------------
1229 __syntaxFix__: "syntax fix"
1230});
1231*/
1232
1233//=============================================================================
1234//
1235 //Clipperz.ByteArray
1236//
1237//=============================================================================
1238
1239Clipperz.ByteArray = Clipperz.ByteArray_array;
1240//Clipperz.ByteArray = Clipperz.ByteArray_string;
1241//Clipperz.ByteArray = Clipperz.ByteArray_hex;
1242
1243//#############################################################################
1244
1245Clipperz.ByteArray.byteToHex = function(aByte) {
1246 return ((aByte < 16) ? "0" : "") + aByte.toString(16);
1247}
1248
1249
1250Clipperz.ByteArray.unicodeToUtf8HexString = function(aUnicode) {
1251 var result;
1252 varself;
1253
1254 self = Clipperz.ByteArray;
1255
1256 if (aUnicode <= 0x7f) { //0x00000000 - 0x0000007f -> 0xxxxxxx
1257 result = self.byteToHex(aUnicode);
1258 // } else if ((aUnicode >= 0x80) && (aUnicode <= 0x7ff)) { //0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
1259 } else if (aUnicode <= 0x7ff) { //0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
1260 result = self.byteToHex((aUnicode >> 6) | 0xc0);
1261 result += self.byteToHex((aUnicode & 0x3F) | 0x80);
1262 // } else if ((aUnicode >= 0x0800) && (aUnicode <= 0xffff)) { //0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
1263 } else if (aUnicode <= 0xffff) { //0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
1264 result = self.byteToHex((aUnicode >> 12) | 0xe0);
1265 result += self.byteToHex(((aUnicode >> 6) & 0x3f) | 0x80);
1266 result += self.byteToHex((aUnicode & 0x3f) | 0x80);
1267 } else { //0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1268 result = self.byteToHex((aUnicode >> 18) | 0xf0);
1269 result += self.byteToHex(((aUnicode >> 12) & 0x3f) | 0x80);
1270 result += self.byteToHex(((aUnicode >> 6) & 0x3f) | 0x80);
1271 result += self.byteToHex((aUnicode & 0x3f) | 0x80);
1272 }
1273
1274 return result;
1275}
1276
1277Clipperz.ByteArray.pushUtf8BytesOfUnicodeChar = function(anArray, aUnicode) {
1278 varself;
1279
1280 self = Clipperz.ByteArray;
1281
1282 if (aUnicode <= 0x7f) { //0x00000000 - 0x0000007f -> 0xxxxxxx
1283 anArray.push(aUnicode);
1284 // } else if ((aUnicode >= 0x80) && (aUnicode <= 0x7ff)) { //0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
1285 } else if (aUnicode <= 0x7ff) { //0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
1286 anArray.push((aUnicode >> 6) | 0xc0);
1287 anArray.push((aUnicode & 0x3F) | 0x80);
1288 // } else if ((aUnicode >= 0x0800) && (aUnicode <= 0xffff)) { //0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
1289 } else if (aUnicode <= 0xffff) { //0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
1290 anArray.push((aUnicode >> 12) | 0xe0);
1291 anArray.push(((aUnicode >> 6) & 0x3f) | 0x80);
1292 anArray.push((aUnicode & 0x3f) | 0x80);
1293 } else { //0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1294 anArray.push((aUnicode >> 18) | 0xf0);
1295 anArray.push(((aUnicode >> 12) & 0x3f) | 0x80);
1296 anArray.push(((aUnicode >> 6) & 0x3f) | 0x80);
1297 anArray.push((aUnicode & 0x3f) | 0x80);
1298 }
1299}
1300
1301Clipperz.ByteArray.prefixMatchingBits = function (aValue, bValue) {
1302 varresult;
1303 var i,c;
1304
1305 result = 0;
1306
1307 c = Math.min(aValue.length(), bValue.length());
1308 i = 0;
1309 while (i<c && (aValue.byteAtIndex(i) == bValue.byteAtIndex(i))) {
1310 result += 8;
1311 i++;
1312 }
1313
1314 if (i<c) {
1315 varxorValue;
1316
1317 xorValue = (aValue.byteAtIndex(i) ^ bValue.byteAtIndex(i));
1318
1319 if (xorValue >= 128) {
1320 result += 0;
1321 } else if (xorValue >= 64) {
1322 result += 1;
1323 } else if (xorValue >= 32) {
1324 result += 2;
1325 } else if (xorValue >= 16) {
1326 result += 3;
1327 } else if (xorValue >= 8) {
1328 result += 4;
1329 } else if (xorValue >= 4) {
1330 result += 5;
1331 } else if (xorValue >= 2) {
1332 result += 6;
1333 } else if (xorValue >= 1) {
1334 result += 7;
1335 }
1336 }
1337
1338 return result;
1339};
1340
1341Clipperz.ByteArray.exception = {
1342 InvalidValue: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue")
1343};
1344
1345//#############################################################################
1346
1347Clipperz.ByteArrayIterator = function(args) {
1348 args = args || {};
1349
1350 this._byteArray = args.byteArray;
1351 this._blockSize = args.blockSize;
1352 this._finalPadding = args.finalPadding || false;
1353
1354 this._currentPosition = 0;
1355
1356 return this;
1357}
1358
1359Clipperz.ByteArrayIterator.prototype = MochiKit.Base.update(null, {
1360
1361 //-------------------------------------------------------------------------
1362
1363 'toString': function() {
1364 return "Clipperz.ByteArrayIterator";
1365 },
1366
1367 //-------------------------------------------------------------------------
1368
1369 'blockSize': function() {
1370 var result;
1371
1372 result = this._blockSize;
1373
1374 return result;
1375 },
1376
1377 //-------------------------------------------------------------------------
1378
1379 'currentPosition': function() {
1380 var result;
1381
1382 result = this._currentPosition;
1383
1384 return result;
1385 },
1386
1387 //-------------------------------------------------------------------------
1388
1389 'byteArray': function() {
1390 var result;
1391
1392 result = this._byteArray;
1393
1394 return result;
1395 },
1396
1397 //-------------------------------------------------------------------------
1398
1399 'finalPadding': function() {
1400 var result;
1401
1402 result = this._finalPadding;
1403
1404 return result;
1405 },
1406
1407 //-------------------------------------------------------------------------
1408
1409 'nextBlock': function() {
1410 var result;
1411 var currentPosition;
1412 varbyteArrayLength;
1413
1414 currentPosition = this._currentPosition;
1415 byteArrayLength = this.byteArray().length();
1416
1417 if (currentPosition < byteArrayLength) {
1418 var i,c;
1419
1420 c = this.blockSize();
1421 result = new Array(c);
1422 for (i=0; i<c; i++) {
1423 if (currentPosition < byteArrayLength) {
1424 result[i] = this.byteArray().byteAtIndex(currentPosition);
1425 currentPosition++;
1426 } else if (this.finalPadding() == true) {
1427 result[i] = 0;
1428 }
1429 }
1430
1431 this._currentPosition = currentPosition;
1432 } else {
1433 result = null;
1434 }
1435
1436 return result;
1437 },
1438
1439 //-------------------------------------------------------------------------
1440
1441 'nextBlockArray': function() {
1442 var result;
1443 var nextBlock;
1444
1445 nextBlock = this.nextBlock();
1446
1447 if (nextBlock != null) {
1448 result = new Clipperz.ByteArray(nextBlock);
1449 } else {
1450 result = null;
1451 }
1452
1453 return result;
1454 },
1455
1456 //-----------------------------------------------------------------------------
1457 __syntaxFix__: "syntax fix"
1458
1459});
diff --git a/frontend/delta/js/Clipperz/CSVProcessor.js b/frontend/delta/js/Clipperz/CSVProcessor.js
new file mode 100644
index 0000000..1288ed7
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/CSVProcessor.js
@@ -0,0 +1,344 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25
26
27Clipperz.CSVProcessor = function(args) {
28 args = args || {};
29
30 // this._status = undefined;
31 // this._error_input= undefined;
32 // this._string = undefined;
33 // this._fields = undefined;
34
35 this._quoteChar = args['quoteChar'] ||"\042";
36 this._eol = args['eol'] ||"";
37 this._escapeChar = args['escapeChar'] ||"\042";
38 this._separatorChar = args['separatorChar'] ||",";
39 this._binary = args['binary'] ||false;
40 this._alwaysQuote = args['alwaysQuote'] ||false;
41
42 return this;
43}
44
45//=============================================================================
46
47Clipperz.CSVProcessor.prototype = MochiKit.Base.update(null, {
48
49 //-------------------------------------------------------------------------
50
51 'quoteChar': function() {
52 return this._quoteChar;
53 },
54
55 //-------------------------------------------------------------------------
56
57 'eol': function() {
58 return this._eol;
59 },
60
61 //-------------------------------------------------------------------------
62
63 'escapeChar': function() {
64 return this._escapeChar;
65 },
66
67 //-------------------------------------------------------------------------
68
69 'separatorChar': function() {
70 return this._separatorChar;
71 },
72
73 'setSeparatorChar': function(aValue) {
74 this._separatorChar = aValue;
75 },
76
77 //-------------------------------------------------------------------------
78
79 'binary': function() {
80 return this._binary;
81 },
82
83 //-------------------------------------------------------------------------
84
85 'alwaysQuote': function() {
86 return this._alwaysQuote;
87 },
88
89 //-------------------------------------------------------------------------
90/*
91 'parse': function(aValue) {
92 var result;
93 var lines;
94 var parameter;
95
96//Clipperz.logDebug(">>> CSVProcessor.parse");
97 result = [];
98
99 lines = aValue.replace(/\r?\n/g, "\n").replace(/^\n* /g, "").replace(/\n$/g, "");;
100 parameter = {
101 line: lines
102 }
103
104 do {
105 var fields;
106
107 fields = this.parseLine(parameter);
108
109 if (fields != null) {
110 result.push(fields);
111 }
112
113 parameter.line = parameter.line.replace(/^\n* /g, "").replace(/\n$/g, "");
114
115//Clipperz.logDebug("line: '" + parameter.line + "'");
116 } while (parameter.line != "");
117//Clipperz.logDebug("--- CSVProcessor.parse - result: " + Clipperz.Base.serializeJSON(result));
118//Clipperz.logDebug("<<< CSVProcessor.parse");
119
120 return result;
121 },
122*/
123 //-------------------------------------------------------------------------
124
125 'deferredParse_core': function(aContext) {
126 var deferredResult;
127
128 if (aContext.line == "") {
129 deferredResult = MochiKit.Async.succeed(aContext.result);
130 } else {
131 var fields;
132
133 fields = this.parseLine(aContext);
134 if (fields != null) {
135 aContext.result.push(fields);
136 }
137
138 aContext.line = aContext.line.replace(/^\n*/g, "").replace(/\n$/g, "");
139
140 deferredResult = new Clipperz.Async.Deferred("CVSProcessor.deferredParse_core");
141 // deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
142 deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
143 deferredResult.addCallback(MochiKit.Async.wait, 0.2);
144 deferredResult.addMethod(this, 'deferredParse_core')
145 deferredResult.callback(aContext);
146 }
147
148 return deferredResult;
149 },
150
151 //.........................................................................
152
153 'deferredParse': function(aValue) {
154 var deferredResult;
155 var lines;
156 var context;
157
158 lines = aValue.replace(/\r?\n/g, "\n").replace(/^\n*/g, "").replace(/\n$/g, "");
159
160 context = {
161 line: lines,
162 size: lines.length,
163 result: []
164 }
165
166 deferredResult = new Clipperz.Async.Deferred("CSVProcessor.deferredParse");
167 deferredResult.addMethod(this, 'deferredParse_core');
168 deferredResult.callback(context);
169
170 return deferredResult;
171 },
172
173 //-------------------------------------------------------------------------
174
175 'parseLine': function(aParameter) {
176 var result;
177 var palatable;
178 var line;
179 var processedField;
180
181 result = [];
182
183 do {
184 processedField = this.parseField(aParameter);
185 if (processedField != null) {
186 result.push(processedField)
187 };
188 } while (processedField != null);
189
190 return result;
191 },
192
193 //-------------------------------------------------------------------------
194
195 'parseField': function(aParameter) {
196 var result;
197
198 var inQuotes;
199 var validRegExp;
200 var singleQuoteBeginRegexp;
201 var escapedQuoteBeginRegexp;
202 var singleQuoteCommaEndRegexp;
203 var singleQuoteNewLineEndRegexp;
204 var commaBeginRegexp;
205 var newlineRegexp;
206
207
208 singleQuoteBeginRegexp = new RegExp("^" + '\\' + this.quoteChar());
209 escapedQuoteBeginRegexp = new RegExp("^" + '\\' + this.escapeChar() + '\\' + this.quoteChar());
210 singleQuoteCommaEndRegexp= new RegExp("^" + '\\' + this.quoteChar() + '\\' + this.separatorChar());
211 singleQuoteNewLineEndRegexp= new RegExp("^" + '\\' + this.quoteChar() + "\n");
212 commaBeginRegexp = new RegExp("^" + '\\' + this.separatorChar());
213 newlineRegexp = new RegExp("^\n");
214
215 inQuotes = false;
216
217//Clipperz.logDebug("#################################### '" + aParameter.line + "'");
218 if (aParameter.line == "") {
219 if (aParameter.isThereAnEmptyFinalField == true) {
220 aParameter.isThereAnEmptyFinalField = false;
221 result = "";
222 } else {
223 result = null;
224 }
225 } else {
226 if (this.binary()) {
227 validRegexp = /^./;
228 // validRegexp = /^[^\\]/;
229 } else {
230 validRegexp = /^[\t\040-\176]/;
231 }
232
233 try {
234 var done;
235
236 done = false;
237 result = "";
238
239 while (!done) {
240 if (aParameter.line.length < 1) {
241//Clipperz.logDebug("---> 1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
242 if (inQuotes == true) {
243//Clipperz.logDebug("---> 1.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
244 throw new Error("CSV Parsing error; end of string, missing closing double-quote...");
245 } else {
246//Clipperz.logDebug("---> 1.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
247 done = true;
248 }
249 } else if (escapedQuoteBeginRegexp.test(aParameter.line)) {
250//Clipperz.logDebug("---> 2.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
251 result += this.quoteChar();
252 aParameter.line = aParameter.line.substr(2, aParameter.line.length - 1);
253//Clipperz.logDebug("<--- 2.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
254 } else if (singleQuoteBeginRegexp.test(aParameter.line)) {
255//Clipperz.logDebug("---> 3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
256 if (inQuotes == true) {
257 if (aParameter.line.length == 1) {
258//Clipperz.logDebug("---> 3.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
259 aParameter.line = '';
260 done = true;
261 } else if (singleQuoteCommaEndRegexp.test(aParameter.line)) {
262//Clipperz.logDebug("---> 3.3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
263 aParameter.line = aParameter.line.substr(2, aParameter.line.length - 1);
264 done = true;
265//Clipperz.logDebug("<--- 3.3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
266 } else if (singleQuoteNewLineEndRegexp.test(aParameter.line)) {
267 aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
268 done = true;
269 } else {
270 throw new Error("CSV Parsing error; double-quote, followed by undesirable character (bad character sequence)... " + aParameter.line);
271 }
272 } else {
273//Clipperz.logDebug("---> 4: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
274 if (result == "") {
275//Clipperz.logDebug("---> 4.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
276 inQuotes = true;
277 aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
278//Clipperz.logDebug("<--- 4.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
279 } else {
280 throw new Error("CSV Parsing error; double-quote, outside of double-quotes (bad character sequence)...");
281 }
282 }
283 } else if (commaBeginRegexp.test(aParameter.line)) {
284//Clipperz.logDebug("---> 5: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
285 if (inQuotes) {
286//Clipperz.logDebug("---> 5.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
287 result += aParameter.line.substr(0 ,1);
288 aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
289//Clipperz.logDebug("<--- 5.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
290 } else {
291//Clipperz.logDebug("---> 5.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
292 aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
293 if (newlineRegexp.test(aParameter.line) || aParameter.line == "") {
294//Clipperz.logDebug("######");
295 aParameter.isThereAnEmptyFinalField = true;
296 };
297 done = true;
298//Clipperz.logDebug("<--- 5.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
299 }
300 } else if (validRegexp.test(aParameter.line)) {
301//Clipperz.logDebug("---> 6: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
302 result += aParameter.line.substr(0, 1);
303 aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
304//Clipperz.logDebug("<--- 6: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
305 } else if (newlineRegexp.test(aParameter.line)) {
306 if (inQuotes == true) {
307 result += aParameter.line.substr(0 ,1);
308 aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
309 } else {
310 if (result == "") {
311 if (aParameter.isThereAnEmptyFinalField == true) {
312 aParameter.isThereAnEmptyFinalField = false;
313 } else {
314 result = null;
315 }
316 }
317
318 done = true;
319 }
320 } else {
321 throw new Error("CSV Parsing error; an undesirable character... '" + aParameter.line.substr(0,1) + "'");
322 }
323 }
324 } catch(exception) {
325 Clipperz.logError(exception.message);
326 // result = null;
327 throw exception;
328 }
329 }
330
331//if (result != null) {
332 //Clipperz.logDebug("<=== result: '" + result.replace(/\n/g, "\\n") + "'");
333//} else {
334 //Clipperz.logDebug("<=== result: NULL");
335//}
336
337 return result;
338 },
339
340 //-------------------------------------------------------------------------
341 __syntaxFix__: "syntax fix"
342});
343
344
diff --git a/frontend/delta/js/Clipperz/Crypto/AES.js b/frontend/delta/js/Clipperz/Crypto/AES.js
new file mode 100644
index 0000000..cb56f11
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/AES.js
@@ -0,0 +1,859 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.AES depends on Clipperz.ByteArray!";
26}
27
28 //Dependency commented to avoid a circular reference
29//try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
30 //throw "Clipperz.Crypto.AES depends on Clipperz.Crypto.PRNG!";
31//}
32
33if (typeof(Clipperz.Crypto.AES) == 'undefined') { Clipperz.Crypto.AES = {}; }
34
35//#############################################################################
36
37Clipperz.Crypto.AES.DeferredExecutionContext = function(args) {
38 args = args || {};
39
40 this._key = args.key;
41 this._message = args.message;
42 this._result = args.message.clone();
43 this._nonce = args.nonce;
44 this._messageLength = this._message.length();
45
46 this._messageArray = this._message.arrayValues();
47 this._resultArray = this._result.arrayValues();
48 this._nonceArray = this._nonce.arrayValues();
49
50 this._executionStep = 0;
51
52 // this._elaborationChunkSize = 1024; // 4096; // 16384; //4096;
53 this._elaborationChunks = 10;
54 this._pauseTime = 0.02; // 0.02 //0.2;
55
56 return this;
57}
58
59Clipperz.Crypto.AES.DeferredExecutionContext.prototype = MochiKit.Base.update(null, {
60
61 'key': function() {
62 return this._key;
63 },
64
65 'message': function() {
66 return this._message;
67 },
68
69 'messageLength': function() {
70 return this._messageLength;
71 },
72
73 'result': function() {
74 return new Clipperz.ByteArray(this.resultArray());
75 },
76
77 'nonce': function() {
78 return this._nonce;
79 },
80
81 'messageArray': function() {
82 return this._messageArray;
83 },
84
85 'resultArray': function() {
86 return this._resultArray;
87 },
88
89 'nonceArray': function() {
90 return this._nonceArray;
91 },
92
93 'elaborationChunkSize': function() {
94 // return Clipperz.Crypto.AES.DeferredExecution.chunkSize;
95 // return this._elaborationChunkSize;
96 return (this._elaborationChunks * 1024);
97 },
98
99 'executionStep': function() {
100 return this._executionStep;
101 },
102
103 'setExecutionStep': function(aValue) {
104 this._executionStep = aValue;
105 },
106
107 'tuneExecutionParameters': function (anElapsedTime) {
108//var originalChunks = this._elaborationChunks;
109 if (anElapsedTime > 0) {
110 this._elaborationChunks = Math.round(this._elaborationChunks * ((anElapsedTime + 1000)/(anElapsedTime * 2)));
111 }
112//Clipperz.log("tuneExecutionParameters - elapsedTime: " + anElapsedTime + /*originalChunks,*/ " chunks # " + this._elaborationChunks + " [" + this._executionStep + " / " + this._messageLength + "]");
113 },
114
115 'pause': function(aValue) {
116 // return MochiKit.Async.wait(Clipperz.Crypto.AES.DeferredExecution.pauseTime, aValue);
117 return MochiKit.Async.wait(this._pauseTime, aValue);
118 },
119
120 'isDone': function () {
121 return (this._executionStep >= this._messageLength);
122 },
123
124 //-----------------------------------------------------------------------------
125 __syntaxFix__: "syntax fix"
126
127});
128
129//#############################################################################
130
131Clipperz.Crypto.AES.Key = function(args) {
132 args = args || {};
133
134 this._key = args.key;
135 this._keySize = args.keySize || this.key().length();
136
137 if (this.keySize() == 128/8) {
138 this._b = 176;
139 this._numberOfRounds = 10;
140 } else if (this.keySize() == 256/8) {
141 this._b = 240;
142 this._numberOfRounds = 14;
143 } else {
144 Clipperz.logError("AES unsupported key size: " + (this.keySize() * 8) + " bits");
145 throw Clipperz.Crypto.AES.exception.UnsupportedKeySize;
146 }
147
148 this._stretchedKey = null;
149
150 return this;
151}
152
153Clipperz.Crypto.AES.Key.prototype = MochiKit.Base.update(null, {
154
155 'asString': function() {
156 return "Clipperz.Crypto.AES.Key (" + this.key().toHexString() + ")";
157 },
158
159 //-----------------------------------------------------------------------------
160
161 'key': function() {
162 return this._key;
163 },
164
165 'keySize': function() {
166 return this._keySize;
167 },
168
169 'b': function() {
170 return this._b;
171 },
172
173 'numberOfRounds': function() {
174 return this._numberOfRounds;
175 },
176 //=========================================================================
177
178 'keyScheduleCore': function(aWord, aRoundConstantsIndex) {
179 varresult;
180 var sbox;
181
182 sbox = Clipperz.Crypto.AES.sbox();
183
184 result = [sbox[aWord[1]] ^ Clipperz.Crypto.AES.roundConstants()[aRoundConstantsIndex],
185 sbox[aWord[2]],
186 sbox[aWord[3]],
187 sbox[aWord[0]]];
188
189 return result;
190 },
191
192 //-----------------------------------------------------------------------------
193
194 'xorWithPreviousStretchValues': function(aKey, aWord, aPreviousWordIndex) {
195 varresult;
196 var i,c;
197
198 result = [];
199 c = 4;
200 for (i=0; i<c; i++) {
201 result[i] = aWord[i] ^ aKey.byteAtIndex(aPreviousWordIndex + i);
202 }
203
204 return result;
205 },
206
207 //-----------------------------------------------------------------------------
208
209 'sboxShakeup': function(aWord) {
210 var result;
211 var sbox;
212 var i,c;
213
214 result = [];
215 sbox = Clipperz.Crypto.AES.sbox();
216 c =4;
217 for (i=0; i<c; i++) {
218 result[i] = sbox[aWord[i]];
219 }
220
221 return result;
222 },
223
224 //-----------------------------------------------------------------------------
225
226 'stretchKey': function(aKey) {
227 varcurrentWord;
228 varkeyLength;
229 varpreviousStretchIndex;
230 var i,c;
231
232 keyLength = aKey.length();
233 previousStretchIndex = keyLength - this.keySize();
234
235 currentWord = [aKey.byteAtIndex(keyLength - 4),
236 aKey.byteAtIndex(keyLength - 3),
237 aKey.byteAtIndex(keyLength - 2),
238 aKey.byteAtIndex(keyLength - 1)];
239 currentWord = this.keyScheduleCore(currentWord, keyLength / this.keySize());
240
241 if (this.keySize() == 256/8) {
242 c = 8;
243 } else if (this.keySize() == 128/8){
244 c = 4;
245 }
246
247 for (i=0; i<c; i++) {
248 if (i == 4) {
249 //fifth streatch word
250 currentWord = this.sboxShakeup(currentWord);
251 }
252
253 currentWord = this.xorWithPreviousStretchValues(aKey, currentWord, previousStretchIndex + (i*4));
254 aKey.appendBytes(currentWord);
255 }
256
257 return aKey;
258 },
259
260 //-----------------------------------------------------------------------------
261
262 'stretchedKey': function() {
263 if (this._stretchedKey == null) {
264 var stretchedKey;
265
266 stretchedKey = this.key().clone();
267
268 while (stretchedKey.length() < this.keySize()) {
269 stretchedKey.appendByte(0);
270 }
271
272 while (stretchedKey.length() < this.b()) {
273 stretchedKey = this.stretchKey(stretchedKey);
274 }
275
276 this._stretchedKey = stretchedKey.split(0, this.b());
277 }
278
279 return this._stretchedKey;
280 },
281
282 //=========================================================================
283 __syntaxFix__: "syntax fix"
284});
285
286//#############################################################################
287
288Clipperz.Crypto.AES.State = function(args) {
289 args = args || {};
290
291 this._data = args.block;
292 this._key = args.key;
293
294 return this;
295}
296
297Clipperz.Crypto.AES.State.prototype = MochiKit.Base.update(null, {
298
299 'key': function() {
300 return this._key;
301 },
302
303 //-----------------------------------------------------------------------------
304
305 'data': function() {
306 return this._data;
307 },
308
309 'setData': function(aValue) {
310 this._data = aValue;
311 },
312
313 //=========================================================================
314
315 'addRoundKey': function(aRoundNumber) {
316 //each byte of the state is combined with the round key; each round key is derived from the cipher key using a key schedule.
317 vardata;
318 varstretchedKey;
319 varfirstStretchedKeyIndex;
320 var i,c;
321
322 data = this.data();
323 stretchedKey = this.key().stretchedKey();
324 firstStretchedKeyIndex = aRoundNumber * (128/8);
325 c = 128/8;
326 for (i=0; i<c; i++) {
327 data[i] = data[i] ^ stretchedKey.byteAtIndex(firstStretchedKeyIndex + i);
328 }
329 },
330
331 //-----------------------------------------------------------------------------
332
333 'subBytes': function() {
334 // a non-linear substitution step where each byte is replaced with another according to a lookup table.
335 var i,c;
336 vardata;
337 var sbox;
338
339 data = this.data();
340 sbox = Clipperz.Crypto.AES.sbox();
341
342 c = 16;
343 for (i=0; i<c; i++) {
344 data[i] = sbox[data[i]];
345 }
346 },
347
348 //-----------------------------------------------------------------------------
349
350 'shiftRows': function() {
351 //a transposition step where each row of the state is shifted cyclically a certain number of steps.
352 varnewValue;
353 vardata;
354 varshiftMapping;
355 vari,c;
356
357 newValue = new Array(16);
358 data = this.data();
359 shiftMapping = Clipperz.Crypto.AES.shiftRowMapping();
360 // [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
361 c = 16;
362 for (i=0; i<c; i++) {
363 newValue[i] = data[shiftMapping[i]];
364 }
365 for (i=0; i<c; i++) {
366 data[i] = newValue[i];
367 }
368 },
369
370 //-----------------------------------------------------------------------------
371/*
372 'mixColumnsWithValues': function(someValues) {
373 varresult;
374 vara;
375 var i,c;
376
377 c = 4;
378 result = [];
379 a = [];
380 for (i=0; i<c; i++) {
381 a[i] = [];
382 a[i][1] = someValues[i]
383 if ((a[i][1] & 0x80) == 0x80) {
384 a[i][2] = (a[i][1] << 1) ^ 0x11b;
385 } else {
386 a[i][2] = a[i][1] << 1;
387 }
388
389 a[i][3] = a[i][2] ^ a[i][1];
390 }
391
392 for (i=0; i<c; i++) {
393 varx;
394
395 x = Clipperz.Crypto.AES.mixColumnsMatrix()[i];
396 result[i] = a[0][x[0]] ^ a[1][x[1]] ^ a[2][x[2]] ^ a[3][x[3]];
397 }
398
399 return result;
400 },
401
402 'mixColumns': function() {
403 //a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
404 var data;
405 var i, c;
406
407 data = this.data();
408 c = 4;
409 for(i=0; i<c; i++) {
410 varblockIndex;
411 var mixedValues;
412
413 blockIndex = i * 4;
414 mixedValues = this.mixColumnsWithValues([data[blockIndex + 0],
415 data[blockIndex + 1],
416 data[blockIndex + 2],
417 data[blockIndex + 3]]);
418 data[blockIndex + 0] = mixedValues[0];
419 data[blockIndex + 1] = mixedValues[1];
420 data[blockIndex + 2] = mixedValues[2];
421 data[blockIndex + 3] = mixedValues[3];
422 }
423 },
424*/
425
426 'mixColumns': function() {
427 //a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
428 var data;
429 var i, c;
430 var a_1;
431 var a_2;
432
433 a_1 = new Array(4);
434 a_2 = new Array(4);
435
436 data = this.data();
437 c = 4;
438 for(i=0; i<c; i++) {
439 varblockIndex;
440 var ii, cc;
441
442 blockIndex = i * 4;
443
444 cc = 4;
445 for (ii=0; ii<cc; ii++) {
446 var value;
447
448 value = data[blockIndex + ii];
449 a_1[ii] = value;
450 a_2[ii] = (value & 0x80) ? ((value << 1) ^ 0x011b) : (value << 1);
451 }
452
453 data[blockIndex + 0] = a_2[0] ^ a_1[1] ^ a_2[1] ^ a_1[2] ^ a_1[3];
454 data[blockIndex + 1] = a_1[0] ^ a_2[1] ^ a_1[2] ^ a_2[2] ^ a_1[3];
455 data[blockIndex + 2] = a_1[0] ^ a_1[1] ^ a_2[2] ^ a_1[3] ^ a_2[3];
456 data[blockIndex + 3] = a_1[0] ^ a_2[0] ^ a_1[1] ^ a_1[2] ^ a_2[3];
457 }
458 },
459
460 //=========================================================================
461
462 'spinRound': function(aRoundNumber) {
463 this.addRoundKey(aRoundNumber);
464 this.subBytes();
465 this.shiftRows();
466 this.mixColumns();
467 },
468
469 'spinLastRound': function() {
470 this.addRoundKey(this.key().numberOfRounds() - 1);
471 this.subBytes();
472 this.shiftRows();
473 this.addRoundKey(this.key().numberOfRounds());
474 },
475
476 //=========================================================================
477
478 'encrypt': function() {
479 vari,c;
480
481 c = this.key().numberOfRounds() - 1;
482 for (i=0; i<c; i++) {
483 this.spinRound(i);
484 }
485
486 this.spinLastRound();
487 },
488
489 //=========================================================================
490 __syntaxFix__: "syntax fix"
491});
492
493//#############################################################################
494
495Clipperz.Crypto.AES.VERSION = "0.1";
496Clipperz.Crypto.AES.NAME = "Clipperz.Crypto.AES";
497
498MochiKit.Base.update(Clipperz.Crypto.AES, {
499
500 //http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-AES.html
501 //http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
502 //http://en.wikipedia.org/wiki/Rijndael_key_schedule
503 //http://en.wikipedia.org/wiki/Rijndael_S-box
504
505 '__repr__': function () {
506 return "[" + this.NAME + " " + this.VERSION + "]";
507 },
508
509 'toString': function () {
510 return this.__repr__();
511 },
512
513 //=============================================================================
514
515 '_sbox': null,
516 'sbox': function() {
517 if (Clipperz.Crypto.AES._sbox == null) {
518 Clipperz.Crypto.AES._sbox = [
5190x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
5200xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
5210xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
5220x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
5230x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
5240x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
5250xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
5260x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
5270xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
5280x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
5290xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
5300xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
5310xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
5320x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
5330xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
5340x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
535 ];
536 }
537
538 return Clipperz.Crypto.AES._sbox;
539 },
540
541 //-----------------------------------------------------------------------------
542 //
543 // 0 4 8 12 0 4 812
544 // 1 5 9 13 => 5 9 131
545 // 2 6 10 14 10 14 26
546 // 3 7 11 15 15 3 711
547 //
548 '_shiftRowMapping': null,
549 'shiftRowMapping': function() {
550 if (Clipperz.Crypto.AES._shiftRowMapping == null) {
551 Clipperz.Crypto.AES._shiftRowMapping = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
552 }
553
554 return Clipperz.Crypto.AES._shiftRowMapping;
555 },
556
557 //-----------------------------------------------------------------------------
558
559 '_mixColumnsMatrix': null,
560 'mixColumnsMatrix': function() {
561 if (Clipperz.Crypto.AES._mixColumnsMatrix == null) {
562 Clipperz.Crypto.AES._mixColumnsMatrix = [[2, 3, 1 ,1],
563 [1, 2, 3, 1],
564 [1, 1, 2, 3],
565 [3, 1, 1, 2] ];
566 }
567
568 return Clipperz.Crypto.AES._mixColumnsMatrix;
569 },
570
571 '_roundConstants': null,
572 'roundConstants': function() {
573 if (Clipperz.Crypto.AES._roundConstants == null) {
574 Clipperz.Crypto.AES._roundConstants = [ , 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154];
575 // Clipperz.Crypto.AES._roundConstants = [ , 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a];
576 }
577
578 return Clipperz.Crypto.AES._roundConstants;
579 },
580
581 //=============================================================================
582
583 'incrementNonce': function(aNonce) {
584//Clipperz.Profile.start("Clipperz.Crypto.AES.incrementNonce");
585 var i;
586 var done;
587
588 done = false;
589 i = aNonce.length - 1;
590
591 while ((i>=0) && (done == false)) {
592 var currentByteValue;
593
594 currentByteValue = aNonce[i];
595
596 if (currentByteValue == 0xff) {
597 aNonce[i] = 0;
598 if (i>= 0) {
599 i --;
600 } else {
601 done = true;
602 }
603 } else {
604 aNonce[i] = currentByteValue + 1;
605 done = true;
606 }
607 }
608//Clipperz.Profile.stop("Clipperz.Crypto.AES.incrementNonce");
609 },
610
611 //-----------------------------------------------------------------------------
612
613 'encryptBlock': function(aKey, aBlock) {
614 varresult;
615 varstate;
616
617 state = new Clipperz.Crypto.AES.State({block:aBlock, key:aKey});
618//is(state.data(), 'before');
619 state.encrypt();
620 result = state.data();
621
622 return result;
623 },
624
625 //-----------------------------------------------------------------------------
626
627 'encryptBlocks': function(aKey, aMessage, aNonce) {
628 varresult;
629 var nonce;
630 var self;
631 varmessageIndex;
632 varmessageLength;
633 var blockSize;
634
635 self = Clipperz.Crypto.AES;
636 blockSize = 128/8;
637 messageLength = aMessage.length;
638 nonce = aNonce;
639
640 result = aMessage;
641 messageIndex = 0;
642 while (messageIndex < messageLength) {
643 var encryptedBlock;
644 var i,c;
645
646 self.incrementNonce(nonce);
647 encryptedBlock = self.encryptBlock(aKey, nonce);
648
649 if ((messageLength - messageIndex) > blockSize) {
650 c = blockSize;
651 } else {
652 c = messageLength - messageIndex;
653 }
654
655 for (i=0; i<c; i++) {
656 result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
657 }
658
659 messageIndex += blockSize;
660 }
661
662 return result;
663 },
664
665 //-----------------------------------------------------------------------------
666
667 'encrypt': function(aKey, someData, aNonce) {
668 var result;
669 var nonce;
670 varencryptedData;
671 var key;
672
673 key = new Clipperz.Crypto.AES.Key({key:aKey});
674 nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
675
676 encryptedData = Clipperz.Crypto.AES.encryptBlocks(key, someData.arrayValues(), nonce.arrayValues());
677
678 result = nonce.appendBytes(encryptedData);
679
680 return result;
681 },
682
683 //-----------------------------------------------------------------------------
684
685 'decrypt': function(aKey, someData) {
686 var result;
687 var nonce;
688 var encryptedData;
689 var decryptedData;
690 vardataIterator;
691 var key;
692
693 key = new Clipperz.Crypto.AES.Key({key:aKey});
694
695 encryptedData = someData.arrayValues();
696 nonce = encryptedData.slice(0, (128/8));
697 encryptedData = encryptedData.slice(128/8);
698 decryptedData = Clipperz.Crypto.AES.encryptBlocks(key, encryptedData, nonce);
699
700 result = new Clipperz.ByteArray(decryptedData);
701
702 return result;
703 },
704
705 //=============================================================================
706
707 'deferredEncryptExecutionChunk': function(anExecutionContext) {
708 varresult;
709 var nonce;
710 var self;
711 varmessageIndex;
712 varmessageLength;
713 var blockSize;
714 var executionLimit;
715 var startTime, endTime;
716
717 self = Clipperz.Crypto.AES;
718 startTime = new Date();
719 blockSize = 128/8;
720 messageLength = anExecutionContext.messageArray().length;
721 nonce = anExecutionContext.nonceArray();
722 result = anExecutionContext.resultArray();
723
724 messageIndex = anExecutionContext.executionStep();
725 executionLimit = messageIndex + anExecutionContext.elaborationChunkSize();
726 executionLimit = Math.min(executionLimit, messageLength);
727
728 while (messageIndex < executionLimit) {
729 var encryptedBlock;
730 var i,c;
731
732 self.incrementNonce(nonce);
733 encryptedBlock = self.encryptBlock(anExecutionContext.key(), nonce);
734
735 if ((executionLimit - messageIndex) > blockSize) {
736 c = blockSize;
737 } else {
738 c = executionLimit - messageIndex;
739 }
740
741 for (i=0; i<c; i++) {
742 result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
743 }
744
745 messageIndex += blockSize;
746 }
747 anExecutionContext.setExecutionStep(messageIndex);
748 endTime = new Date();
749 anExecutionContext.tuneExecutionParameters(endTime - startTime);
750
751 return anExecutionContext;
752 },
753
754 //-----------------------------------------------------------------------------
755/*
756 'deferredEncryptBlocks': function(anExecutionContext) {
757 vardeferredResult;
758 varmessageSize;
759 var i,c;
760
761 messageSize = anExecutionContext.messageLength();
762
763 deferredResult = new Clipperz.Async.Deferred("AES.deferredEncryptBloks");
764
765 c = Math.ceil(messageSize / anExecutionContext.elaborationChunkSize());
766 for (i=0; i<c; i++) {
767 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptExecutionChunk);
768 deferredResult.addMethod(anExecutionContext, 'pause');
769 }
770
771 deferredResult.callback(anExecutionContext);
772
773 return deferredResult;
774 },
775*/
776
777 'deferredEncryptBlocks': function(anExecutionContext) {
778 vardeferredResult;
779
780 if (! anExecutionContext.isDone()) {
781 deferredResult = Clipperz.Async.callbacks("Clipperz.Crypto.AES.deferredEncryptBloks", [
782 Clipperz.Crypto.AES.deferredEncryptExecutionChunk,
783 MochiKit.Base.method(anExecutionContext, 'pause'),
784 Clipperz.Crypto.AES.deferredEncryptBlocks
785 ], {trace:false}, anExecutionContext);
786 } else {
787 deferredResult = MochiKit.Async.succeed(anExecutionContext);
788 }
789
790 return deferredResult;
791 },
792
793 //-----------------------------------------------------------------------------
794
795 'deferredEncrypt': function(aKey, someData, aNonce) {
796 var deferredResult;
797 varexecutionContext;
798 var result;
799 var nonce;
800 var key;
801
802 key = new Clipperz.Crypto.AES.Key({key:aKey});
803 nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
804
805 executionContext = new Clipperz.Crypto.AES.DeferredExecutionContext({key:key, message:someData, nonce:nonce});
806
807 deferredResult = new Clipperz.Async.Deferred("AES.deferredEncrypt");
808 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
809 deferredResult.addCallback(function(anExecutionContext) {
810 var result;
811
812 result = anExecutionContext.nonce().clone();
813 result.appendBytes(anExecutionContext.resultArray());
814
815 return result;
816 });
817 deferredResult.callback(executionContext)
818
819 return deferredResult;
820 },
821
822 //-----------------------------------------------------------------------------
823
824 'deferredDecrypt': function(aKey, someData) {
825 var deferredResult
826 var nonce;
827 var message;
828 var key;
829
830 key = new Clipperz.Crypto.AES.Key({key:aKey});
831 nonce = someData.split(0, (128/8));
832 message = someData.split(128/8);
833 executionContext = new Clipperz.Crypto.AES.DeferredExecutionContext({key:key, message:message, nonce:nonce});
834
835 deferredResult = new Clipperz.Async.Deferred("AES.deferredDecrypt");
836 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
837 deferredResult.addCallback(function(anExecutionContext) {
838 return anExecutionContext.result();
839 });
840 deferredResult.callback(executionContext);
841
842 return deferredResult;
843 },
844
845 //-----------------------------------------------------------------------------
846 __syntaxFix__: "syntax fix"
847
848});
849
850//#############################################################################
851
852//Clipperz.Crypto.AES.DeferredExecution = {
853 // 'chunkSize': 16384, // 4096, // 1024 4096 8192 1638432768;
854 // 'pauseTime': 0.02 //0.2
855//}
856
857Clipperz.Crypto.AES.exception = {
858 'UnsupportedKeySize': new MochiKit.Base.NamedError("Clipperz.Crypto.AES.exception.UnsupportedKeySize")
859};
diff --git a/frontend/delta/js/Clipperz/Crypto/AES_2.js b/frontend/delta/js/Clipperz/Crypto/AES_2.js
new file mode 100644
index 0000000..1627f39
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/AES_2.js
@@ -0,0 +1,843 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.AES_2 depends on Clipperz.ByteArray!";
26}
27
28 //Dependency commented to avoid a circular reference
29//try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
30 //throw "Clipperz.Crypto.AES_2 depends on Clipperz.Crypto.PRNG!";
31//}
32
33if (typeof(Clipperz.Crypto.AES_2) == 'undefined') { Clipperz.Crypto.AES_2 = {}; }
34
35//#############################################################################
36
37Clipperz.Crypto.AES_2.DeferredExecutionContext = function(args) {
38 args = args || {};
39
40 this._key = args.key;
41 this._message = args.message;
42 this._result = args.message.clone();
43 this._nonce = args.nonce;
44 this._messageLength = this._message.length();
45
46 this._messageArray = this._message.arrayValues();
47 this._resultArray = this._result.arrayValues();
48 this._nonceArray = this._nonce.arrayValues();
49
50 this._executionStep = 0;
51
52 // this._elaborationChunkSize = 1024; // 4096; // 16384; //4096;
53 this._elaborationChunks = 10;
54 this._pauseTime = 0.02; // 0.02 //0.2;
55
56 return this;
57}
58
59Clipperz.Crypto.AES_2.DeferredExecutionContext.prototype = MochiKit.Base.update(null, {
60
61 'key': function() {
62 return this._key;
63 },
64
65 'message': function() {
66 return this._message;
67 },
68
69 'messageLength': function() {
70 return this._messageLength;
71 },
72
73 'result': function() {
74 return new Clipperz.ByteArray(this.resultArray());
75 },
76
77 'nonce': function() {
78 return this._nonce;
79 },
80
81 'messageArray': function() {
82 return this._messageArray;
83 },
84
85 'resultArray': function() {
86 return this._resultArray;
87 },
88
89 'nonceArray': function() {
90 return this._nonceArray;
91 },
92
93 'elaborationChunkSize': function() {
94 // return Clipperz.Crypto.AES_2.DeferredExecution.chunkSize;
95 // return this._elaborationChunkSize;
96 return (this._elaborationChunks * 1024);
97 },
98
99 'executionStep': function() {
100 return this._executionStep;
101 },
102
103 'setExecutionStep': function(aValue) {
104 this._executionStep = aValue;
105 },
106
107 'tuneExecutionParameters': function (anElapsedTime) {
108//var originalChunks = this._elaborationChunks;
109 if (anElapsedTime > 0) {
110 this._elaborationChunks = Math.round(this._elaborationChunks * ((anElapsedTime + 1000)/(anElapsedTime * 2)));
111 }
112//Clipperz.log("tuneExecutionParameters - elapsedTime: " + anElapsedTime + /*originalChunks,*/ " chunks # " + this._elaborationChunks + " [" + this._executionStep + " / " + this._messageLength + "]");
113 },
114
115 'pause': function(aValue) {
116 // return MochiKit.Async.wait(Clipperz.Crypto.AES_2.DeferredExecution.pauseTime, aValue);
117 return MochiKit.Async.wait(this._pauseTime, aValue);
118 },
119
120 'isDone': function () {
121 return (this._executionStep >= this._messageLength);
122 },
123
124 //-----------------------------------------------------------------------------
125 __syntaxFix__: "syntax fix"
126
127});
128
129//#############################################################################
130
131Clipperz.Crypto.AES_2.Key = function(args) {
132 args = args || {};
133
134 this._key = args.key;
135 this._keySize = args.keySize || this.key().length();
136
137 if (this.keySize() == 128/8) {
138 this._b = 176;
139 this._numberOfRounds = 10;
140 } else if (this.keySize() == 256/8) {
141 this._b = 240;
142 this._numberOfRounds = 14;
143 } else {
144 Clipperz.logError("AES unsupported key size: " + (this.keySize() * 8) + " bits");
145 throw Clipperz.Crypto.AES_2.exception.UnsupportedKeySize;
146 }
147
148 this._stretchedKey = null;
149
150 return this;
151}
152
153Clipperz.Crypto.AES_2.Key.prototype = MochiKit.Base.update(null, {
154
155 'asString': function() {
156 return "Clipperz.Crypto.AES_2.Key (" + this.key().toHexString() + ")";
157 },
158
159 //-----------------------------------------------------------------------------
160
161 'key': function() {
162 return this._key;
163 },
164
165 'keySize': function() {
166 return this._keySize;
167 },
168
169 'b': function() {
170 return this._b;
171 },
172
173 'numberOfRounds': function() {
174 return this._numberOfRounds;
175 },
176 //=========================================================================
177
178 'keyScheduleCore': function(aWord, aRoundConstantsIndex) {
179 varresult;
180 var sbox;
181
182 sbox = Clipperz.Crypto.AES_2.sbox();
183
184 result = [sbox[aWord[1]] ^ Clipperz.Crypto.AES_2.roundConstants()[aRoundConstantsIndex],
185 sbox[aWord[2]],
186 sbox[aWord[3]],
187 sbox[aWord[0]]];
188
189 return result;
190 },
191
192 //-----------------------------------------------------------------------------
193
194 'xorWithPreviousStretchValues': function(aKey, aWord, aPreviousWordIndex) {
195 varresult;
196 var i,c;
197
198 result = [];
199 c = 4;
200 for (i=0; i<c; i++) {
201 result[i] = aWord[i] ^ aKey.byteAtIndex(aPreviousWordIndex + i);
202 }
203
204 return result;
205 },
206
207 //-----------------------------------------------------------------------------
208
209 'sboxShakeup': function(aWord) {
210 var result;
211 var sbox;
212 var i,c;
213
214 result = [];
215 sbox = Clipperz.Crypto.AES_2.sbox();
216 c =4;
217 for (i=0; i<c; i++) {
218 result[i] = sbox[aWord[i]];
219 }
220
221 return result;
222 },
223
224 //-----------------------------------------------------------------------------
225
226 'stretchKey': function(aKey) {
227 varcurrentWord;
228 varkeyLength;
229 varpreviousStretchIndex;
230 var i,c;
231
232 keyLength = aKey.length();
233 previousStretchIndex = keyLength - this.keySize();
234
235 currentWord = [aKey.byteAtIndex(keyLength - 4),
236 aKey.byteAtIndex(keyLength - 3),
237 aKey.byteAtIndex(keyLength - 2),
238 aKey.byteAtIndex(keyLength - 1)];
239 currentWord = this.keyScheduleCore(currentWord, keyLength / this.keySize());
240
241 if (this.keySize() == 256/8) {
242 c = 8;
243 } else if (this.keySize() == 128/8){
244 c = 4;
245 }
246
247 for (i=0; i<c; i++) {
248 if (i == 4) {
249 //fifth streatch word
250 currentWord = this.sboxShakeup(currentWord);
251 }
252
253 currentWord = this.xorWithPreviousStretchValues(aKey, currentWord, previousStretchIndex + (i*4));
254 aKey.appendBytes(currentWord);
255 }
256
257 return aKey;
258 },
259
260 //-----------------------------------------------------------------------------
261
262 'stretchedKey': function() {
263 if (this._stretchedKey == null) {
264 var stretchedKey;
265
266 stretchedKey = this.key().clone();
267
268 while (stretchedKey.length() < this.keySize()) {
269 stretchedKey.appendByte(0);
270 }
271
272 while (stretchedKey.length() < this.b()) {
273 stretchedKey = this.stretchKey(stretchedKey);
274 }
275
276 this._stretchedKey = stretchedKey.split(0, this.b());
277 }
278
279 return this._stretchedKey;
280 },
281
282 //=========================================================================
283 __syntaxFix__: "syntax fix"
284});
285
286//#############################################################################
287
288Clipperz.Crypto.AES_2.State = function(args) {
289 args = args || {};
290
291 this._data = args.block.slice(0);
292 this._key = args.key;
293
294 return this;
295}
296
297Clipperz.Crypto.AES_2.State.prototype = MochiKit.Base.update(null, {
298
299 'key': function() {
300 return this._key;
301 },
302
303 //-----------------------------------------------------------------------------
304
305 'data': function() {
306 return this._data;
307 },
308
309 'setData': function(aValue) {
310 this._data = aValue;
311 },
312
313 //=========================================================================
314
315 'addRoundKey': function(aRoundNumber) {
316 //each byte of the state is combined with the round key; each round key is derived from the cipher key using a key schedule.
317 vardata;
318 varstretchedKey;
319 varfirstStretchedKeyIndex;
320 var i,c;
321
322 data = this.data();
323 stretchedKey = this.key().stretchedKey();
324 firstStretchedKeyIndex = aRoundNumber * (128/8);
325 c = 128/8;
326 for (i=0; i<c; i++) {
327 data[i] = data[i] ^ stretchedKey.byteAtIndex(firstStretchedKeyIndex + i);
328 }
329 },
330
331 //-----------------------------------------------------------------------------
332
333 'subBytes': function() {
334 // a non-linear substitution step where each byte is replaced with another according to a lookup table.
335 var i,c;
336 vardata;
337 var sbox;
338
339 data = this.data();
340 sbox = Clipperz.Crypto.AES_2.sbox();
341
342 c = 16;
343 for (i=0; i<c; i++) {
344 data[i] = sbox[data[i]];
345 }
346 },
347
348 //-----------------------------------------------------------------------------
349
350 'shiftRows': function() {
351 //a transposition step where each row of the state is shifted cyclically a certain number of steps.
352 varnewValue;
353 vardata;
354 varshiftMapping;
355 vari,c;
356
357 newValue = new Array(16);
358 data = this.data();
359 shiftMapping = Clipperz.Crypto.AES_2.shiftRowMapping();
360 // [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
361 c = 16;
362 for (i=0; i<c; i++) {
363 newValue[i] = data[shiftMapping[i]];
364 }
365 for (i=0; i<c; i++) {
366 data[i] = newValue[i];
367 }
368 },
369
370 //-----------------------------------------------------------------------------
371/*
372 'mixColumnsWithValues': function(someValues) {
373 varresult;
374 vara;
375 var i,c;
376
377 c = 4;
378 result = [];
379 a = [];
380 for (i=0; i<c; i++) {
381 a[i] = [];
382 a[i][1] = someValues[i]
383 if ((a[i][1] & 0x80) == 0x80) {
384 a[i][2] = (a[i][1] << 1) ^ 0x11b;
385 } else {
386 a[i][2] = a[i][1] << 1;
387 }
388
389 a[i][3] = a[i][2] ^ a[i][1];
390 }
391
392 for (i=0; i<c; i++) {
393 varx;
394
395 x = Clipperz.Crypto.AES_2.mixColumnsMatrix()[i];
396 result[i] = a[0][x[0]] ^ a[1][x[1]] ^ a[2][x[2]] ^ a[3][x[3]];
397 }
398
399 return result;
400 },
401
402 'mixColumns': function() {
403 //a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
404 var data;
405 var i, c;
406
407 data = this.data();
408 c = 4;
409 for(i=0; i<c; i++) {
410 varblockIndex;
411 var mixedValues;
412
413 blockIndex = i * 4;
414 mixedValues = this.mixColumnsWithValues([data[blockIndex + 0],
415 data[blockIndex + 1],
416 data[blockIndex + 2],
417 data[blockIndex + 3]]);
418 data[blockIndex + 0] = mixedValues[0];
419 data[blockIndex + 1] = mixedValues[1];
420 data[blockIndex + 2] = mixedValues[2];
421 data[blockIndex + 3] = mixedValues[3];
422 }
423 },
424*/
425
426 'mixColumns': function() {
427 //a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
428 var data;
429 var i, c;
430 var a_1;
431 var a_2;
432
433 a_1 = new Array(4);
434 a_2 = new Array(4);
435
436 data = this.data();
437 c = 4;
438 for(i=0; i<c; i++) {
439 varblockIndex;
440 var ii, cc;
441
442 blockIndex = i * 4;
443
444 cc = 4;
445 for (ii=0; ii<cc; ii++) {
446 var value;
447
448 value = data[blockIndex + ii];
449 a_1[ii] = value;
450 a_2[ii] = (value & 0x80) ? ((value << 1) ^ 0x011b) : (value << 1);
451 }
452
453 data[blockIndex + 0] = a_2[0] ^ a_1[1] ^ a_2[1] ^ a_1[2] ^ a_1[3];
454 data[blockIndex + 1] = a_1[0] ^ a_2[1] ^ a_1[2] ^ a_2[2] ^ a_1[3];
455 data[blockIndex + 2] = a_1[0] ^ a_1[1] ^ a_2[2] ^ a_1[3] ^ a_2[3];
456 data[blockIndex + 3] = a_1[0] ^ a_2[0] ^ a_1[1] ^ a_1[2] ^ a_2[3];
457 }
458 },
459
460 //=========================================================================
461
462 'spinRound': function(aRoundNumber) {
463 this.addRoundKey(aRoundNumber);
464 this.subBytes();
465 this.shiftRows();
466 this.mixColumns();
467 },
468
469 'spinLastRound': function() {
470 this.addRoundKey(this.key().numberOfRounds() - 1);
471 this.subBytes();
472 this.shiftRows();
473 this.addRoundKey(this.key().numberOfRounds());
474 },
475
476 //=========================================================================
477
478 'encrypt': function() {
479 vari,c;
480
481 c = this.key().numberOfRounds() - 1;
482 for (i=0; i<c; i++) {
483 this.spinRound(i);
484 }
485
486 this.spinLastRound();
487 },
488
489 //=========================================================================
490 __syntaxFix__: "syntax fix"
491});
492
493//#############################################################################
494
495Clipperz.Crypto.AES_2.VERSION = "0.1";
496Clipperz.Crypto.AES_2.NAME = "Clipperz.Crypto.AES_2";
497
498MochiKit.Base.update(Clipperz.Crypto.AES_2, {
499
500 //http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-AES.html
501 //http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
502 //http://en.wikipedia.org/wiki/Rijndael_key_schedule
503 //http://en.wikipedia.org/wiki/Rijndael_S-box
504
505 '__repr__': function () {
506 return "[" + this.NAME + " " + this.VERSION + "]";
507 },
508
509 'toString': function () {
510 return this.__repr__();
511 },
512
513 //=============================================================================
514
515 '_sbox': null,
516 'sbox': function() {
517 if (Clipperz.Crypto.AES_2._sbox == null) {
518 Clipperz.Crypto.AES_2._sbox = [
5190x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
5200xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
5210xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
5220x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
5230x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
5240x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
5250xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
5260x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
5270xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
5280x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
5290xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
5300xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
5310xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
5320x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
5330xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
5340x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
535 ];
536 }
537
538 return Clipperz.Crypto.AES_2._sbox;
539 },
540
541 //-----------------------------------------------------------------------------
542 //
543 // 0 4 8 12 0 4 812
544 // 1 5 9 13 => 5 9 131
545 // 2 6 10 14 10 14 26
546 // 3 7 11 15 15 3 711
547 //
548 '_shiftRowMapping': null,
549 'shiftRowMapping': function() {
550 if (Clipperz.Crypto.AES_2._shiftRowMapping == null) {
551 Clipperz.Crypto.AES_2._shiftRowMapping = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
552 }
553
554 return Clipperz.Crypto.AES_2._shiftRowMapping;
555 },
556
557 //-----------------------------------------------------------------------------
558
559 '_mixColumnsMatrix': null,
560 'mixColumnsMatrix': function() {
561 if (Clipperz.Crypto.AES_2._mixColumnsMatrix == null) {
562 Clipperz.Crypto.AES_2._mixColumnsMatrix = [[2, 3, 1 ,1],
563 [1, 2, 3, 1],
564 [1, 1, 2, 3],
565 [3, 1, 1, 2] ];
566 }
567
568 return Clipperz.Crypto.AES_2._mixColumnsMatrix;
569 },
570
571 '_roundConstants': null,
572 'roundConstants': function() {
573 if (Clipperz.Crypto.AES_2._roundConstants == null) {
574 Clipperz.Crypto.AES_2._roundConstants = [ , 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154];
575 // Clipperz.Crypto.AES_2._roundConstants = [ , 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a];
576 }
577
578 return Clipperz.Crypto.AES_2._roundConstants;
579 },
580
581 //=============================================================================
582
583 'incrementNonce': function(nonce) {
584 var i;
585 var done;
586
587 done = false;
588 i = nonce.length - 1;
589
590 while ((i>=0) && (done == false)) {
591 var currentByteValue;
592
593 currentByteValue = nonce[i];
594
595 if (currentByteValue == 0xff) {
596 nonce[i] = 0;
597 if (i>= 0) {
598 i --;
599 } else {
600 done = true;
601 }
602 } else {
603 nonce[i] = currentByteValue + 1;
604 done = true;
605 }
606 }
607 },
608
609 //-----------------------------------------------------------------------------
610
611 'encryptBlock': function(aKey, aBlock) {
612 varresult;
613 varstate;
614
615 state = new Clipperz.Crypto.AES_2.State({block:aBlock, key:aKey});
616//is(state.data(), 'before');
617 state.encrypt();
618 result = state.data();
619
620 return result;
621 },
622
623 //-----------------------------------------------------------------------------
624
625 'encryptBlocks': function(aKey, aMessage, aNonce) {
626 varresult;
627 var nonce;
628 var self;
629 varmessageIndex;
630 varmessageLength;
631 var blockSize;
632
633 self = Clipperz.Crypto.AES_2;
634 blockSize = 128/8;
635 messageLength = aMessage.length;
636 nonce = aNonce;
637
638 result = aMessage;
639 messageIndex = 0;
640 while (messageIndex < messageLength) {
641 var encryptedBlock;
642 var i,c;
643
644 encryptedBlock = self.encryptBlock(aKey, nonce);
645
646 if ((messageLength - messageIndex) > blockSize) {
647 c = blockSize;
648 } else {
649 c = messageLength - messageIndex;
650 }
651
652 for (i=0; i<c; i++) {
653 result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
654 }
655
656 messageIndex += blockSize;
657 // nonce = self.incrementNonce(nonce);
658 self.incrementNonce(nonce)
659 }
660
661 return result;
662 },
663
664 //-----------------------------------------------------------------------------
665
666 'encrypt': function(aKey, someData, aNonce) {
667 var result;
668 var nonce;
669 varencryptedData;
670 var key;
671
672 key = new Clipperz.Crypto.AES_2.Key({key:aKey});
673 nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
674
675 encryptedData = Clipperz.Crypto.AES_2.encryptBlocks(key, someData.arrayValues(), nonce.arrayValues());
676
677 result = nonce.appendBytes(encryptedData);
678
679 return result;
680 },
681
682 //-----------------------------------------------------------------------------
683
684 'decrypt': function(aKey, someData) {
685 var result;
686 var nonce;
687 var encryptedData;
688 var decryptedData;
689 vardataIterator;
690 var key;
691
692 key = new Clipperz.Crypto.AES_2.Key({key:aKey});
693
694 encryptedData = someData.arrayValues();
695 nonce = encryptedData.slice(0, (128/8));
696 encryptedData = encryptedData.slice(128/8);
697 decryptedData = Clipperz.Crypto.AES_2.encryptBlocks(key, encryptedData, nonce);
698
699 result = new Clipperz.ByteArray(decryptedData);
700
701 return result;
702 },
703
704 //=============================================================================
705
706 'deferredEncryptExecutionChunk': function(anExecutionContext) {
707 varresult;
708 var nonce;
709 var self;
710 varmessageIndex;
711 varmessageLength;
712 var blockSize;
713 var executionLimit;
714 var startTime, endTime;
715
716 self = Clipperz.Crypto.AES_2;
717 startTime = new Date();
718 blockSize = 128/8;
719 messageLength = anExecutionContext.messageArray().length;
720 nonce = anExecutionContext.nonceArray();
721 result = anExecutionContext.resultArray();
722
723 messageIndex = anExecutionContext.executionStep();
724 executionLimit = messageIndex + anExecutionContext.elaborationChunkSize();
725 executionLimit = Math.min(executionLimit, messageLength);
726
727 while (messageIndex < executionLimit) {
728 var encryptedBlock;
729 var i,c;
730
731//console.log("+++ nonce: [" + nonce + "]")
732 encryptedBlock = self.encryptBlock(anExecutionContext.key(), nonce);
733
734 if ((executionLimit - messageIndex) > blockSize) {
735 c = blockSize;
736 } else {
737 c = executionLimit - messageIndex;
738 }
739
740 for (i=0; i<c; i++) {
741 result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
742 }
743
744 messageIndex += blockSize;
745 // nonce = self.incrementNonce(nonce);
746 self.incrementNonce(nonce);
747 }
748 anExecutionContext.setExecutionStep(messageIndex);
749 endTime = new Date();
750 anExecutionContext.tuneExecutionParameters(endTime - startTime);
751
752 return anExecutionContext;
753 },
754
755 //-----------------------------------------------------------------------------
756
757 'deferredEncryptBlocks': function(anExecutionContext) {
758 vardeferredResult;
759
760//console.log("executionContext", anExecutionContext)
761//console.log(" --- nonce: " + anExecutionContext.nonceArray())
762 if (! anExecutionContext.isDone()) {
763 deferredResult = Clipperz.Async.callbacks("Clipperz.Crypto.AES_2.deferredEncryptBloks", [
764 Clipperz.Crypto.AES_2.deferredEncryptExecutionChunk,
765 MochiKit.Base.method(anExecutionContext, 'pause'),
766 Clipperz.Crypto.AES_2.deferredEncryptBlocks
767 ], {trace:false}, anExecutionContext);
768 } else {
769 deferredResult = MochiKit.Async.succeed(anExecutionContext);
770 }
771
772 return deferredResult;
773 },
774
775 //-----------------------------------------------------------------------------
776
777 'deferredEncrypt': function(aKey, someData, aNonce) {
778 var deferredResult;
779 varexecutionContext;
780 var result;
781 var nonce;
782 var key;
783
784 key = new Clipperz.Crypto.AES_2.Key({key:aKey});
785 nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
786
787 executionContext = new Clipperz.Crypto.AES_2.DeferredExecutionContext({key:key, message:someData, nonce:nonce});
788
789 deferredResult = new Clipperz.Async.Deferred("AES.deferredEncrypt");
790 deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredEncryptBlocks);
791 deferredResult.addCallback(function(anExecutionContext) {
792 var result;
793
794 result = anExecutionContext.nonce().clone();
795 result.appendBytes(anExecutionContext.resultArray());
796
797 return result;
798 });
799 deferredResult.callback(executionContext)
800
801 return deferredResult;
802 },
803
804 //-----------------------------------------------------------------------------
805
806 'deferredDecrypt': function(aKey, someData) {
807 var deferredResult
808 var nonce;
809 var message;
810 var key;
811
812 key = new Clipperz.Crypto.AES_2.Key({key:aKey});
813 nonce = someData.split(0, (128/8));
814//console.log("nonce: [" + nonce.arrayValues() + "]")
815 message = someData.split(128/8);
816//console.log("message: [" + message.arrayValues() + "]")
817 executionContext = new Clipperz.Crypto.AES_2.DeferredExecutionContext({key:key, message:message, nonce:nonce});
818
819 deferredResult = new Clipperz.Async.Deferred("AES.deferredDecrypt");
820 deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredEncryptBlocks);
821 deferredResult.addCallback(function(anExecutionContext) {
822 return anExecutionContext.result();
823 });
824 deferredResult.callback(executionContext);
825
826 return deferredResult;
827 },
828
829 //-----------------------------------------------------------------------------
830 __syntaxFix__: "syntax fix"
831
832});
833
834//#############################################################################
835
836//Clipperz.Crypto.AES_2.DeferredExecution = {
837 // 'chunkSize': 16384, // 4096, // 1024 4096 8192 1638432768;
838 // 'pauseTime': 0.02 //0.2
839//}
840
841Clipperz.Crypto.AES_2.exception = {
842 'UnsupportedKeySize': new MochiKit.Base.NamedError("Clipperz.Crypto.AES_2.exception.UnsupportedKeySize")
843};
diff --git a/frontend/delta/js/Clipperz/Crypto/Base.js b/frontend/delta/js/Clipperz/Crypto/Base.js
new file mode 100644
index 0000000..9acfc49
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/Base.js
@@ -0,0 +1,1847 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.Base) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.Base depends on Clipperz.Base!";
26}
27
28if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
29if (typeof(Clipperz.Crypto.Base) == 'undefined') { Clipperz.Crypto.Base = {}; }
30
31Clipperz.Crypto.Base.VERSION = "0.1";
32Clipperz.Crypto.Base.NAME = "Clipperz.Crypto.Base";
33
34//#############################################################################
35 //Downloaded on March 30, 2006 from http://anmar.eu.org/projects/jssha2/files/jssha2-0.3.zip (jsSha2/sha256.js)
36//#############################################################################
37
38/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256
39 * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
40 * Distributed under the BSD License
41 * Some bits taken from Paul Johnston's SHA-1 implementation
42 */
43var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
44function safe_add (x, y) {
45 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
46 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
47 return (msw << 16) | (lsw & 0xFFFF);
48}
49function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
50function R (X, n) {return ( X >>> n );}
51function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
52function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
53function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
54function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
55function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
56function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
57function core_sha256 (m, l) {
58 var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
59 var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
60 var W = new Array(64);
61 var a, b, c, d, e, f, g, h, i, j;
62 var T1, T2;
63 /* append padding */
64 m[l >> 5] |= 0x80 << (24 - l % 32);
65 m[((l + 64 >> 9) << 4) + 15] = l;
66 for ( var i = 0; i<m.length; i+=16 ) {
67 a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
68 for ( var j = 0; j<64; j++) {
69 if (j < 16) W[j] = m[j + i];
70 else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
71 T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
72 T2 = safe_add(Sigma0256(a), Maj(a, b, c));
73 h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
74 }
75 HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
76 }
77 return HASH;
78}
79function str2binb (str) {
80 var bin = Array();
81 var mask = (1 << chrsz) - 1;
82 for(var i = 0; i < str.length * chrsz; i += chrsz)
83 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
84 return bin;
85}
86function binb2hex (binarray) {
87 var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
88 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
89 var str = "";
90 for (var i = 0; i < binarray.length * 4; i++) {
91 str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
92 }
93 return str;
94}
95function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
96
97
98
99//#############################################################################
100 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (entropy.js)
101//#############################################################################
102
103 // Entropy collection utilities
104
105 /*Start by declaring static storage and initialise
106 the entropy vector from the time we come through
107 here. */
108
109 var entropyData = new Array(); // Collected entropy data
110 var edlen = 0; // Keyboard array data length
111
112 addEntropyTime(); // Start entropy collection with page load time
113 ce(); // Roll milliseconds into initial entropy
114
115 //Add a byte to the entropy vector
116
117 function addEntropyByte(b) {
118 entropyData[edlen++] = b;
119 }
120
121 /*Capture entropy. When the user presses a key or performs
122 various other events for which we can request
123 notification, add the time in 255ths of a second to the
124 entropyData array. The name of the function is short
125 so it doesn't bloat the form object declarations in
126 which it appears in various "onXXX" events. */
127
128 function ce() {
129 addEntropyByte(Math.floor((((new Date).getMilliseconds()) * 255) / 999));
130 }
131
132 //Add a 32 bit quantity to the entropy vector
133
134 function addEntropy32(w) {
135 var i;
136
137 for (i = 0; i < 4; i++) {
138 addEntropyByte(w & 0xFF);
139 w >>= 8;
140 }
141 }
142
143 /*Add the current time and date (milliseconds since the epoch,
144 truncated to 32 bits) to the entropy vector. */
145
146 function addEntropyTime() {
147 addEntropy32((new Date()).getTime());
148 }
149
150 /* Start collection of entropy from mouse movements. The
151 argument specifies the number of entropy items to be
152 obtained from mouse motion, after which mouse motion
153 will be ignored. Note that you can re-enable mouse
154 motion collection at any time if not already underway. */
155
156 var mouseMotionCollect = 0;
157 var oldMoveHandler; // For saving and restoring mouse move handler in IE4
158
159 function mouseMotionEntropy(maxsamp) {
160 if (mouseMotionCollect <= 0) {
161 mouseMotionCollect = maxsamp;
162 if ((document.implementation.hasFeature("Events", "2.0")) &&
163 document.addEventListener) {
164 // Browser supports Document Object Model (DOM) 2 events
165 document.addEventListener("mousemove", mouseMoveEntropy, false);
166 } else {
167 if (document.attachEvent) {
168 // Internet Explorer 5 and above event model
169 document.attachEvent("onmousemove", mouseMoveEntropy);
170 } else {
171 //Internet Explorer 4 event model
172 oldMoveHandler = document.onmousemove;
173 document.onmousemove = mouseMoveEntropy;
174 }
175 }
176//dump("Mouse enable", mouseMotionCollect);
177 }
178 }
179
180 /*Collect entropy from mouse motion events. Note that
181 this is craftily coded to work with either DOM2 or Internet
182 Explorer style events. Note that we don't use every successive
183 mouse movement event. Instead, we XOR the three bytes collected
184 from the mouse and use that to determine how many subsequent
185 mouse movements we ignore before capturing the next one. */
186
187 var mouseEntropyTime = 0; // Delay counter for mouse entropy collection
188
189 function mouseMoveEntropy(e) {
190 if (!e) {
191 e = window.event; // Internet Explorer event model
192 }
193 if (mouseMotionCollect > 0) {
194 if (mouseEntropyTime-- <= 0) {
195 addEntropyByte(e.screenX & 0xFF);
196 addEntropyByte(e.screenY & 0xFF);
197 ce();
198 mouseMotionCollect--;
199 mouseEntropyTime = (entropyData[edlen - 3] ^ entropyData[edlen - 2] ^
200 entropyData[edlen - 1]) % 19;
201//dump("Mouse Move", byteArrayToHex(entropyData.slice(-3)));
202 }
203 if (mouseMotionCollect <= 0) {
204 if (document.removeEventListener) {
205 document.removeEventListener("mousemove", mouseMoveEntropy, false);
206 } else if (document.detachEvent) {
207 document.detachEvent("onmousemove", mouseMoveEntropy);
208 } else {
209 document.onmousemove = oldMoveHandler;
210 }
211//dump("Spung!", 0);
212 }
213 }
214 }
215
216 /*Compute a 32 byte key value from the entropy vector.
217 We compute the value by taking the MD5 sum of the even
218 and odd bytes respectively of the entropy vector, then
219 concatenating the two MD5 sums. */
220
221 function keyFromEntropy() {
222 var i, k = new Array(32);
223
224 if (edlen == 0) {
225 alert("Blooie! Entropy vector void at call to keyFromEntropy.");
226 }
227//dump("Entropy bytes", edlen);
228
229 md5_init();
230 for (i = 0; i < edlen; i += 2) {
231 md5_update(entropyData[i]);
232 }
233 md5_finish();
234 for (i = 0; i < 16; i++) {
235 k[i] = digestBits[i];
236 }
237
238 md5_init();
239 for (i = 1; i < edlen; i += 2) {
240 md5_update(entropyData[i]);
241 }
242 md5_finish();
243 for (i = 0; i < 16; i++) {
244 k[i + 16] = digestBits[i];
245 }
246
247//dump("keyFromEntropy", byteArrayToHex(k));
248 return k;
249 }
250
251//#############################################################################
252 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (aesprng.js)
253//#############################################################################
254
255
256 // AES based pseudorandom number generator
257
258 /* Constructor. Called with an array of 32 byte (0-255) values
259 containing the initial seed. */
260
261 function AESprng(seed) {
262 this.key = new Array();
263 this.key = seed;
264 this.itext = hexToByteArray("9F489613248148F9C27945C6AE62EECA3E3367BB14064E4E6DC67A9F28AB3BD1");
265 this.nbytes = 0; // Bytes left in buffer
266
267 this.next = AESprng_next;
268 this.nextbits = AESprng_nextbits;
269 this.nextInt = AESprng_nextInt;
270 this.round = AESprng_round;
271
272 /* Encrypt the initial text with the seed key
273 three times, feeding the output of the encryption
274 back into the key for the next round. */
275
276 bsb = blockSizeInBits;
277 blockSizeInBits = 256;
278 var i, ct;
279 for (i = 0; i < 3; i++) {
280 this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
281 }
282
283 /* Now make between one and four additional
284 key-feedback rounds, with the number determined
285 by bits from the result of the first three
286 rounds. */
287
288 var n = 1 + (this.key[3] & 2) + (this.key[9] & 1);
289 for (i = 0; i < n; i++) {
290 this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
291 }
292 blockSizeInBits = bsb;
293 }
294
295 function AESprng_round() {
296 bsb = blockSizeInBits;
297 blockSizeInBits = 256;
298 this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
299 this.nbytes = 32;
300 blockSizeInBits = bsb;
301 }
302
303 //Return next byte from the generator
304
305 function AESprng_next() {
306 if (this.nbytes <= 0) {
307 this.round();
308 }
309 return(this.key[--this.nbytes]);
310 }
311
312 //Return n bit integer value (up to maximum integer size)
313
314 function AESprng_nextbits(n) {
315 var i, w = 0, nbytes = Math.floor((n + 7) / 8);
316
317 for (i = 0; i < nbytes; i++) {
318 w = (w << 8) | this.next();
319 }
320 return w & ((1 << n) - 1);
321 }
322
323 // Return integer between 0 and n inclusive
324
325 function AESprng_nextInt(n) {
326 var p = 1, nb = 0;
327
328 // Determine smallest p, 2^p > n
329 // nb = log_2 p
330
331 while (n >= p) {
332 p <<= 1;
333 nb++;
334 }
335 p--;
336
337 /* Generate values from 0 through n by first generating
338 values v from 0 to (2^p)-1, then discarding any results v > n.
339 For the rationale behind this (and why taking
340 values mod (n + 1) is biased toward smaller values, see
341 Ferguson and Schneier, "Practical Cryptography",
342 ISBN 0-471-22357-3, section 10.8). */
343
344 while (true) {
345 var v = this.nextbits(nb) & p;
346
347 if (v <= n) {
348 return v;
349 }
350 }
351 }
352
353//#############################################################################
354 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (md5.js)
355//#############################################################################
356
357/*
358 * md5.jvs 1.0b 27/06/96
359 *
360 * Javascript implementation of the RSA Data Security, Inc. MD5
361 * Message-Digest Algorithm.
362 *
363 * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
364 *
365 * Permission to use, copy, modify, and distribute this software
366 * and its documentation for any purposes and without
367 * fee is hereby granted provided that this copyright notice
368 * appears in all copies.
369 *
370 * Of course, this soft is provided "as is" without express or implied
371 * warranty of any kind.
372
373 This version contains some trivial reformatting modifications
374 by John Walker.
375
376 */
377
378function array(n) {
379 for (i = 0; i < n; i++) {
380 this[i] = 0;
381 }
382 this.length = n;
383}
384
385/* Some basic logical functions had to be rewritten because of a bug in
386 * Javascript.. Just try to compute 0xffffffff >> 4 with it..
387 * Of course, these functions are slower than the original would be, but
388 * at least, they work!
389 */
390
391function integer(n) {
392 return n % (0xffffffff + 1);
393}
394
395function shr(a, b) {
396 a = integer(a);
397 b = integer(b);
398 if (a - 0x80000000 >= 0) {
399 a = a % 0x80000000;
400 a >>= b;
401 a += 0x40000000 >> (b - 1);
402 } else {
403 a >>= b;
404 }
405 return a;
406}
407
408function shl1(a) {
409 a = a % 0x80000000;
410 if (a & 0x40000000 == 0x40000000) {
411 a -= 0x40000000;
412 a *= 2;
413 a += 0x80000000;
414 } else {
415 a *= 2;
416 }
417 return a;
418}
419
420function shl(a, b) {
421 a = integer(a);
422 b = integer(b);
423 for (var i = 0; i < b; i++) {
424 a = shl1(a);
425 }
426 return a;
427}
428
429function and(a, b) {
430 a = integer(a);
431 b = integer(b);
432 var t1 = a - 0x80000000;
433 var t2 = b - 0x80000000;
434 if (t1 >= 0) {
435 if (t2 >= 0) {
436 return ((t1 & t2) + 0x80000000);
437 } else {
438 return (t1 & b);
439 }
440 } else {
441 if (t2 >= 0) {
442 return (a & t2);
443 } else {
444 return (a & b);
445 }
446 }
447}
448
449function or(a, b) {
450 a = integer(a);
451 b = integer(b);
452 var t1 = a - 0x80000000;
453 var t2 = b - 0x80000000;
454 if (t1 >= 0) {
455 if (t2 >= 0) {
456 return ((t1 | t2) + 0x80000000);
457 } else {
458 return ((t1 | b) + 0x80000000);
459 }
460 } else {
461 if (t2 >= 0) {
462 return ((a | t2) + 0x80000000);
463 } else {
464 return (a | b);
465 }
466 }
467}
468
469function xor(a, b) {
470 a = integer(a);
471 b = integer(b);
472 var t1 = a - 0x80000000;
473 var t2 = b - 0x80000000;
474 if (t1 >= 0) {
475 if (t2 >= 0) {
476 return (t1 ^ t2);
477 } else {
478 return ((t1 ^ b) + 0x80000000);
479 }
480 } else {
481 if (t2 >= 0) {
482 return ((a ^ t2) + 0x80000000);
483 } else {
484 return (a ^ b);
485 }
486 }
487}
488
489function not(a) {
490 a = integer(a);
491 return 0xffffffff - a;
492}
493
494/* Here begin the real algorithm */
495
496var state = new array(4);
497var count = new array(2);
498 count[0] = 0;
499 count[1] = 0;
500var buffer = new array(64);
501var transformBuffer = new array(16);
502var digestBits = new array(16);
503
504var S11 = 7;
505var S12 = 12;
506var S13 = 17;
507var S14 = 22;
508var S21 = 5;
509var S22 = 9;
510var S23 = 14;
511var S24 = 20;
512var S31 = 4;
513var S32 = 11;
514var S33 = 16;
515var S34 = 23;
516var S41 = 6;
517var S42 = 10;
518var S43 = 15;
519var S44 = 21;
520
521function F(x, y, z) {
522 return or(and(x, y), and(not(x), z));
523}
524
525function G(x, y, z) {
526 return or(and(x, z), and(y, not(z)));
527}
528
529function H(x, y, z) {
530 return xor(xor(x, y), z);
531}
532
533function I(x, y, z) {
534 return xor(y ,or(x , not(z)));
535}
536
537function rotateLeft(a, n) {
538 return or(shl(a, n), (shr(a, (32 - n))));
539}
540
541function FF(a, b, c, d, x, s, ac) {
542 a = a + F(b, c, d) + x + ac;
543 a = rotateLeft(a, s);
544 a = a + b;
545 return a;
546}
547
548function GG(a, b, c, d, x, s, ac) {
549 a = a + G(b, c, d) + x + ac;
550 a = rotateLeft(a, s);
551 a = a + b;
552 return a;
553}
554
555function HH(a, b, c, d, x, s, ac) {
556 a = a + H(b, c, d) + x + ac;
557 a = rotateLeft(a, s);
558 a = a + b;
559 return a;
560}
561
562function II(a, b, c, d, x, s, ac) {
563 a = a + I(b, c, d) + x + ac;
564 a = rotateLeft(a, s);
565 a = a + b;
566 return a;
567}
568
569function transform(buf, offset) {
570 var a = 0, b = 0, c = 0, d = 0;
571 var x = transformBuffer;
572
573 a = state[0];
574 b = state[1];
575 c = state[2];
576 d = state[3];
577
578 for (i = 0; i < 16; i++) {
579 x[i] = and(buf[i * 4 + offset], 0xFF);
580 for (j = 1; j < 4; j++) {
581 x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
582 }
583 }
584
585 /* Round 1 */
586 a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
587 d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
588 c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
589 b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
590 a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
591 d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
592 c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
593 b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
594 a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
595 d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
596 c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
597 b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
598 a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
599 d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
600 c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
601 b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
602
603 /* Round 2 */
604 a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
605 d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
606 c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
607 b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
608 a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
609 d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */
610 c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
611 b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
612 a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
613 d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
614 c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
615 b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
616 a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
617 d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
618 c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
619 b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
620
621 /* Round 3 */
622 a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
623 d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
624 c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
625 b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
626 a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
627 d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
628 c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
629 b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
630 a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
631 d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
632 c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
633 b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
634 a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
635 d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
636 c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
637 b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
638
639 /* Round 4 */
640 a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
641 d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
642 c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
643 b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
644 a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
645 d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
646 c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
647 b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
648 a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
649 d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
650 c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
651 b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
652 a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
653 d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
654 c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
655 b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
656
657 state[0] += a;
658 state[1] += b;
659 state[2] += c;
660 state[3] += d;
661
662}
663
664function md5_init() {
665 count[0] = count[1] = 0;
666 state[0] = 0x67452301;
667 state[1] = 0xefcdab89;
668 state[2] = 0x98badcfe;
669 state[3] = 0x10325476;
670 for (i = 0; i < digestBits.length; i++) {
671 digestBits[i] = 0;
672 }
673}
674
675function md5_update(b) {
676 var index, i;
677
678 index = and(shr(count[0],3) , 0x3F);
679 if (count[0] < 0xFFFFFFFF - 7) {
680 count[0] += 8;
681 } else {
682 count[1]++;
683 count[0] -= 0xFFFFFFFF + 1;
684 count[0] += 8;
685 }
686 buffer[index] = and(b, 0xff);
687 if (index >= 63) {
688 transform(buffer, 0);
689 }
690}
691
692function md5_finish() {
693 var bits = new array(8);
694 var padding;
695 var i = 0, index = 0, padLen = 0;
696
697 for (i = 0; i < 4; i++) {
698 bits[i] = and(shr(count[0], (i * 8)), 0xFF);
699 }
700 for (i = 0; i < 4; i++) {
701 bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
702 }
703 index = and(shr(count[0], 3), 0x3F);
704 padLen = (index < 56) ? (56 - index) : (120 - index);
705 padding = new array(64);
706 padding[0] = 0x80;
707 for (i = 0; i < padLen; i++) {
708 md5_update(padding[i]);
709 }
710 for (i = 0; i < 8; i++) {
711 md5_update(bits[i]);
712 }
713
714 for (i = 0; i < 4; i++) {
715 for (j = 0; j < 4; j++) {
716 digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
717 }
718 }
719}
720
721/* End of the MD5 algorithm */
722
723//#############################################################################
724 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (aes.js)
725//#############################################################################
726
727
728/* rijndael.js Rijndael Reference Implementation
729
730 This is a modified version of the software described below,
731 produced in September 2003 by John Walker for use in the
732 JavsScrypt browser-based encryption package. The principal
733 changes are replacing the original getRandomBytes function with
734 one which calls our pseudorandom generator (which must
735 be instantiated and seeded before the first call on getRandomBytes),
736 and changing keySizeInBits to 256. Some code not required by the
737 JavsScrypt application has been commented out. Please see
738 http://www.fourmilab.ch/javascrypt/ for further information on
739 JavaScrypt.
740
741 The following is the original copyright and application
742 information.
743
744 Copyright (c) 2001 Fritz Schneider
745
746 This software is provided as-is, without express or implied warranty.
747 Permission to use, copy, modify, distribute or sell this software, with or
748 without fee, for any purpose and by any individual or organization, is hereby
749 granted, provided that the above copyright notice and this paragraph appear
750 in all copies. Distribution as a part of an application or binary must
751 include the above copyright notice in the documentation and/or other materials
752 provided with the application or distribution.
753
754 As the above disclaimer notes, you are free to use this code however you
755 want. However, I would request that you send me an email
756 (fritz /at/ cs /dot/ ucsd /dot/ edu) to say hi if you find this code useful
757 or instructional. Seeing that people are using the code acts as
758 encouragement for me to continue development. If you *really* want to thank
759 me you can buy the book I wrote with Thomas Powell, _JavaScript:
760 _The_Complete_Reference_ :)
761
762 This code is an UNOPTIMIZED REFERENCE implementation of Rijndael.
763 If there is sufficient interest I can write an optimized (word-based,
764 table-driven) version, although you might want to consider using a
765 compiled language if speed is critical to your application. As it stands,
766 one run of the monte carlo test (10,000 encryptions) can take up to
767 several minutes, depending upon your processor. You shouldn't expect more
768 than a few kilobytes per second in throughput.
769
770 Also note that there is very little error checking in these functions.
771 Doing proper error checking is always a good idea, but the ideal
772 implementation (using the instanceof operator and exceptions) requires
773 IE5+/NS6+, and I've chosen to implement this code so that it is compatible
774 with IE4/NS4.
775
776 And finally, because JavaScript doesn't have an explicit byte/char data
777 type (although JavaScript 2.0 most likely will), when I refer to "byte"
778 in this code I generally mean "32 bit integer with value in the interval
779 [0,255]" which I treat as a byte.
780
781 See http://www-cse.ucsd.edu/~fritz/rijndael.html for more documentation
782 of the (very simple) API provided by this code.
783
784 Fritz Schneider
785 fritz at cs.ucsd.edu
786
787*/
788
789
790// Rijndael parameters -- Valid values are 128, 192, or 256
791
792var keySizeInBits = 256;
793var blockSizeInBits = 128;
794
795//
796// Note: in the following code the two dimensional arrays are indexed as
797// you would probably expect, as array[row][column]. The state arrays
798// are 2d arrays of the form state[4][Nb].
799
800
801// The number of rounds for the cipher, indexed by [Nk][Nb]
802var roundsArray = [ ,,,,[,,,,10,, 12,, 14],,
803 [,,,,12,, 12,, 14],,
804 [,,,,14,, 14,, 14] ];
805
806// The number of bytes to shift by in shiftRow, indexed by [Nb][row]
807var shiftOffsets = [ ,,,,[,1, 2, 3],,[,1, 2, 3],,[,1, 3, 4] ];
808
809// The round constants used in subkey expansion
810var Rcon = [
8110x01, 0x02, 0x04, 0x08, 0x10, 0x20,
8120x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
8130xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
8140x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
8150xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ];
816
817// Precomputed lookup table for the SBox
818var SBox = [
819 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171,
820118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
821114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113,
822216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
823235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214,
824179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
825190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69,
826249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
827188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68,
82823, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
829144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73,
830 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
831141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37,
832 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
833181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225,
834248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
835140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187,
836 22 ];
837
838// Precomputed lookup table for the inverse SBox
839var SBoxInverse = [
840 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215,
841251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222,
842233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66,
843250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73,
844109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92,
845204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21,
846 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247,
847228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2,
848193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220,
849234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173,
850 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29,
851 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75,
852198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168,
853 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81,
854127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160,
855224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
856 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12,
857125 ];
858
859// This method circularly shifts the array left by the number of elements
860// given in its parameter. It returns the resulting array and is used for
861// the ShiftRow step. Note that shift() and push() could be used for a more
862// elegant solution, but they require IE5.5+, so I chose to do it manually.
863
864function cyclicShiftLeft(theArray, positions) {
865 var temp = theArray.slice(0, positions);
866 theArray = theArray.slice(positions).concat(temp);
867 return theArray;
868}
869
870// Cipher parameters ... do not change these
871var Nk = keySizeInBits / 32;
872var Nb = blockSizeInBits / 32;
873var Nr = roundsArray[Nk][Nb];
874
875// Multiplies the element "poly" of GF(2^8) by x. See the Rijndael spec.
876
877function xtime(poly) {
878 poly <<= 1;
879 return ((poly & 0x100) ? (poly ^ 0x11B) : (poly));
880}
881
882// Multiplies the two elements of GF(2^8) together and returns the result.
883// See the Rijndael spec, but should be straightforward: for each power of
884// the indeterminant that has a 1 coefficient in x, add y times that power
885// to the result. x and y should be bytes representing elements of GF(2^8)
886
887function mult_GF256(x, y) {
888 var bit, result = 0;
889
890 for (bit = 1; bit < 256; bit *= 2, y = xtime(y)) {
891 if (x & bit)
892 result ^= y;
893 }
894 return result;
895}
896
897// Performs the substitution step of the cipher. State is the 2d array of
898// state information (see spec) and direction is string indicating whether
899// we are performing the forward substitution ("encrypt") or inverse
900// substitution (anything else)
901
902function byteSub(state, direction) {
903 var S;
904 if (direction == "encrypt") // Point S to the SBox we're using
905 S = SBox;
906 else
907 S = SBoxInverse;
908 for (var i = 0; i < 4; i++) // Substitute for every byte in state
909 for (var j = 0; j < Nb; j++)
910 state[i][j] = S[state[i][j]];
911}
912
913// Performs the row shifting step of the cipher.
914
915function shiftRow(state, direction) {
916 for (var i=1; i<4; i++) // Row 0 never shifts
917 if (direction == "encrypt")
918 state[i] = cyclicShiftLeft(state[i], shiftOffsets[Nb][i]);
919 else
920 state[i] = cyclicShiftLeft(state[i], Nb - shiftOffsets[Nb][i]);
921
922}
923
924// Performs the column mixing step of the cipher. Most of these steps can
925// be combined into table lookups on 32bit values (at least for encryption)
926// to greatly increase the speed.
927
928function mixColumn(state, direction) {
929 var b = []; // Result of matrix multiplications
930 for (var j = 0; j < Nb; j++) { // Go through each column...
931 for (var i = 0; i < 4; i++) { // and for each row in the column...
932 if (direction == "encrypt")
933 b[i] = mult_GF256(state[i][j], 2) ^ // perform mixing
934 mult_GF256(state[(i+1)%4][j], 3) ^
935 state[(i+2)%4][j] ^
936 state[(i+3)%4][j];
937 else
938 b[i] = mult_GF256(state[i][j], 0xE) ^
939 mult_GF256(state[(i+1)%4][j], 0xB) ^
940 mult_GF256(state[(i+2)%4][j], 0xD) ^
941 mult_GF256(state[(i+3)%4][j], 9);
942 }
943 for (var i = 0; i < 4; i++) // Place result back into column
944 state[i][j] = b[i];
945 }
946}
947
948// Adds the current round key to the state information. Straightforward.
949
950function addRoundKey(state, roundKey) {
951 for (var j = 0; j < Nb; j++) { // Step through columns...
952 state[0][j] ^= (roundKey[j] & 0xFF); // and XOR
953 state[1][j] ^= ((roundKey[j]>>8) & 0xFF);
954 state[2][j] ^= ((roundKey[j]>>16) & 0xFF);
955 state[3][j] ^= ((roundKey[j]>>24) & 0xFF);
956 }
957}
958
959// This function creates the expanded key from the input (128/192/256-bit)
960// key. The parameter key is an array of bytes holding the value of the key.
961// The returned value is an array whose elements are the 32-bit words that
962// make up the expanded key.
963
964function keyExpansion(key) {
965 var expandedKey = new Array();
966 var temp;
967
968 // in case the key size or parameters were changed...
969 Nk = keySizeInBits / 32;
970 Nb = blockSizeInBits / 32;
971 Nr = roundsArray[Nk][Nb];
972
973 for (var j=0; j < Nk; j++) // Fill in input key first
974 expandedKey[j] =
975 (key[4*j]) | (key[4*j+1]<<8) | (key[4*j+2]<<16) | (key[4*j+3]<<24);
976
977 // Now walk down the rest of the array filling in expanded key bytes as
978 // per Rijndael's spec
979 for (j = Nk; j < Nb * (Nr + 1); j++) { // For each word of expanded key
980 temp = expandedKey[j - 1];
981 if (j % Nk == 0)
982 temp = ( (SBox[(temp>>8) & 0xFF]) |
983 (SBox[(temp>>16) & 0xFF]<<8) |
984 (SBox[(temp>>24) & 0xFF]<<16) |
985 (SBox[temp & 0xFF]<<24) ) ^ Rcon[Math.floor(j / Nk) - 1];
986 else if (Nk > 6 && j % Nk == 4)
987 temp = (SBox[(temp>>24) & 0xFF]<<24) |
988 (SBox[(temp>>16) & 0xFF]<<16) |
989 (SBox[(temp>>8) & 0xFF]<<8) |
990 (SBox[temp & 0xFF]);
991 expandedKey[j] = expandedKey[j-Nk] ^ temp;
992 }
993 return expandedKey;
994}
995
996// Rijndael's round functions...
997
998function Round(state, roundKey) {
999 byteSub(state, "encrypt");
1000 shiftRow(state, "encrypt");
1001 mixColumn(state, "encrypt");
1002 addRoundKey(state, roundKey);
1003}
1004
1005function InverseRound(state, roundKey) {
1006 addRoundKey(state, roundKey);
1007 mixColumn(state, "decrypt");
1008 shiftRow(state, "decrypt");
1009 byteSub(state, "decrypt");
1010}
1011
1012function FinalRound(state, roundKey) {
1013 byteSub(state, "encrypt");
1014 shiftRow(state, "encrypt");
1015 addRoundKey(state, roundKey);
1016}
1017
1018function InverseFinalRound(state, roundKey){
1019 addRoundKey(state, roundKey);
1020 shiftRow(state, "decrypt");
1021 byteSub(state, "decrypt");
1022}
1023
1024// encrypt is the basic encryption function. It takes parameters
1025// block, an array of bytes representing a plaintext block, and expandedKey,
1026// an array of words representing the expanded key previously returned by
1027// keyExpansion(). The ciphertext block is returned as an array of bytes.
1028
1029function encrypt(block, expandedKey) {
1030 var i;
1031 if (!block || block.length*8 != blockSizeInBits)
1032 return;
1033 if (!expandedKey)
1034 return;
1035
1036 block = packBytes(block);
1037 addRoundKey(block, expandedKey);
1038 for (i=1; i<Nr; i++)
1039 Round(block, expandedKey.slice(Nb*i, Nb*(i+1)));
1040 FinalRound(block, expandedKey.slice(Nb*Nr));
1041 return unpackBytes(block);
1042}
1043
1044// decrypt is the basic decryption function. It takes parameters
1045// block, an array of bytes representing a ciphertext block, and expandedKey,
1046// an array of words representing the expanded key previously returned by
1047// keyExpansion(). The decrypted block is returned as an array of bytes.
1048
1049function decrypt(block, expandedKey) {
1050 var i;
1051 if (!block || block.length*8 != blockSizeInBits)
1052 return;
1053 if (!expandedKey)
1054 return;
1055
1056 block = packBytes(block);
1057 InverseFinalRound(block, expandedKey.slice(Nb*Nr));
1058 for (i = Nr - 1; i>0; i--)
1059 InverseRound(block, expandedKey.slice(Nb*i, Nb*(i+1)));
1060 addRoundKey(block, expandedKey);
1061 return unpackBytes(block);
1062}
1063
1064/* !NEEDED
1065// This method takes a byte array (byteArray) and converts it to a string by
1066// applying String.fromCharCode() to each value and concatenating the result.
1067// The resulting string is returned. Note that this function SKIPS zero bytes
1068// under the assumption that they are padding added in formatPlaintext().
1069// Obviously, do not invoke this method on raw data that can contain zero
1070// bytes. It is really only appropriate for printable ASCII/Latin-1
1071// values. Roll your own function for more robust functionality :)
1072
1073function byteArrayToString(byteArray) {
1074 var result = "";
1075 for(var i=0; i<byteArray.length; i++)
1076 if (byteArray[i] != 0)
1077 result += String.fromCharCode(byteArray[i]);
1078 return result;
1079}
1080*/
1081
1082// This function takes an array of bytes (byteArray) and converts them
1083// to a hexadecimal string. Array element 0 is found at the beginning of
1084// the resulting string, high nibble first. Consecutive elements follow
1085// similarly, for example [16, 255] --> "10ff". The function returns a
1086// string.
1087
1088function byteArrayToHex(byteArray) {
1089 var result = "";
1090 if (!byteArray)
1091 return;
1092 for (var i=0; i<byteArray.length; i++)
1093 result += ((byteArray[i]<16) ? "0" : "") + byteArray[i].toString(16);
1094
1095 return result;
1096}
1097
1098// This function converts a string containing hexadecimal digits to an
1099// array of bytes. The resulting byte array is filled in the order the
1100// values occur in the string, for example "10FF" --> [16, 255]. This
1101// function returns an array.
1102
1103function hexToByteArray(hexString) {
1104 var byteArray = [];
1105 if (hexString.length % 2) // must have even length
1106 return;
1107 if (hexString.indexOf("0x") == 0 || hexString.indexOf("0X") == 0)
1108 hexString = hexString.substring(2);
1109 for (var i = 0; i<hexString.length; i += 2)
1110 byteArray[Math.floor(i/2)] = parseInt(hexString.slice(i, i+2), 16);
1111 return byteArray;
1112}
1113
1114// This function packs an array of bytes into the four row form defined by
1115// Rijndael. It assumes the length of the array of bytes is divisible by
1116// four. Bytes are filled in according to the Rijndael spec (starting with
1117// column 0, row 0 to 3). This function returns a 2d array.
1118
1119function packBytes(octets) {
1120 var state = new Array();
1121 if (!octets || octets.length % 4)
1122 return;
1123
1124 state[0] = new Array(); state[1] = new Array();
1125 state[2] = new Array(); state[3] = new Array();
1126 for (var j=0; j<octets.length; j+= 4) {
1127 state[0][j/4] = octets[j];
1128 state[1][j/4] = octets[j+1];
1129 state[2][j/4] = octets[j+2];
1130 state[3][j/4] = octets[j+3];
1131 }
1132 return state;
1133}
1134
1135// This function unpacks an array of bytes from the four row format preferred
1136// by Rijndael into a single 1d array of bytes. It assumes the input "packed"
1137// is a packed array. Bytes are filled in according to the Rijndael spec.
1138// This function returns a 1d array of bytes.
1139
1140function unpackBytes(packed) {
1141 var result = new Array();
1142 for (var j=0; j<packed[0].length; j++) {
1143 result[result.length] = packed[0][j];
1144 result[result.length] = packed[1][j];
1145 result[result.length] = packed[2][j];
1146 result[result.length] = packed[3][j];
1147 }
1148 return result;
1149}
1150
1151// This function takes a prospective plaintext (string or array of bytes)
1152// and pads it with pseudorandom bytes if its length is not a multiple of the block
1153// size. If plaintext is a string, it is converted to an array of bytes
1154// in the process. The type checking can be made much nicer using the
1155// instanceof operator, but this operator is not available until IE5.0 so I
1156// chose to use the heuristic below.
1157
1158function formatPlaintext(plaintext) {
1159 var bpb = blockSizeInBits / 8; // bytes per block
1160 var fillWithRandomBits;
1161 var i;
1162
1163 // if primitive string or String instance
1164 if ((!((typeof plaintext == "object") &&
1165 ((typeof (plaintext[0])) == "number"))) &&
1166 ((typeof plaintext == "string") || plaintext.indexOf))
1167 {
1168 plaintext = plaintext.split("");
1169 // Unicode issues here (ignoring high byte)
1170 for (i=0; i<plaintext.length; i++) {
1171 plaintext[i] = plaintext[i].charCodeAt(0) & 0xFF;
1172 }
1173 }
1174
1175 i = plaintext.length % bpb;
1176 if (i > 0) {
1177//alert("adding " + (bpb - 1) + " bytes");
1178 // plaintext = plaintext.concat(getRandomBytes(bpb - i));
1179 {
1180 varpaddingBytes;
1181 var ii,cc;
1182
1183 paddingBytes = new Array();
1184 cc = bpb - i;
1185 for (ii=0; ii<cc; ii++) {
1186 paddingBytes[ii] = cc;
1187 }
1188
1189//is("cc", cc);
1190//is(getRandomBytes(bpb - i) + "", paddingBytes + "");
1191 plaintext = plaintext.concat(paddingBytes);
1192 }
1193 }
1194
1195 return plaintext;
1196}
1197
1198// Returns an array containing "howMany" random bytes.
1199
1200function getRandomBytes(howMany) {
1201 var i, bytes = new Array();
1202
1203//alert("getting some random bytes");
1204 for (i = 0; i < howMany; i++) {
1205 bytes[i] = prng.nextInt(255);
1206 }
1207 return bytes;
1208}
1209
1210// rijndaelEncrypt(plaintext, key, mode)
1211// Encrypts the plaintext using the given key and in the given mode.
1212// The parameter "plaintext" can either be a string or an array of bytes.
1213// The parameter "key" must be an array of key bytes. If you have a hex
1214// string representing the key, invoke hexToByteArray() on it to convert it
1215// to an array of bytes. The third parameter "mode" is a string indicating
1216// the encryption mode to use, either "ECB" or "CBC". If the parameter is
1217// omitted, ECB is assumed.
1218//
1219// An array of bytes representing the cihpertext is returned. To convert
1220// this array to hex, invoke byteArrayToHex() on it.
1221
1222function rijndaelEncrypt(plaintext, key, mode) {
1223 var expandedKey, i, aBlock;
1224 var bpb = blockSizeInBits / 8; // bytes per block
1225 var ct; // ciphertext
1226
1227 if (!plaintext || !key)
1228 return;
1229 if (key.length*8 != keySizeInBits)
1230 return;
1231 if (mode == "CBC") {
1232 ct = getRandomBytes(bpb); // get IV
1233//dump("IV", byteArrayToHex(ct));
1234 } else {
1235 mode = "ECB";
1236 ct = new Array();
1237 }
1238
1239 // convert plaintext to byte array and pad with zeros if necessary.
1240 plaintext = formatPlaintext(plaintext);
1241
1242 expandedKey = keyExpansion(key);
1243
1244 for (var block = 0; block < plaintext.length / bpb; block++) {
1245 aBlock = plaintext.slice(block * bpb, (block + 1) * bpb);
1246 if (mode == "CBC") {
1247 for (var i = 0; i < bpb; i++) {
1248 aBlock[i] ^= ct[(block * bpb) + i];
1249 }
1250 }
1251 ct = ct.concat(encrypt(aBlock, expandedKey));
1252 }
1253
1254 return ct;
1255}
1256
1257// rijndaelDecrypt(ciphertext, key, mode)
1258// Decrypts the using the given key and mode. The parameter "ciphertext"
1259// must be an array of bytes. The parameter "key" must be an array of key
1260// bytes. If you have a hex string representing the ciphertext or key,
1261// invoke hexToByteArray() on it to convert it to an array of bytes. The
1262// parameter "mode" is a string, either "CBC" or "ECB".
1263//
1264// An array of bytes representing the plaintext is returned. To convert
1265// this array to a hex string, invoke byteArrayToHex() on it. To convert it
1266// to a string of characters, you can use byteArrayToString().
1267
1268function rijndaelDecrypt(ciphertext, key, mode) {
1269 var expandedKey;
1270 var bpb = blockSizeInBits / 8; // bytes per block
1271 var pt = new Array(); // plaintext array
1272 var aBlock; // a decrypted block
1273 var block; // current block number
1274
1275 if (!ciphertext || !key || typeof ciphertext == "string")
1276 return;
1277 if (key.length*8 != keySizeInBits)
1278 return;
1279 if (!mode) {
1280 mode = "ECB"; // assume ECB if mode omitted
1281 }
1282
1283 expandedKey = keyExpansion(key);
1284
1285 // work backwards to accomodate CBC mode
1286 for (block=(ciphertext.length / bpb)-1; block>0; block--) {
1287 aBlock =
1288 decrypt(ciphertext.slice(block*bpb,(block+1)*bpb), expandedKey);
1289 if (mode == "CBC")
1290 for (var i=0; i<bpb; i++)
1291 pt[(block-1)*bpb + i] = aBlock[i] ^ ciphertext[(block-1)*bpb + i];
1292 else
1293 pt = aBlock.concat(pt);
1294 }
1295
1296 // do last block if ECB (skips the IV in CBC)
1297 if (mode == "ECB")
1298 pt = decrypt(ciphertext.slice(0, bpb), expandedKey).concat(pt);
1299
1300 return pt;
1301}
1302
1303//#############################################################################
1304 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (utf-8.js)
1305//#############################################################################
1306
1307
1308 /*Encoding and decoding of Unicode character strings as
1309 UTF-8 byte streams. */
1310
1311 //UNICODE_TO_UTF8 -- Encode Unicode argument string as UTF-8 return value
1312
1313 function unicode_to_utf8(s) {
1314 var utf8 = "";
1315
1316 for (var n = 0; n < s.length; n++) {
1317 var c = s.charCodeAt(n);
1318
1319 if (c <= 0x7F) {
1320 // 0x00 - 0x7F: Emit as single byte, unchanged
1321 utf8 += String.fromCharCode(c);
1322 } else if ((c >= 0x80) && (c <= 0x7FF)) {
1323 // 0x80 - 0x7FF: Output as two byte code, 0xC0 in first byte
1324 // 0x80 in second byte
1325 utf8 += String.fromCharCode((c >> 6) | 0xC0);
1326 utf8 += String.fromCharCode((c & 0x3F) | 0x80);
1327 } else {
1328 // 0x800 - 0xFFFF: Output as three bytes, 0xE0 in first byte
1329 // 0x80 in second byte
1330 // 0x80 in third byte
1331 utf8 += String.fromCharCode((c >> 12) | 0xE0);
1332 utf8 += String.fromCharCode(((c >> 6) & 0x3F) | 0x80);
1333 utf8 += String.fromCharCode((c & 0x3F) | 0x80);
1334 }
1335 }
1336 return utf8;
1337 }
1338
1339 //UTF8_TO_UNICODE -- Decode UTF-8 argument into Unicode string return value
1340
1341 function utf8_to_unicode(utf8) {
1342 var s = "", i = 0, b1, b2, b2;
1343
1344 while (i < utf8.length) {
1345 b1 = utf8.charCodeAt(i);
1346 if (b1 < 0x80) { // One byte code: 0x00 0x7F
1347 s += String.fromCharCode(b1);
1348 i++;
1349 } else if((b1 >= 0xC0) && (b1 < 0xE0)) {// Two byte code: 0x80 - 0x7FF
1350 b2 = utf8.charCodeAt(i + 1);
1351 s += String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
1352 i += 2;
1353 } else { // Three byte code: 0x800 - 0xFFFF
1354 b2 = utf8.charCodeAt(i + 1);
1355 b3 = utf8.charCodeAt(i + 2);
1356 s += String.fromCharCode(((b1 & 0xF) << 12) |
1357 ((b2 & 0x3F) << 6) |
1358 (b3 & 0x3F));
1359 i += 3;
1360 }
1361 }
1362 return s;
1363 }
1364
1365 /*ENCODE_UTF8 -- Encode string as UTF8 only if it contains
1366 a character of 0x9D (Unicode OPERATING
1367 SYSTEM COMMAND) or a character greater
1368 than 0xFF. This permits all strings
1369 consisting exclusively of 8 bit
1370 graphic characters to be encoded as
1371 themselves. We choose 0x9D as the sentinel
1372 character as opposed to one of the more
1373 logical PRIVATE USE characters because 0x9D
1374 is not overloaded by the regrettable
1375 "Windows-1252" character set. Now such characters
1376 don't belong in JavaScript strings, but you never
1377 know what somebody is going to paste into a
1378 text box, so this choice keeps Windows-encoded
1379 strings from bloating to UTF-8 encoding. */
1380
1381 function encode_utf8(s) {
1382 var i, necessary = false;
1383
1384 for (i = 0; i < s.length; i++) {
1385 if ((s.charCodeAt(i) == 0x9D) ||
1386 (s.charCodeAt(i) > 0xFF)) {
1387 necessary = true;
1388 break;
1389 }
1390 }
1391 if (!necessary) {
1392 return s;
1393 }
1394 return String.fromCharCode(0x9D) + unicode_to_utf8(s);
1395 }
1396
1397 /* DECODE_UTF8 -- Decode a string encoded with encode_utf8
1398 above. If the string begins with the
1399 sentinel character 0x9D (OPERATING
1400 SYSTEM COMMAND), then we decode the
1401 balance as a UTF-8 stream. Otherwise,
1402 the string is output unchanged, as
1403 it's guaranteed to contain only 8 bit
1404 characters excluding 0x9D. */
1405
1406 function decode_utf8(s) {
1407 if ((s.length > 0) && (s.charCodeAt(0) == 0x9D)) {
1408 return utf8_to_unicode(s.substring(1));
1409 }
1410 return s;
1411 }
1412
1413
1414//#############################################################################
1415 //Downloaded on April 26, 2006 from http://pajhome.org.uk/crypt/md5/md5.js
1416//#############################################################################
1417
1418/*
1419 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
1420 * Digest Algorithm, as defined in RFC 1321.
1421 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
1422 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
1423 * Distributed under the BSD License
1424 * See http://pajhome.org.uk/crypt/md5 for more info.
1425 */
1426
1427/*
1428 * Configurable variables. You may need to tweak these to be compatible with
1429 * the server-side, but the defaults work in most cases.
1430 */
1431var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
1432var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
1433var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
1434
1435/*
1436 * These are the functions you'll usually want to call
1437 * They take string arguments and return either hex or base-64 encoded strings
1438 */
1439function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
1440function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
1441function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
1442function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
1443function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
1444function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
1445
1446/*
1447 * Perform a simple self-test to see if the VM is working
1448 */
1449function md5_vm_test()
1450{
1451 return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
1452}
1453
1454/*
1455 * Calculate the MD5 of an array of little-endian words, and a bit length
1456 */
1457function core_md5(x, len)
1458{
1459 /* append padding */
1460 x[len >> 5] |= 0x80 << ((len) % 32);
1461 x[(((len + 64) >>> 9) << 4) + 14] = len;
1462
1463 var a = 1732584193;
1464 var b = -271733879;
1465 var c = -1732584194;
1466 var d = 271733878;
1467
1468 for(var i = 0; i < x.length; i += 16)
1469 {
1470 var olda = a;
1471 var oldb = b;
1472 var oldc = c;
1473 var oldd = d;
1474
1475 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
1476 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
1477 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
1478 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
1479 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
1480 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
1481 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
1482 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
1483 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
1484 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
1485 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
1486 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
1487 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
1488 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
1489 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
1490 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
1491
1492 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
1493 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
1494 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
1495 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
1496 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
1497 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
1498 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
1499 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
1500 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
1501 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
1502 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
1503 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
1504 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
1505 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
1506 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
1507 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
1508
1509 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
1510 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
1511 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
1512 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
1513 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
1514 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
1515 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
1516 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
1517 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
1518 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
1519 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
1520 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
1521 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
1522 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
1523 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
1524 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
1525
1526 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
1527 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
1528 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
1529 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
1530 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
1531 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
1532 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
1533 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
1534 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
1535 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
1536 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
1537 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
1538 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
1539 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
1540 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
1541 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
1542
1543 a = safe_add(a, olda);
1544 b = safe_add(b, oldb);
1545 c = safe_add(c, oldc);
1546 d = safe_add(d, oldd);
1547 }
1548 return Array(a, b, c, d);
1549
1550}
1551
1552/*
1553 * These functions implement the four basic operations the algorithm uses.
1554 */
1555function md5_cmn(q, a, b, x, s, t)
1556{
1557 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
1558}
1559function md5_ff(a, b, c, d, x, s, t)
1560{
1561 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
1562}
1563function md5_gg(a, b, c, d, x, s, t)
1564{
1565 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
1566}
1567function md5_hh(a, b, c, d, x, s, t)
1568{
1569 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
1570}
1571function md5_ii(a, b, c, d, x, s, t)
1572{
1573 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
1574}
1575
1576/*
1577 * Calculate the HMAC-MD5, of a key and some data
1578 */
1579function core_hmac_md5(key, data)
1580{
1581 var bkey = str2binl(key);
1582 if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
1583
1584 var ipad = Array(16), opad = Array(16);
1585 for(var i = 0; i < 16; i++)
1586 {
1587 ipad[i] = bkey[i] ^ 0x36363636;
1588 opad[i] = bkey[i] ^ 0x5C5C5C5C;
1589 }
1590
1591 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
1592 return core_md5(opad.concat(hash), 512 + 128);
1593}
1594
1595/*
1596 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
1597 * to work around bugs in some JS interpreters.
1598 */
1599function safe_add(x, y)
1600{
1601 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
1602 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
1603 return (msw << 16) | (lsw & 0xFFFF);
1604}
1605
1606/*
1607 * Bitwise rotate a 32-bit number to the left.
1608 */
1609function bit_rol(num, cnt)
1610{
1611 return (num << cnt) | (num >>> (32 - cnt));
1612}
1613
1614/*
1615 * Convert a string to an array of little-endian words
1616 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
1617 */
1618function str2binl(str)
1619{
1620 var bin = Array();
1621 var mask = (1 << chrsz) - 1;
1622 for(var i = 0; i < str.length * chrsz; i += chrsz)
1623 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
1624 return bin;
1625}
1626
1627/*
1628 * Convert an array of little-endian words to a string
1629 */
1630function binl2str(bin)
1631{
1632 var str = "";
1633 var mask = (1 << chrsz) - 1;
1634 for(var i = 0; i < bin.length * 32; i += chrsz)
1635 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
1636 return str;
1637}
1638
1639/*
1640 * Convert an array of little-endian words to a hex string.
1641 */
1642function binl2hex(binarray)
1643{
1644 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
1645 var str = "";
1646 for(var i = 0; i < binarray.length * 4; i++)
1647 {
1648 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
1649 hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
1650 }
1651 return str;
1652}
1653
1654/*
1655 * Convert an array of little-endian words to a base-64 string
1656 */
1657function binl2b64(binarray)
1658{
1659 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1660 var str = "";
1661 for(var i = 0; i < binarray.length * 4; i += 3)
1662 {
1663 var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
1664 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
1665 | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
1666 for(var j = 0; j < 4; j++)
1667 {
1668 if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
1669 else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
1670 }
1671 }
1672 return str;
1673}
1674
1675
1676//#############################################################################
1677//#############################################################################
1678//#############################################################################
1679
1680
1681
1682MochiKit.Base.update(Clipperz.Crypto.Base, {
1683
1684 '__repr__': function () {
1685 return "[" + this.NAME + " " + this.VERSION + "]";
1686 },
1687
1688 'toString': function () {
1689 return this.__repr__();
1690 },
1691
1692 //-----------------------------------------------------------------------------
1693
1694 'encryptUsingSecretKey': function (aKey, aMessage) {
1695//Clipperz.Profile.start("Clipperz.Crypto.Base.encryptUsingSecretKey");
1696 var result;
1697 var plaintext;
1698 varheader;
1699 varkey;
1700
1701 key = hexToByteArray(Clipperz.Crypto.Base.computeHashValue(aKey));
1702
1703 addEntropyTime();
1704 prng = new AESprng(keyFromEntropy());
1705
1706 plaintext = encode_utf8(aMessage);
1707
1708 header = Clipperz.Base.byteArrayToString(hexToByteArray(Clipperz.Crypto.Base.computeMD5HashValue(plaintext)));
1709
1710 // Add message length in bytes to header
1711 i = plaintext.length;
1712 header += String.fromCharCode(i >>> 24);
1713 header += String.fromCharCode(i >>> 16);
1714 header += String.fromCharCode(i >>> 8);
1715 header += String.fromCharCode(i & 0xFF);
1716
1717 //The format of the actual message passed to rijndaelEncrypt
1718 //is:
1719 //
1720 // Bytes Content
1721 // 0-15 MD5 signature of plaintext
1722 // 16-19 Length of plaintext, big-endian order
1723 // 20-end Plaintext
1724 //
1725 //Note that this message will be padded with zero bytes
1726 //to an integral number of AES blocks (blockSizeInBits / 8).
1727 //This does not include the initial vector for CBC
1728 //encryption, which is added internally by rijndaelEncrypt.
1729 result = byteArrayToHex(rijndaelEncrypt(header + plaintext, key, "CBC"));
1730
1731 delete prng;
1732
1733//Clipperz.Profile.stop("Clipperz.Crypto.Base.encryptUsingSecretKey");
1734 return result;
1735 },
1736
1737 //.............................................................................
1738
1739 'decryptUsingSecretKey': function (aKey, aMessage) {
1740//Clipperz.Profile.start("Clipperz.Crypto.Base.decryptUsingSecretKey");
1741 varkey;
1742 var decryptedText;
1743 vartextLength;
1744 varheader;
1745 varheaderDigest;
1746 var plaintext;
1747 var i;
1748
1749 key = hexToByteArray(Clipperz.Crypto.Base.computeHashValue(aKey));
1750
1751 decryptedText = rijndaelDecrypt(hexToByteArray(aMessage), key, "CBC");
1752
1753 header = decryptedText.slice(0, 20);
1754 decryptedText = decryptedText.slice(20);
1755
1756 headerDigest = byteArrayToHex(header.slice(0,16));
1757 textLength = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | header[19];
1758
1759 if ((textLength < 0) || (textLength > decryptedText.length)) {
1760 // jslog.warning("Message (length " + decryptedText.length + ") truncated. " + textLength + " characters expected.");
1761 //Try to sauve qui peut by setting length to entire message
1762 textLength = decryptedText.length;
1763 }
1764
1765 plainText = "";
1766
1767 for (i=0; i<textLength; i++) {
1768 plainText += String.fromCharCode(decryptedText[i]);
1769 }
1770
1771 if (Clipperz.Crypto.Base.computeMD5HashValue(plainText) != headerDigest) {
1772 // jslog.warning("Message corrupted. Checksum of decrypted message does not match.");
1773 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
1774 // throw new Error("Message corrupted. Checksum of decrypted message does not match. Parsed result: " + decode_utf8(plainText));
1775 }
1776
1777 // That's it; plug plaintext into the result field
1778
1779 result = decode_utf8(plainText);
1780
1781//Clipperz.Profile.stop("Clipperz.Crypto.Base.decryptUsingSecretKey");
1782 return result;
1783 },
1784
1785 //-----------------------------------------------------------------------------
1786
1787 'computeHashValue': function (aMessage) {
1788//Clipperz.Profile.start("Clipperz.Crypto.Base.computeHashValue");
1789 varresult;
1790
1791 result = hex_sha256(aMessage);
1792//Clipperz.Profile.stop("Clipperz.Crypto.Base.computeHashValue");
1793
1794 return result;
1795 },
1796
1797 //.........................................................................
1798
1799 'computeMD5HashValue': function (aMessage) {
1800 varresult;
1801//Clipperz.Profile.start("Clipperz.Crypto.Base.computeMD5HashValue");
1802 result = hex_md5(aMessage);
1803//Clipperz.Profile.stop("Clipperz.Crypto.Base.computeMD5HashValue");
1804
1805 return result;
1806 },
1807
1808 //-----------------------------------------------------------------------------
1809
1810 'generateRandomSeed': function () {
1811//Clipperz.Profile.start("Clipperz.Crypto.Base.generateRandomSeed");
1812 varresult;
1813 var seed;
1814 var prng;
1815 var charA;
1816 var i;
1817
1818 addEntropyTime();
1819
1820 seed = keyFromEntropy();
1821 prng = new AESprng(seed);
1822
1823 result = "";
1824 charA = ("A").charCodeAt(0);
1825
1826 for (i = 0; i < 64; i++) {
1827 result += String.fromCharCode(charA + prng.nextInt(25));
1828 }
1829
1830 delete prng;
1831
1832 result = Clipperz.Crypto.Base.computeHashValue(result);
1833
1834//Clipperz.Profile.stop("Clipperz.Crypto.Base.generateRandomSeed");
1835 return result;
1836 },
1837
1838 //-----------------------------------------------------------------------------
1839
1840 'exception': {
1841 'CorruptedMessage': new MochiKit.Base.NamedError("Clipperz.Crypto.Base.exception.CorruptedMessage")
1842 },
1843
1844 //.........................................................................
1845 __syntaxFix__: "syntax fix"
1846});
1847
diff --git a/frontend/delta/js/Clipperz/Crypto/BigInt.js b/frontend/delta/js/Clipperz/Crypto/BigInt.js
new file mode 100644
index 0000000..031ed30
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/BigInt.js
@@ -0,0 +1,1754 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
26
27//#############################################################################
28 //Downloaded on March 05, 2007 from http://www.leemon.com/crypto/BigInt.js
29//#############################################################################
30
31
32////////////////////////////////////////////////////////////////////////////////////////
33// Big Integer Library v. 5.0
34// Created 2000, last modified 2006
35// Leemon Baird
36// www.leemon.com
37//
38// This file is public domain. You can use it for any purpose without restriction.
39// I do not guarantee that it is correct, so use it at your own risk. If you use
40// it for something interesting, I'd appreciate hearing about it. If you find
41// any bugs or make any improvements, I'd appreciate hearing about those too.
42// It would also be nice if my name and address were left in the comments.
43// But none of that is required.
44//
45// This code defines a bigInt library for arbitrary-precision integers.
46// A bigInt is an array of integers storing the value in chunks of bpe bits,
47// little endian (buff[0] is the least significant word).
48// Negative bigInts are stored two's complement.
49// Some functions assume their parameters have at least one leading zero element.
50// Functions with an underscore at the end of the name have unpredictable behavior in case of overflow,
51// so the caller must make sure overflow won't happen.
52// For each function where a parameter is modified, that same
53// variable must not be used as another argument too.
54// So, you cannot square x by doing multMod_(x,x,n).
55// You must use squareMod_(x,n) instead, or do y=dup(x); multMod_(x,y,n).
56//
57// These functions are designed to avoid frequent dynamic memory allocation in the inner loop.
58// For most functions, if it needs a BigInt as a local variable it will actually use
59// a global, and will only allocate to it when it's not the right size. This ensures
60// that when a function is called repeatedly with same-sized parameters, it only allocates
61// memory on the first call.
62//
63// Note that for cryptographic purposes, the calls to Math.random() must
64// be replaced with calls to a better pseudorandom number generator.
65//
66// In the following, "bigInt" means a bigInt with at least one leading zero element,
67// and "integer" means a nonnegative integer less than radix. In some cases, integer
68// can be negative. Negative bigInts are 2s complement.
69//
70// The following functions do not modify their inputs, but dynamically allocate memory every time they are called:
71//
72// function bigInt2str(x,base) //convert a bigInt into a string in a given base, from base 2 up to base 95
73// function dup(x) //returns a copy of bigInt x
74// function findPrimes(n) //return array of all primes less than integer n
75// function int2bigInt(t,n,m) //convert integer t to a bigInt with at least n bits and m array elements
76// function int2bigInt(s,b,n,m) //convert string s in base b to a bigInt with at least n bits and m array elements
77// function trim(x,k) //return a copy of x with exactly k leading zero elements
78//
79// The following functions do not modify their inputs, so there is never a problem with the result being too big:
80//
81// function bitSize(x) //returns how many bits long the bigInt x is, not counting leading zeros
82// function equals(x,y) //is the bigInt x equal to the bigint y?
83// function equalsInt(x,y) //is bigint x equal to integer y?
84// function greater(x,y) //is x>y? (x and y are nonnegative bigInts)
85// function greaterShift(x,y,shift)//is (x <<(shift*bpe)) > y?
86// function isZero(x) //is the bigInt x equal to zero?
87// function millerRabin(x,b) //does one round of Miller-Rabin base integer b say that bigInt x is possibly prime (as opposed to definitely composite)?
88// function modInt(x,n) //return x mod n for bigInt x and integer n.
89// function negative(x) //is bigInt x negative?
90//
91// The following functions do not modify their inputs, but allocate memory and call functions with underscores
92//
93// function add(x,y) //return (x+y) for bigInts x and y.
94// function addInt(x,n) //return (x+n) where x is a bigInt and n is an integer.
95// function expand(x,n) //return a copy of x with at least n elements, adding leading zeros if needed
96// function inverseMod(x,n) //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
97// function mod(x,n) //return a new bigInt equal to (x mod n) for bigInts x and n.
98// function mult(x,y) //return x*y for bigInts x and y. This is faster when y<x.
99// function multMod(x,y,n) //return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
100// function powMod(x,y,n) //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
101// function randTruePrime(k) //return a new, random, k-bit, true prime using Maurer's algorithm.
102// function sub(x,y) //return (x-y) for bigInts x and y. Negative answers will be 2s complement
103//
104// The following functions write a bigInt result to one of the parameters, but
105// the result is never bigger than the original, so there can't be overflow problems:
106//
107// function divInt_(x,n) //do x=floor(x/n) for bigInt x and integer n, and return the remainder
108// function GCD_(x,y) //set x to the greatest common divisor of bigInts x and y, (y is destroyed).
109// function halve_(x) //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
110// function mod_(x,n) //do x=x mod n for bigInts x and n.
111// function rightShift_(x,n) //right shift bigInt x by n bits. 0 <= n < bpe.
112//
113// The following functions write a bigInt result to one of the parameters. The caller is responsible for
114// ensuring it is large enough to hold the result.
115//
116// function addInt_(x,n) //do x=x+n where x is a bigInt and n is an integer
117// function add_(x,y) //do x=x+y for bigInts x and y
118// function addShift_(x,y,ys) //do x=x+(y<<(ys*bpe))
119// function copy_(x,y) //do x=y on bigInts x and y
120// function copyInt_(x,n) //do x=n on bigInt x and integer n
121// function carry_(x) //do carries and borrows so each element of the bigInt x fits in bpe bits.
122// function divide_(x,y,q,r) //divide_ x by y giving quotient q and remainder r
123// function eGCD_(x,y,d,a,b) //sets a,b,d to positive big integers such that d = GCD_(x,y) = a*x-b*y
124// function inverseMod_(x,n) //do x=x**(-1) mod n, for bigInts x and n. Returns 1 (0) if inverse does (doesn't) exist
125// function inverseModInt_(x,n) //return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
126// function leftShift_(x,n) //left shift bigInt x by n bits. n<bpe.
127// function linComb_(x,y,a,b) //do x=a*x+b*y for bigInts x and y and integers a and b
128// function linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys
129// function mont_(x,y,n,np) //Montgomery multiplication (see comments where the function is defined)
130// function mult_(x,y) //do x=x*y for bigInts x and y.
131// function multInt_(x,n) //do x=x*n where x is a bigInt and n is an integer.
132// function multMod_(x,y,n) //do x=x*y mod n for bigInts x,y,n.
133// function powMod_(x,y,n) //do x=x**y mod n, where x,y,n are bigInts (n is odd) and ** is exponentiation. 0**0=1.
134// function randBigInt_(b,n,s) //do b = an n-bit random BigInt. if s=1, then nth bit (most significant bit) is set to 1. n>=1.
135// function randTruePrime_(ans,k) //do ans = a random k-bit true random prime (not just probable prime) with 1 in the msb.
136// function squareMod_(x,n) //do x=x*x mod n for bigInts x,n
137// function sub_(x,y) //do x=x-y for bigInts x and y. Negative answers will be 2s complement.
138// function subShift_(x,y,ys) //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement.
139//
140// The following functions are based on algorithms from the _Handbook of Applied Cryptography_
141// powMod_() = algorithm 14.94, Montgomery exponentiation
142// eGCD_,inverseMod_() = algorithm 14.61, Binary extended GCD_
143// GCD_() = algorothm 14.57, Lehmer's algorithm
144// mont_() = algorithm 14.36, Montgomery multiplication
145// divide_() = algorithm 14.20 Multiple-precision division
146// squareMod_() = algorithm 14.16 Multiple-precision squaring
147// randTruePrime_() = algorithm 4.62, Maurer's algorithm
148// millerRabin() = algorithm 4.24, Miller-Rabin algorithm
149//
150// Profiling shows:
151// randTruePrime_() spends:
152// 10% of its time in calls to powMod_()
153// 85% of its time in calls to millerRabin()
154// millerRabin() spends:
155// 99% of its time in calls to powMod_() (always with a base of 2)
156// powMod_() spends:
157// 94% of its time in calls to mont_() (almost always with x==y)
158//
159// This suggests there are several ways to speed up this library slightly:
160// - convert powMod_ to use a Montgomery form of k-ary window (or maybe a Montgomery form of sliding window)
161// -- this should especially focus on being fast when raising 2 to a power mod n
162// - convert randTruePrime_() to use a minimum r of 1/3 instead of 1/2 with the appropriate change to the test
163// - tune the parameters in randTruePrime_(), including c, m, and recLimit
164// - speed up the single loop in mont_() that takes 95% of the runtime, perhaps by reducing checking
165// within the loop when all the parameters are the same length.
166//
167// There are several ideas that look like they wouldn't help much at all:
168// - replacing trial division in randTruePrime_() with a sieve (that speeds up something taking almost no time anyway)
169// - increase bpe from 15 to 30 (that would help if we had a 32*32->64 multiplier, but not with JavaScript's 32*32->32)
170// - speeding up mont_(x,y,n,np) when x==y by doing a non-modular, non-Montgomery square
171// followed by a Montgomery reduction. The intermediate answer will be twice as long as x, so that
172// method would be slower. This is unfortunate because the code currently spends almost all of its time
173// doing mont_(x,x,...), both for randTruePrime_() and powMod_(). A faster method for Montgomery squaring
174// would have a large impact on the speed of randTruePrime_() and powMod_(). HAC has a couple of poorly-worded
175// sentences that seem to imply it's faster to do a non-modular square followed by a single
176// Montgomery reduction, but that's obviously wrong.
177////////////////////////////////////////////////////////////////////////////////////////
178
179//globals
180bpe=0; //bits stored per array element
181mask=0; //AND this with an array element to chop it down to bpe bits
182radix=mask+1; //equals 2^bpe. A single 1 bit to the left of the last bit of mask.
183
184//the digits for converting to different bases
185digitsStr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-';
186
187//initialize the global variables
188for (bpe=0; (1<<(bpe+1)) > (1<<bpe); bpe++); //bpe=number of bits in the mantissa on this platform
189bpe>>=1; //bpe=number of bits in one element of the array representing the bigInt
190mask=(1<<bpe)-1; //AND the mask with an integer to get its bpe least significant bits
191radix=mask+1; //2^bpe. a single 1 bit to the left of the first bit of mask
192one=int2bigInt(1,1,1); //constant used in powMod_()
193
194//the following global variables are scratchpad memory to
195//reduce dynamic memory allocation in the inner loop
196t=new Array(0);
197ss=t; //used in mult_()
198s0=t; //used in multMod_(), squareMod_()
199s1=t; //used in powMod_(), multMod_(), squareMod_()
200s2=t; //used in powMod_(), multMod_()
201s3=t; //used in powMod_()
202s4=t; s5=t; //used in mod_()
203s6=t; //used in bigInt2str()
204s7=t; //used in powMod_()
205T=t; //used in GCD_()
206sa=t; //used in mont_()
207mr_x1=t; mr_r=t; mr_a=t; //used in millerRabin()
208eg_v=t; eg_u=t; eg_A=t; eg_B=t; eg_C=t; eg_D=t; //used in eGCD_(), inverseMod_()
209md_q1=t; md_q2=t; md_q3=t; md_r=t; md_r1=t; md_r2=t; md_tt=t; //used in mod_()
210
211primes=t; pows=t; s_i=t; s_i2=t; s_R=t; s_rm=t; s_q=t; s_n1=t;
212 s_a=t; s_r2=t; s_n=t; s_b=t; s_d=t; s_x1=t; s_x2=t, s_aa=t; //used in randTruePrime_()
213
214////////////////////////////////////////////////////////////////////////////////////////
215
216//return array of all primes less than integer n
217function findPrimes(n) {
218 var i,s,p,ans;
219 s=new Array(n);
220 for (i=0;i<n;i++)
221 s[i]=0;
222 s[0]=2;
223 p=0; //first p elements of s are primes, the rest are a sieve
224 for(;s[p]<n;) { //s[p] is the pth prime
225 for(i=s[p]*s[p]; i<n; i+=s[p]) //mark multiples of s[p]
226 s[i]=1;
227 p++;
228 s[p]=s[p-1]+1;
229 for(; s[p]<n && s[s[p]]; s[p]++); //find next prime (where s[p]==0)
230 }
231 ans=new Array(p);
232 for(i=0;i<p;i++)
233 ans[i]=s[i];
234 return ans;
235}
236
237//does a single round of Miller-Rabin base b consider x to be a possible prime?
238//x is a bigInt, and b is an integer
239function millerRabin(x,b) {
240 var i,j,k,s;
241
242 if (mr_x1.length!=x.length) {
243 mr_x1=dup(x);
244 mr_r=dup(x);
245 mr_a=dup(x);
246 }
247
248 copyInt_(mr_a,b);
249 copy_(mr_r,x);
250 copy_(mr_x1,x);
251
252 addInt_(mr_r,-1);
253 addInt_(mr_x1,-1);
254
255 //s=the highest power of two that divides mr_r
256 k=0;
257 for (i=0;i<mr_r.length;i++)
258 for (j=1;j<mask;j<<=1)
259 if (x[i] & j) {
260 s=(k<mr_r.length+bpe ? k : 0);
261 i=mr_r.length;
262 j=mask;
263 } else
264 k++;
265
266 if (s)
267 rightShift_(mr_r,s);
268
269 powMod_(mr_a,mr_r,x);
270
271 if (!equalsInt(mr_a,1) && !equals(mr_a,mr_x1)) {
272 j=1;
273 while (j<=s-1 && !equals(mr_a,mr_x1)) {
274 squareMod_(mr_a,x);
275 if (equalsInt(mr_a,1)) {
276 return 0;
277 }
278 j++;
279 }
280 if (!equals(mr_a,mr_x1)) {
281 return 0;
282 }
283 }
284 return 1;
285}
286
287//returns how many bits long the bigInt is, not counting leading zeros.
288function bitSize(x) {
289 var j,z,w;
290 for (j=x.length-1; (x[j]==0) && (j>0); j--);
291 for (z=0,w=x[j]; w; (w>>=1),z++);
292 z+=bpe*j;
293 return z;
294}
295
296//return a copy of x with at least n elements, adding leading zeros if needed
297function expand(x,n) {
298 var ans=int2bigInt(0,(x.length>n ? x.length : n)*bpe,0);
299 copy_(ans,x);
300 return ans;
301}
302
303//return a k-bit true random prime using Maurer's algorithm.
304function randTruePrime(k) {
305 var ans=int2bigInt(0,k,0);
306 randTruePrime_(ans,k);
307 return trim(ans,1);
308}
309
310//return a new bigInt equal to (x mod n) for bigInts x and n.
311function mod(x,n) {
312 var ans=dup(x);
313 mod_(ans,n);
314 return trim(ans,1);
315}
316
317//return (x+n) where x is a bigInt and n is an integer.
318function addInt(x,n) {
319 var ans=expand(x,x.length+1);
320 addInt_(ans,n);
321 return trim(ans,1);
322}
323
324//return x*y for bigInts x and y. This is faster when y<x.
325function mult(x,y) {
326 var ans=expand(x,x.length+y.length);
327 mult_(ans,y);
328 return trim(ans,1);
329}
330
331//return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
332function powMod(x,y,n) {
333 var ans=expand(x,n.length);
334 powMod_(ans,trim(y,2),trim(n,2),0); //this should work without the trim, but doesn't
335 return trim(ans,1);
336}
337
338//return (x-y) for bigInts x and y. Negative answers will be 2s complement
339function sub(x,y) {
340 var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
341 sub_(ans,y);
342 return trim(ans,1);
343}
344
345//return (x+y) for bigInts x and y.
346function add(x,y) {
347 var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
348 add_(ans,y);
349 return trim(ans,1);
350}
351
352//return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
353function inverseMod(x,n) {
354 var ans=expand(x,n.length);
355 var s;
356 s=inverseMod_(ans,n);
357 return s ? trim(ans,1) : null;
358}
359
360//return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
361function multMod(x,y,n) {
362 var ans=expand(x,n.length);
363 multMod_(ans,y,n);
364 return trim(ans,1);
365}
366
367//generate a k-bit true random prime using Maurer's algorithm,
368//and put it into ans. The bigInt ans must be large enough to hold it.
369function randTruePrime_(ans,k) {
370 var c,m,pm,dd,j,r,B,divisible,z,zz,recSize;
371
372 if (primes.length==0)
373 primes=findPrimes(30000); //check for divisibility by primes <=30000
374
375 if (pows.length==0) {
376 pows=new Array(512);
377 for (j=0;j<512;j++) {
378 pows[j]=Math.pow(2,j/511.-1.);
379 }
380 }
381
382 //c and m should be tuned for a particular machine and value of k, to maximize speed
383 //this was: c=primes[primes.length-1]/k/k; //check using all the small primes. (c=0.1 in HAC)
384 c=0.1;
385 m=20; //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
386 recLimit=20; /*must be at least 2 (was 29)*/ //stop recursion when k <=recLimit
387
388 if (s_i2.length!=ans.length) {
389 s_i2=dup(ans);
390 s_R =dup(ans);
391 s_n1=dup(ans);
392 s_r2=dup(ans);
393 s_d =dup(ans);
394 s_x1=dup(ans);
395 s_x2=dup(ans);
396 s_b =dup(ans);
397 s_n =dup(ans);
398 s_i =dup(ans);
399 s_rm=dup(ans);
400 s_q =dup(ans);
401 s_a =dup(ans);
402 s_aa=dup(ans);
403 }
404
405 if (k <= recLimit) { //generate small random primes by trial division up to its square root
406 pm=(1<<((k+2)>>1))-1; //pm is binary number with all ones, just over sqrt(2^k)
407 copyInt_(ans,0);
408 for (dd=1;dd;) {
409 dd=0;
410 ans[0]= 1 | (1<<(k-1)) | Math.floor(Math.random()*(1<<k)); //random, k-bit, odd integer, with msb 1
411 for (j=1;(j<primes.length) && ((primes[j]&pm)==primes[j]);j++) { //trial division by all primes 3...sqrt(2^k)
412 if (0==(ans[0]%primes[j])) {
413 dd=1;
414 break;
415 }
416 }
417 }
418 carry_(ans);
419 return;
420 }
421
422 B=c*k*k; //try small primes up to B (or all the primes[] array if the largest is less than B).
423 if (k>2*m) //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
424 for (r=1; k-k*r<=m; )
425 r=pows[Math.floor(Math.random()*512)]; //r=Math.pow(2,Math.random()-1);
426 else
427 r=.5;
428
429 //simulation suggests the more complex algorithm using r=.333 is only slightly faster.
430
431 recSize=Math.floor(r*k)+1;
432
433 randTruePrime_(s_q,recSize);
434 copyInt_(s_i2,0);
435 s_i2[Math.floor((k-2)/bpe)] |= (1<<((k-2)%bpe)); //s_i2=2^(k-2)
436 divide_(s_i2,s_q,s_i,s_rm); //s_i=floor((2^(k-1))/(2q))
437
438 z=bitSize(s_i);
439
440 for (;;) {
441 for (;;) { //generate z-bit numbers until one falls in the range [0,s_i-1]
442 randBigInt_(s_R,z,0);
443 if (greater(s_i,s_R))
444 break;
445 } //now s_R is in the range [0,s_i-1]
446 addInt_(s_R,1); //now s_R is in the range [1,s_i]
447 add_(s_R,s_i); //now s_R is in the range [s_i+1,2*s_i]
448
449 copy_(s_n,s_q);
450 mult_(s_n,s_R);
451 multInt_(s_n,2);
452 addInt_(s_n,1); //s_n=2*s_R*s_q+1
453
454 copy_(s_r2,s_R);
455 multInt_(s_r2,2); //s_r2=2*s_R
456
457 //check s_n for divisibility by small primes up to B
458 for (divisible=0,j=0; (j<primes.length) && (primes[j]<B); j++)
459 if (modInt(s_n,primes[j])==0) {
460 divisible=1;
461 break;
462 }
463
464 if (!divisible) //if it passes small primes check, then try a single Miller-Rabin base 2
465 if (!millerRabin(s_n,2)) //this line represents 75% of the total runtime for randTruePrime_
466 divisible=1;
467
468 if (!divisible) { //if it passes that test, continue checking s_n
469 addInt_(s_n,-3);
470 for (j=s_n.length-1;(s_n[j]==0) && (j>0); j--); //strip leading zeros
471 for (zz=0,w=s_n[j]; w; (w>>=1),zz++);
472 zz+=bpe*j; //zz=number of bits in s_n, ignoring leading zeros
473 for (;;) { //generate z-bit numbers until one falls in the range [0,s_n-1]
474 randBigInt_(s_a,zz,0);
475 if (greater(s_n,s_a))
476 break;
477 } //now s_a is in the range [0,s_n-1]
478 addInt_(s_n,3); //now s_a is in the range [0,s_n-4]
479 addInt_(s_a,2); //now s_a is in the range [2,s_n-2]
480 copy_(s_b,s_a);
481 copy_(s_n1,s_n);
482 addInt_(s_n1,-1);
483 powMod_(s_b,s_n1,s_n); //s_b=s_a^(s_n-1) modulo s_n
484 addInt_(s_b,-1);
485 if (isZero(s_b)) {
486 copy_(s_b,s_a);
487 powMod_(s_b,s_r2,s_n);
488 addInt_(s_b,-1);
489 copy_(s_aa,s_n);
490 copy_(s_d,s_b);
491 GCD_(s_d,s_n); //if s_b and s_n are relatively prime, then s_n is a prime
492 if (equalsInt(s_d,1)) {
493 copy_(ans,s_aa);
494 return; //if we've made it this far, then s_n is absolutely guaranteed to be prime
495 }
496 }
497 }
498 }
499}
500
501//set b to an n-bit random BigInt. If s=1, then nth bit (most significant bit) is set to 1.
502//array b must be big enough to hold the result. Must have n>=1
503function randBigInt_(b,n,s) {
504 var i,a;
505 for (i=0;i<b.length;i++)
506 b[i]=0;
507 a=Math.floor((n-1)/bpe)+1; //# array elements to hold the BigInt
508 for (i=0;i<a;i++) {
509 b[i]=Math.floor(Math.random()*(1<<(bpe-1)));
510 }
511 b[a-1] &= (2<<((n-1)%bpe))-1;
512 if (s)
513 b[a-1] |= (1<<((n-1)%bpe));
514}
515
516//set x to the greatest common divisor of x and y.
517//x,y are bigInts with the same number of elements. y is destroyed.
518function GCD_(x,y) {
519 var i,xp,yp,A,B,C,D,q,sing;
520 if (T.length!=x.length)
521 T=dup(x);
522
523 sing=1;
524 while (sing) { //while y has nonzero elements other than y[0]
525 sing=0;
526 for (i=1;i<y.length;i++) //check if y has nonzero elements other than 0
527 if (y[i]) {
528 sing=1;
529 break;
530 }
531 if (!sing) break; //quit when y all zero elements except possibly y[0]
532
533 for (i=x.length;!x[i] && i>=0;i--); //find most significant element of x
534 xp=x[i];
535 yp=y[i];
536 A=1; B=0; C=0; D=1;
537 while ((yp+C) && (yp+D)) {
538 q =Math.floor((xp+A)/(yp+C));
539 qp=Math.floor((xp+B)/(yp+D));
540 if (q!=qp)
541 break;
542 t= A-q*C; A=C; C=t; // do (A,B,xp, C,D,yp) = (C,D,yp, A,B,xp) - q*(0,0,0, C,D,yp)
543 t= B-q*D; B=D; D=t;
544 t=xp-q*yp; xp=yp; yp=t;
545 }
546 if (B) {
547 copy_(T,x);
548 linComb_(x,y,A,B); //x=A*x+B*y
549 linComb_(y,T,D,C); //y=D*y+C*T
550 } else {
551 mod_(x,y);
552 copy_(T,x);
553 copy_(x,y);
554 copy_(y,T);
555 }
556 }
557 if (y[0]==0)
558 return;
559 t=modInt(x,y[0]);
560 copyInt_(x,y[0]);
561 y[0]=t;
562 while (y[0]) {
563 x[0]%=y[0];
564 t=x[0]; x[0]=y[0]; y[0]=t;
565 }
566}
567
568//do x=x**(-1) mod n, for bigInts x and n.
569//If no inverse exists, it sets x to zero and returns 0, else it returns 1.
570//The x array must be at least as large as the n array.
571function inverseMod_(x,n) {
572 var k=1+2*Math.max(x.length,n.length);
573
574 if(!(x[0]&1) && !(n[0]&1)) { //if both inputs are even, then inverse doesn't exist
575 copyInt_(x,0);
576 return 0;
577 }
578
579 if (eg_u.length!=k) {
580 eg_u=new Array(k);
581 eg_v=new Array(k);
582 eg_A=new Array(k);
583 eg_B=new Array(k);
584 eg_C=new Array(k);
585 eg_D=new Array(k);
586 }
587
588 copy_(eg_u,x);
589 copy_(eg_v,n);
590 copyInt_(eg_A,1);
591 copyInt_(eg_B,0);
592 copyInt_(eg_C,0);
593 copyInt_(eg_D,1);
594 for (;;) {
595 while(!(eg_u[0]&1)) { //while eg_u is even
596 halve_(eg_u);
597 if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if eg_A==eg_B==0 mod 2
598 halve_(eg_A);
599 halve_(eg_B);
600 } else {
601 add_(eg_A,n); halve_(eg_A);
602 sub_(eg_B,x); halve_(eg_B);
603 }
604 }
605
606 while (!(eg_v[0]&1)) { //while eg_v is even
607 halve_(eg_v);
608 if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if eg_C==eg_D==0 mod 2
609 halve_(eg_C);
610 halve_(eg_D);
611 } else {
612 add_(eg_C,n); halve_(eg_C);
613 sub_(eg_D,x); halve_(eg_D);
614 }
615 }
616
617 if (!greater(eg_v,eg_u)) { //eg_v <= eg_u
618 sub_(eg_u,eg_v);
619 sub_(eg_A,eg_C);
620 sub_(eg_B,eg_D);
621 } else { //eg_v > eg_u
622 sub_(eg_v,eg_u);
623 sub_(eg_C,eg_A);
624 sub_(eg_D,eg_B);
625 }
626
627 if (equalsInt(eg_u,0)) {
628 if (negative(eg_C)) //make sure answer is nonnegative
629 add_(eg_C,n);
630 copy_(x,eg_C);
631
632 if (!equalsInt(eg_v,1)) { //if GCD_(x,n)!=1, then there is no inverse
633 copyInt_(x,0);
634 return 0;
635 }
636 return 1;
637 }
638 }
639}
640
641//return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
642function inverseModInt_(x,n) {
643 var a=1,b=0,t;
644 for (;;) {
645 if (x==1) return a;
646 if (x==0) return 0;
647 b-=a*Math.floor(n/x);
648 n%=x;
649
650 if (n==1) return b; //to avoid negatives, change this b to n-b, and each -= to +=
651 if (n==0) return 0;
652 a-=b*Math.floor(x/n);
653 x%=n;
654 }
655}
656
657//Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that:
658// v = GCD_(x,y) = a*x-b*y
659//The bigInts v, a, b, must have exactly as many elements as the larger of x and y.
660function eGCD_(x,y,v,a,b) {
661 var g=0;
662 var k=Math.max(x.length,y.length);
663 if (eg_u.length!=k) {
664 eg_u=new Array(k);
665 eg_A=new Array(k);
666 eg_B=new Array(k);
667 eg_C=new Array(k);
668 eg_D=new Array(k);
669 }
670 while(!(x[0]&1) && !(y[0]&1)) { //while x and y both even
671 halve_(x);
672 halve_(y);
673 g++;
674 }
675 copy_(eg_u,x);
676 copy_(v,y);
677 copyInt_(eg_A,1);
678 copyInt_(eg_B,0);
679 copyInt_(eg_C,0);
680 copyInt_(eg_D,1);
681 for (;;) {
682 while(!(eg_u[0]&1)) { //while u is even
683 halve_(eg_u);
684 if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if A==B==0 mod 2
685 halve_(eg_A);
686 halve_(eg_B);
687 } else {
688 add_(eg_A,y); halve_(eg_A);
689 sub_(eg_B,x); halve_(eg_B);
690 }
691 }
692
693 while (!(v[0]&1)) { //while v is even
694 halve_(v);
695 if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if C==D==0 mod 2
696 halve_(eg_C);
697 halve_(eg_D);
698 } else {
699 add_(eg_C,y); halve_(eg_C);
700 sub_(eg_D,x); halve_(eg_D);
701 }
702 }
703
704 if (!greater(v,eg_u)) { //v<=u
705 sub_(eg_u,v);
706 sub_(eg_A,eg_C);
707 sub_(eg_B,eg_D);
708 } else { //v>u
709 sub_(v,eg_u);
710 sub_(eg_C,eg_A);
711 sub_(eg_D,eg_B);
712 }
713 if (equalsInt(eg_u,0)) {
714 if (negative(eg_C)) { //make sure a (C)is nonnegative
715 add_(eg_C,y);
716 sub_(eg_D,x);
717 }
718 multInt_(eg_D,-1); ///make sure b (D) is nonnegative
719 copy_(a,eg_C);
720 copy_(b,eg_D);
721 leftShift_(v,g);
722 return;
723 }
724 }
725}
726
727
728//is bigInt x negative?
729function negative(x) {
730 return ((x[x.length-1]>>(bpe-1))&1);
731}
732
733
734//is (x << (shift*bpe)) > y?
735//x and y are nonnegative bigInts
736//shift is a nonnegative integer
737function greaterShift(x,y,shift) {
738 var kx=x.length, ky=y.length;
739 k=((kx+shift)<ky) ? (kx+shift) : ky;
740 for (i=ky-1-shift; i<kx && i>=0; i++)
741 if (x[i]>0)
742 return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger
743 for (i=kx-1+shift; i<ky; i++)
744 if (y[i]>0)
745 return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger
746 for (i=k-1; i>=shift; i--)
747 if (x[i-shift]>y[i]) return 1;
748 else if (x[i-shift]<y[i]) return 0;
749 return 0;
750}
751
752//is x > y? (x and y both nonnegative)
753function greater(x,y) {
754 var i;
755 var k=(x.length<y.length) ? x.length : y.length;
756
757 for (i=x.length;i<y.length;i++)
758 if (y[i])
759 return 0; //y has more digits
760
761 for (i=y.length;i<x.length;i++)
762 if (x[i])
763 return 1; //x has more digits
764
765 for (i=k-1;i>=0;i--)
766 if (x[i]>y[i])
767 return 1;
768 else if (x[i]<y[i])
769 return 0;
770 return 0;
771}
772
773//divide_ x by y giving quotient q and remainder r. (q=floor(x/y), r=x mod y). All 4 are bigints.
774//x must have at least one leading zero element.
775//y must be nonzero.
776//q and r must be arrays that are exactly the same length as x.
777//the x array must have at least as many elements as y.
778function divide_(x,y,q,r) {
779 var kx, ky;
780 var i,j,y1,y2,c,a,b;
781 copy_(r,x);
782 for (ky=y.length;y[ky-1]==0;ky--); //kx,ky is number of elements in x,y, not including leading zeros
783 for (kx=r.length;r[kx-1]==0 && kx>ky;kx--);
784
785 //normalize: ensure the most significant element of y has its highest bit set
786 b=y[ky-1];
787 for (a=0; b; a++)
788 b>>=1;
789 a=bpe-a; //a is how many bits to shift so that the high order bit of y is leftmost in its array element
790 leftShift_(y,a); //multiply both by 1<<a now, then divide_ both by that at the end
791 leftShift_(r,a);
792
793 copyInt_(q,0); // q=0
794 while (!greaterShift(y,r,kx-ky)) { // while (leftShift_(y,kx-ky) <= r) {
795 subShift_(r,y,kx-ky); // r=r-leftShift_(y,kx-ky)
796 q[kx-ky]++; // q[kx-ky]++;
797 } // }
798
799 for (i=kx-1; i>=ky; i--) {
800 if (r[i]==y[ky-1])
801 q[i-ky]=mask;
802 else
803 q[i-ky]=Math.floor((r[i]*radix+r[i-1])/y[ky-1]);
804
805 //The following for(;;) loop is equivalent to the commented while loop,
806 //except that the uncommented version avoids overflow.
807 //The commented loop comes from HAC, which assumes r[-1]==y[-1]==0
808 // while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2])
809 // q[i-ky]--;
810 for (;;) {
811 y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
812 c=y2>>bpe;
813 y2=y2 & mask;
814 y1=c+q[i-ky]*y[ky-1];
815 c=y1>>bpe;
816 y1=y1 & mask;
817
818 if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i])
819 q[i-ky]--;
820 else
821 break;
822 }
823
824 linCombShift_(r,y,-q[i-ky],i-ky); //r=r-q[i-ky]*leftShift_(y,i-ky)
825 if (negative(r)) {
826 addShift_(r,y,i-ky); //r=r+leftShift_(y,i-ky)
827 q[i-ky]--;
828 }
829 }
830
831 rightShift_(y,a); //undo the normalization step
832 rightShift_(r,a); //undo the normalization step
833}
834
835//do carries and borrows so each element of the bigInt x fits in bpe bits.
836function carry_(x) {
837 var i,k,c,b;
838 k=x.length;
839 c=0;
840 for (i=0;i<k;i++) {
841 c+=x[i];
842 b=0;
843 if (c<0) {
844 b=-(c>>bpe);
845 c+=b*radix;
846 }
847 x[i]=c & mask;
848 c=(c>>bpe)-b;
849 }
850}
851
852//return x mod n for bigInt x and integer n.
853function modInt(x,n) {
854 var i,c=0;
855 for (i=x.length-1; i>=0; i--)
856 c=(c*radix+x[i])%n;
857 return c;
858}
859
860//convert the integer t into a bigInt with at least the given number of bits.
861//the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word)
862//Pad the array with leading zeros so that it has at least minSize elements.
863//There will always be at least one leading 0 element.
864function int2bigInt(t,bits,minSize) {
865 var i,k;
866 k=Math.ceil(bits/bpe)+1;
867 k=minSize>k ? minSize : k;
868 buff=new Array(k);
869 copyInt_(buff,t);
870 return buff;
871}
872
873//return the bigInt given a string representation in a given base.
874//Pad the array with leading zeros so that it has at least minSize elements.
875//If base=-1, then it reads in a space-separated list of array elements in decimal.
876//The array will always have at least one leading zero, unless base=-1.
877function str2bigInt(s,base,minSize) {
878 var d, i, j, x, y, kk;
879 var k=s.length;
880 if (base==-1) { //comma-separated list of array elements in decimal
881 x=new Array(0);
882 for (;;) {
883 y=new Array(x.length+1);
884 for (i=0;i<x.length;i++)
885 y[i+1]=x[i];
886 y[0]=parseInt(s,10);
887 x=y;
888 d=s.indexOf(',',0);
889 if (d<1)
890 break;
891 s=s.substring(d+1);
892 if (s.length==0)
893 break;
894 }
895 if (x.length<minSize) {
896 y=new Array(minSize);
897 copy_(y,x);
898 return y;
899 }
900 return x;
901 }
902
903 x=int2bigInt(0,base*k,0);
904 for (i=0;i<k;i++) {
905 d=digitsStr.indexOf(s.substring(i,i+1),0);
906 if (base<=36 && d>=36) //convert lowercase to uppercase if base<=36
907 d-=26;
908 if (d<base && d>=0) { //ignore illegal characters
909 multInt_(x,base);
910 addInt_(x,d);
911 }
912 }
913
914 for (k=x.length;k>0 && !x[k-1];k--); //strip off leading zeros
915 k=minSize>k+1 ? minSize : k+1;
916 y=new Array(k);
917 kk=k<x.length ? k : x.length;
918 for (i=0;i<kk;i++)
919 y[i]=x[i];
920 for (;i<k;i++)
921 y[i]=0;
922 return y;
923}
924
925//is bigint x equal to integer y?
926//y must have less than bpe bits
927function equalsInt(x,y) {
928 var i;
929 if (x[0]!=y)
930 return 0;
931 for (i=1;i<x.length;i++)
932 if (x[i])
933 return 0;
934 return 1;
935}
936
937//are bigints x and y equal?
938//this works even if x and y are different lengths and have arbitrarily many leading zeros
939function equals(x,y) {
940 var i;
941 var k=x.length<y.length ? x.length : y.length;
942 for (i=0;i<k;i++)
943 if (x[i]!=y[i])
944 return 0;
945 if (x.length>y.length) {
946 for (;i<x.length;i++)
947 if (x[i])
948 return 0;
949 } else {
950 for (;i<y.length;i++)
951 if (y[i])
952 return 0;
953 }
954 return 1;
955}
956
957//is the bigInt x equal to zero?
958function isZero(x) {
959 var i;
960 for (i=0;i<x.length;i++)
961 if (x[i])
962 return 0;
963 return 1;
964}
965
966//convert a bigInt into a string in a given base, from base 2 up to base 95.
967//Base -1 prints the contents of the array representing the number.
968function bigInt2str(x,base) {
969 var i,t,s="";
970
971 if (s6.length!=x.length)
972 s6=dup(x);
973 else
974 copy_(s6,x);
975
976 if (base==-1) { //return the list of array contents
977 for (i=x.length-1;i>0;i--)
978 s+=x[i]+',';
979 s+=x[0];
980 }
981 else { //return it in the given base
982 while (!isZero(s6)) {
983 t=divInt_(s6,base); //t=s6 % base; s6=floor(s6/base);
984 s=digitsStr.substring(t,t+1)+s;
985 }
986 }
987 if (s.length==0)
988 s="0";
989 return s;
990}
991
992//returns a duplicate of bigInt x
993function dup(x) {
994 var i;
995 buff=new Array(x.length);
996 copy_(buff,x);
997 return buff;
998}
999
1000//do x=y on bigInts x and y. x must be an array at least as big as y (not counting the leading zeros in y).
1001function copy_(x,y) {
1002 var i;
1003 var k=x.length<y.length ? x.length : y.length;
1004 for (i=0;i<k;i++)
1005 x[i]=y[i];
1006 for (i=k;i<x.length;i++)
1007 x[i]=0;
1008}
1009
1010//do x=y on bigInt x and integer y.
1011function copyInt_(x,n) {
1012 var i,c;
1013 for (c=n,i=0;i<x.length;i++) {
1014 x[i]=c & mask;
1015 c>>=bpe;
1016 }
1017}
1018
1019//do x=x+n where x is a bigInt and n is an integer.
1020//x must be large enough to hold the result.
1021function addInt_(x,n) {
1022 var i,k,c,b;
1023 x[0]+=n;
1024 k=x.length;
1025 c=0;
1026 for (i=0;i<k;i++) {
1027 c+=x[i];
1028 b=0;
1029 if (c<0) {
1030 b=-(c>>bpe);
1031 c+=b*radix;
1032 }
1033 x[i]=c & mask;
1034 c=(c>>bpe)-b;
1035 if (!c) return; //stop carrying as soon as the carry_ is zero
1036 }
1037}
1038
1039//right shift bigInt x by n bits. 0 <= n < bpe.
1040function rightShift_(x,n) {
1041 var i;
1042 var k=Math.floor(n/bpe);
1043 if (k) {
1044 for (i=0;i<x.length-k;i++) //right shift x by k elements
1045 x[i]=x[i+k];
1046 for (;i<x.length;i++)
1047 x[i]=0;
1048 n%=bpe;
1049 }
1050 for (i=0;i<x.length-1;i++) {
1051 x[i]=mask & ((x[i+1]<<(bpe-n)) | (x[i]>>n));
1052 }
1053 x[i]>>=n;
1054}
1055
1056//do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
1057function halve_(x) {
1058 var i;
1059 for (i=0;i<x.length-1;i++) {
1060 x[i]=mask & ((x[i+1]<<(bpe-1)) | (x[i]>>1));
1061 }
1062 x[i]=(x[i]>>1) | (x[i] & (radix>>1)); //most significant bit stays the same
1063}
1064
1065//left shift bigInt x by n bits.
1066function leftShift_(x,n) {
1067 var i;
1068 var k=Math.floor(n/bpe);
1069 if (k) {
1070 for (i=x.length; i>=k; i--) //left shift x by k elements
1071 x[i]=x[i-k];
1072 for (;i>=0;i--)
1073 x[i]=0;
1074 n%=bpe;
1075 }
1076 if (!n)
1077 return;
1078 for (i=x.length-1;i>0;i--) {
1079 x[i]=mask & ((x[i]<<n) | (x[i-1]>>(bpe-n)));
1080 }
1081 x[i]=mask & (x[i]<<n);
1082}
1083
1084//do x=x*n where x is a bigInt and n is an integer.
1085//x must be large enough to hold the result.
1086function multInt_(x,n) {
1087 var i,k,c,b;
1088 if (!n)
1089 return;
1090 k=x.length;
1091 c=0;
1092 for (i=0;i<k;i++) {
1093 c+=x[i]*n;
1094 b=0;
1095 if (c<0) {
1096 b=-(c>>bpe);
1097 c+=b*radix;
1098 }
1099 x[i]=c & mask;
1100 c=(c>>bpe)-b;
1101 }
1102}
1103
1104//do x=floor(x/n) for bigInt x and integer n, and return the remainder
1105function divInt_(x,n) {
1106 var i,r=0,s;
1107 for (i=x.length-1;i>=0;i--) {
1108 s=r*radix+x[i];
1109 x[i]=Math.floor(s/n);
1110 r=s%n;
1111 }
1112 return r;
1113}
1114
1115//do the linear combination x=a*x+b*y for bigInts x and y, and integers a and b.
1116//x must be large enough to hold the answer.
1117function linComb_(x,y,a,b) {
1118 var i,c,k,kk;
1119 k=x.length<y.length ? x.length : y.length;
1120 kk=x.length;
1121 for (c=0,i=0;i<k;i++) {
1122 c+=a*x[i]+b*y[i];
1123 x[i]=c & mask;
1124 c>>=bpe;
1125 }
1126 for (i=k;i<kk;i++) {
1127 c+=a*x[i];
1128 x[i]=c & mask;
1129 c>>=bpe;
1130 }
1131}
1132
1133//do the linear combination x=a*x+b*(y<<(ys*bpe)) for bigInts x and y, and integers a, b and ys.
1134//x must be large enough to hold the answer.
1135function linCombShift_(x,y,b,ys) {
1136 var i,c,k,kk;
1137 k=x.length<ys+y.length ? x.length : ys+y.length;
1138 kk=x.length;
1139 for (c=0,i=ys;i<k;i++) {
1140 c+=x[i]+b*y[i-ys];
1141 x[i]=c & mask;
1142 c>>=bpe;
1143 }
1144 for (i=k;c && i<kk;i++) {
1145 c+=x[i];
1146 x[i]=c & mask;
1147 c>>=bpe;
1148 }
1149}
1150
1151//do x=x+(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
1152//x must be large enough to hold the answer.
1153function addShift_(x,y,ys) {
1154 var i,c,k,kk;
1155 k=x.length<ys+y.length ? x.length : ys+y.length;
1156 kk=x.length;
1157 for (c=0,i=ys;i<k;i++) {
1158 c+=x[i]+y[i-ys];
1159 x[i]=c & mask;
1160 c>>=bpe;
1161 }
1162 for (i=k;c && i<kk;i++) {
1163 c+=x[i];
1164 x[i]=c & mask;
1165 c>>=bpe;
1166 }
1167}
1168
1169//do x=x-(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
1170//x must be large enough to hold the answer.
1171function subShift_(x,y,ys) {
1172 var i,c,k,kk;
1173 k=x.length<ys+y.length ? x.length : ys+y.length;
1174 kk=x.length;
1175 for (c=0,i=ys;i<k;i++) {
1176 c+=x[i]-y[i-ys];
1177 x[i]=c & mask;
1178 c>>=bpe;
1179 }
1180 for (i=k;c && i<kk;i++) {
1181 c+=x[i];
1182 x[i]=c & mask;
1183 c>>=bpe;
1184 }
1185}
1186
1187//do x=x-y for bigInts x and y.
1188//x must be large enough to hold the answer.
1189//negative answers will be 2s complement
1190function sub_(x,y) {
1191 var i,c,k,kk;
1192 k=x.length<y.length ? x.length : y.length;
1193 for (c=0,i=0;i<k;i++) {
1194 c+=x[i]-y[i];
1195 x[i]=c & mask;
1196 c>>=bpe;
1197 }
1198 for (i=k;c && i<x.length;i++) {
1199 c+=x[i];
1200 x[i]=c & mask;
1201 c>>=bpe;
1202 }
1203}
1204
1205//do x=x+y for bigInts x and y.
1206//x must be large enough to hold the answer.
1207function add_(x,y) {
1208 var i,c,k,kk;
1209 k=x.length<y.length ? x.length : y.length;
1210 for (c=0,i=0;i<k;i++) {
1211 c+=x[i]+y[i];
1212 x[i]=c & mask;
1213 c>>=bpe;
1214 }
1215 for (i=k;c && i<x.length;i++) {
1216 c+=x[i];
1217 x[i]=c & mask;
1218 c>>=bpe;
1219 }
1220}
1221
1222//do x=x*y for bigInts x and y. This is faster when y<x.
1223function mult_(x,y) {
1224 var i;
1225 if (ss.length!=2*x.length)
1226 ss=new Array(2*x.length);
1227 copyInt_(ss,0);
1228 for (i=0;i<y.length;i++)
1229 if (y[i])
1230 linCombShift_(ss,x,y[i],i); //ss=1*ss+y[i]*(x<<(i*bpe))
1231 copy_(x,ss);
1232}
1233
1234//do x=x mod n for bigInts x and n.
1235function mod_(x,n) {
1236 if (s4.length!=x.length)
1237 s4=dup(x);
1238 else
1239 copy_(s4,x);
1240 if (s5.length!=x.length)
1241 s5=dup(x);
1242 divide_(s4,n,s5,x); //x = remainder of s4 / n
1243}
1244
1245//do x=x*y mod n for bigInts x,y,n.
1246//for greater speed, let y<x.
1247function multMod_(x,y,n) {
1248 var i;
1249 if (s0.length!=2*x.length)
1250 s0=new Array(2*x.length);
1251 copyInt_(s0,0);
1252 for (i=0;i<y.length;i++)
1253 if (y[i])
1254 linCombShift_(s0,x,y[i],i); //s0=1*s0+y[i]*(x<<(i*bpe))
1255 mod_(s0,n);
1256 copy_(x,s0);
1257}
1258
1259//do x=x*x mod n for bigInts x,n.
1260function squareMod_(x,n) {
1261 var i,j,d,c,kx,kn,k;
1262 for (kx=x.length; kx>0 && !x[kx-1]; kx--); //ignore leading zeros in x
1263 k=kx>n.length ? 2*kx : 2*n.length; //k=# elements in the product, which is twice the elements in the larger of x and n
1264 if (s0.length!=k)
1265 s0=new Array(k);
1266 copyInt_(s0,0);
1267 for (i=0;i<kx;i++) {
1268 c=s0[2*i]+x[i]*x[i];
1269 s0[2*i]=c & mask;
1270 c>>=bpe;
1271 for (j=i+1;j<kx;j++) {
1272 c=s0[i+j]+2*x[i]*x[j]+c;
1273 s0[i+j]=(c & mask);
1274 c>>=bpe;
1275 }
1276 s0[i+kx]=c;
1277 }
1278 mod_(s0,n);
1279 copy_(x,s0);
1280}
1281
1282//return x with exactly k leading zero elements
1283function trim(x,k) {
1284 var i,y;
1285 for (i=x.length; i>0 && !x[i-1]; i--);
1286 y=new Array(i+k);
1287 copy_(y,x);
1288 return y;
1289}
1290
1291//do x=x**y mod n, where x,y,n are bigInts and ** is exponentiation. 0**0=1.
1292//this is faster when n is odd. x usually needs to have as many elements as n.
1293function powMod_(x,y,n) {
1294 var k1,k2,kn,np;
1295 if(s7.length!=n.length)
1296 s7=dup(n);
1297
1298 //for even modulus, use a simple square-and-multiply algorithm,
1299 //rather than using the more complex Montgomery algorithm.
1300 if ((n[0]&1)==0) {
1301 copy_(s7,x);
1302 copyInt_(x,1);
1303 while(!equalsInt(y,0)) {
1304 if (y[0]&1)
1305 multMod_(x,s7,n);
1306 divInt_(y,2);
1307 squareMod_(s7,n);
1308 }
1309 return;
1310 }
1311
1312 //calculate np from n for the Montgomery multiplications
1313 copyInt_(s7,0);
1314 for (kn=n.length;kn>0 && !n[kn-1];kn--);
1315 np=radix-inverseModInt_(modInt(n,radix),radix);
1316 s7[kn]=1;
1317 multMod_(x ,s7,n); // x = x * 2**(kn*bp) mod n
1318
1319 if (s3.length!=x.length)
1320 s3=dup(x);
1321 else
1322 copy_(s3,x);
1323
1324 for (k1=y.length-1;k1>0 & !y[k1]; k1--); //k1=first nonzero element of y
1325 if (y[k1]==0) { //anything to the 0th power is 1
1326 copyInt_(x,1);
1327 return;
1328 }
1329 for (k2=1<<(bpe-1);k2 && !(y[k1] & k2); k2>>=1); //k2=position of first 1 bit in y[k1]
1330 for (;;) {
1331 if (!(k2>>=1)) { //look at next bit of y
1332 k1--;
1333 if (k1<0) {
1334 mont_(x,one,n,np);
1335 return;
1336 }
1337 k2=1<<(bpe-1);
1338 }
1339 mont_(x,x,n,np);
1340
1341 if (k2 & y[k1]) //if next bit is a 1
1342 mont_(x,s3,n,np);
1343 }
1344}
1345
1346//do x=x*y*Ri mod n for bigInts x,y,n,
1347// where Ri = 2**(-kn*bpe) mod n, and kn is the
1348// number of elements in the n array, not
1349// counting leading zeros.
1350//x must be large enough to hold the answer.
1351//It's OK if x and y are the same variable.
1352//must have:
1353// x,y < n
1354// n is odd
1355// np = -(n^(-1)) mod radix
1356function mont_(x,y,n,np) {
1357 var i,j,c,ui,t;
1358 var kn=n.length;
1359 var ky=y.length;
1360
1361 if (sa.length!=kn)
1362 sa=new Array(kn);
1363
1364 for (;kn>0 && n[kn-1]==0;kn--); //ignore leading zeros of n
1365 //this function sometimes gives wrong answers when the next line is uncommented
1366 //for (;ky>0 && y[ky-1]==0;ky--); //ignore leading zeros of y
1367
1368 copyInt_(sa,0);
1369
1370 //the following loop consumes 95% of the runtime for randTruePrime_() and powMod_() for large keys
1371 for (i=0; i<kn; i++) {
1372 t=sa[0]+x[i]*y[0];
1373 ui=((t & mask) * np) & mask; //the inner "& mask" is needed on Macintosh MSIE, but not windows MSIE
1374 c=(t+ui*n[0]) >> bpe;
1375 t=x[i];
1376
1377 //do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe
1378 for (j=1;j<ky;j++) {
1379 c+=sa[j]+t*y[j]+ui*n[j];
1380 sa[j-1]=c & mask;
1381 c>>=bpe;
1382 }
1383 for (;j<kn;j++) {
1384 c+=sa[j]+ui*n[j];
1385 sa[j-1]=c & mask;
1386 c>>=bpe;
1387 }
1388 sa[j-1]=c & mask;
1389 }
1390
1391 if (!greater(n,sa))
1392 sub_(sa,n);
1393 copy_(x,sa);
1394}
1395
1396
1397
1398
1399//#############################################################################
1400//#############################################################################
1401//#############################################################################
1402//#############################################################################
1403//#############################################################################
1404//#############################################################################
1405//#############################################################################
1406
1407
1408
1409
1410
1411//#############################################################################
1412
1413Clipperz.Crypto.BigInt = function (aValue, aBase) {
1414 varbase;
1415 varvalue;
1416
1417 if (typeof(aValue) == 'object') {
1418 this._internalValue = aValue;
1419 } else {
1420 if (typeof(aValue) == 'undefined') {
1421 value = "0";
1422 } else {
1423 value = aValue + "";
1424 }
1425
1426 if (typeof(aBase) == 'undefined') {
1427 base = 10;
1428 } else {
1429 base = aBase;
1430 }
1431
1432 this._internalValue = str2bigInt(value, base, 1, 1);
1433 }
1434
1435 return this;
1436}
1437
1438//=============================================================================
1439
1440MochiKit.Base.update(Clipperz.Crypto.BigInt.prototype, {
1441
1442 'clone': function() {
1443 return new Clipperz.Crypto.BigInt(this.internalValue());
1444 },
1445
1446 //-------------------------------------------------------------------------
1447
1448 'internalValue': function () {
1449 return this._internalValue;
1450 },
1451
1452 //-------------------------------------------------------------------------
1453
1454 'isBigInt': true,
1455
1456 //-------------------------------------------------------------------------
1457
1458 'toString': function(aBase) {
1459 return this.asString(aBase);
1460 },
1461
1462 //-------------------------------------------------------------------------
1463
1464 'asString': function (aBase, minimumLength) {
1465 varresult;
1466 varbase;
1467
1468 if (typeof(aBase) == 'undefined') {
1469 base = 10;
1470 } else {
1471 base = aBase;
1472 }
1473
1474 result = bigInt2str(this.internalValue(), base).toLowerCase();
1475
1476 if ((typeof(minimumLength) != 'undefined') && (result.length < minimumLength)) {
1477 var i, c;
1478 c = (minimumLength - result.length);
1479 for (i=0; i<c; i++) {
1480 result = '0' + result;
1481 }
1482 }
1483
1484 return result;
1485 },
1486
1487 //-------------------------------------------------------------------------
1488
1489 'asByteArray': function() {
1490 return new Clipperz.ByteArray("0x" + this.asString(16), 16);
1491 },
1492
1493 //-------------------------------------------------------------------------
1494
1495 'equals': function (aValue) {
1496 var result;
1497
1498 if (aValue.isBigInt) {
1499 result = equals(this.internalValue(), aValue.internalValue());
1500 } else if (typeof(aValue) == "number") {
1501 result = equalsInt(this.internalValue(), aValue);
1502 } else {
1503 throw Clipperz.Crypt.BigInt.exception.UnknownType;
1504 }
1505
1506 return result;
1507 },
1508
1509 //-------------------------------------------------------------------------
1510
1511 'compare': function(aValue) {
1512/*
1513 var result;
1514 var thisAsString;
1515 var aValueAsString;
1516
1517 thisAsString = this.asString(10);
1518 aValueAsString = aValue.asString(10);
1519
1520 result = MochiKit.Base.compare(thisAsString.length, aValueAsString.length);
1521 if (result == 0) {
1522 result = MochiKit.Base.compare(thisAsString, aValueAsString);
1523 }
1524
1525 return result;
1526*/
1527 var result;
1528
1529 if (equals(this.internalValue(), aValue.internalValue())) {
1530 result = 0;
1531 } else if (greater(this.internalValue(), aValue.internalValue())) {
1532 result = 1;
1533 } else {
1534 result = -1;
1535 }
1536
1537 return result;
1538 },
1539
1540 //-------------------------------------------------------------------------
1541
1542 'add': function (aValue) {
1543 var result;
1544
1545 if (aValue.isBigInt) {
1546 result = add(this.internalValue(), aValue.internalValue());
1547 } else {
1548 result = addInt(this.internalValue(), aValue);
1549 }
1550
1551 return new Clipperz.Crypto.BigInt(result);
1552 },
1553
1554 //-------------------------------------------------------------------------
1555
1556 'subtract': function (aValue) {
1557 var result;
1558 var value;
1559
1560 if (aValue.isBigInt) {
1561 value = aValue;
1562 } else {
1563 value = new Clipperz.Crypto.BigInt(aValue);
1564 }
1565
1566 result = sub(this.internalValue(), value.internalValue());
1567
1568 return new Clipperz.Crypto.BigInt(result);
1569 },
1570
1571 //-------------------------------------------------------------------------
1572
1573 'multiply': function (aValue, aModule) {
1574 var result;
1575 var value;
1576
1577 if (aValue.isBigInt) {
1578 value = aValue;
1579 } else {
1580 value = new Clipperz.Crypto.BigInt(aValue);
1581 }
1582
1583 if (typeof(aModule) == 'undefined') {
1584 result = mult(this.internalValue(), value.internalValue());
1585 } else {
1586 if (greater(this.internalValue(), value.internalValue())) {
1587 result = multMod(this.internalValue(), value.internalValue(), aModule);
1588 } else {
1589 result = multMod(value.internalValue(), this.internalValue(), aModule);
1590 }
1591 }
1592
1593 return new Clipperz.Crypto.BigInt(result);
1594 },
1595
1596 //-------------------------------------------------------------------------
1597
1598 'module': function (aModule) {
1599 varresult;
1600 var module;
1601
1602 if (aModule.isBigInt) {
1603 module = aModule;
1604 } else {
1605 module = new Clipperz.Crypto.BigInt(aModule);
1606 }
1607
1608 result = mod(this.internalValue(), module.internalValue());
1609
1610 return new Clipperz.Crypto.BigInt(result);
1611 },
1612
1613 //-------------------------------------------------------------------------
1614
1615 'powerModule': function(aValue, aModule) {
1616 varresult;
1617 varvalue;
1618 var module;
1619
1620 if (aValue.isBigInt) {
1621 value = aValue;
1622 } else {
1623 value = new Clipperz.Crypto.BigInt(aValue);
1624 }
1625
1626 if (aModule.isBigInt) {
1627 module = aModule;
1628 } else {
1629 module = new Clipperz.Crypto.BigInt(aModule);
1630 }
1631
1632 if (aValue == -1) {
1633 result = inverseMod(this.internalValue(), module.internalValue());
1634 } else {
1635 result = powMod(this.internalValue(), value.internalValue(), module.internalValue());
1636 }
1637
1638 return new Clipperz.Crypto.BigInt(result);
1639 },
1640
1641 //-------------------------------------------------------------------------
1642
1643 'xor': function(aValue) {
1644 var result;
1645 varthisByteArray;
1646 var aValueByteArray;
1647 var xorArray;
1648
1649 thisByteArray = new Clipperz.ByteArray("0x" + this.asString(16), 16);
1650 aValueByteArray = new Clipperz.ByteArray("0x" + aValue.asString(16), 16);
1651 xorArray = thisByteArray.xorMergeWithBlock(aValueByteArray, 'right');
1652 result = new Clipperz.Crypto.BigInt(xorArray.toHexString(), 16);
1653
1654 return result;
1655 },
1656
1657 //-------------------------------------------------------------------------
1658
1659 'shiftLeft': function(aNumberOfBitsToShift) {
1660 var result;
1661 var internalResult;
1662 var wholeByteToShift;
1663 var bitsLeftToShift;
1664
1665 wholeByteToShift = Math.floor(aNumberOfBitsToShift / 8);
1666 bitsLeftToShift = aNumberOfBitsToShift % 8;
1667
1668 if (wholeByteToShift == 0) {
1669 internalResult = this.internalValue();
1670 } else {
1671 var hexValue;
1672 var i,c;
1673
1674 hexValue = this.asString(16);
1675 c = wholeByteToShift;
1676 for (i=0; i<c; i++) {
1677 hexValue += "00";
1678 }
1679 internalResult = str2bigInt(hexValue, 16, 1, 1);
1680 }
1681
1682 if (bitsLeftToShift > 0) {
1683 leftShift_(internalResult, bitsLeftToShift);
1684 }
1685 result = new Clipperz.Crypto.BigInt(internalResult);
1686
1687 return result;
1688 },
1689
1690 //-------------------------------------------------------------------------
1691
1692 'bitSize': function() {
1693 return bitSize(this.internalValue());
1694 },
1695
1696 //-------------------------------------------------------------------------
1697
1698 'isBitSet': function(aBitPosition) {
1699 var result;
1700
1701 if (this.asByteArray().bitAtIndex(aBitPosition) == 0) {
1702 result = false;
1703 } else {
1704 result = true;
1705 };
1706
1707 return result;
1708 },
1709
1710 //-------------------------------------------------------------------------
1711 __syntaxFix__: "syntax fix"
1712
1713});
1714
1715//#############################################################################
1716
1717Clipperz.Crypto.BigInt.randomPrime = function(aBitSize) {
1718 return new Clipperz.Crypto.BigInt(randTruePrime(aBitSize));
1719}
1720
1721//#############################################################################
1722//#############################################################################
1723
1724Clipperz.Crypto.BigInt.ZERO = new Clipperz.Crypto.BigInt(0);
1725
1726//#############################################################################
1727
1728Clipperz.Crypto.BigInt.equals = function(a, b) {
1729 return a.equals(b);
1730}
1731
1732Clipperz.Crypto.BigInt.add = function(a, b) {
1733 return a.add(b);
1734}
1735
1736Clipperz.Crypto.BigInt.subtract = function(a, b) {
1737 return a.subtract(b);
1738}
1739
1740Clipperz.Crypto.BigInt.multiply = function(a, b, module) {
1741 return a.multiply(b, module);
1742}
1743
1744Clipperz.Crypto.BigInt.module = function(a, module) {
1745 return a.module(module);
1746}
1747
1748Clipperz.Crypto.BigInt.powerModule = function(a, b, module) {
1749 return a.powerModule(b, module);
1750}
1751
1752Clipperz.Crypto.BigInt.exception = {
1753 UnknownType: new MochiKit.Base.NamedError("Clipperz.Crypto.BigInt.exception.UnknownType")
1754}
diff --git a/frontend/delta/js/Clipperz/Crypto/BigInt_scoped.js b/frontend/delta/js/Clipperz/Crypto/BigInt_scoped.js
new file mode 100644
index 0000000..bc60330
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/BigInt_scoped.js
@@ -0,0 +1,1644 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
26
27if (typeof(Leemon) == 'undefined') { Leemon = {}; }
28if (typeof(Baird.Crypto) == 'undefined') { Baird.Crypto = {}; }
29if (typeof(Baird.Crypto.BigInt) == 'undefined') { Baird.Crypto.BigInt = {}; }
30
31
32//#############################################################################
33 //Downloaded on March 05, 2007 from http://www.leemon.com/crypto/BigInt.js
34//#############################################################################
35
36////////////////////////////////////////////////////////////////////////////////////////
37// Big Integer Library v. 5.0
38// Created 2000, last modified 2006
39// Leemon Baird
40// www.leemon.com
41//
42// This file is public domain. You can use it for any purpose without restriction.
43// I do not guarantee that it is correct, so use it at your own risk. If you use
44// it for something interesting, I'd appreciate hearing about it. If you find
45// any bugs or make any improvements, I'd appreciate hearing about those too.
46// It would also be nice if my name and address were left in the comments.
47// But none of that is required.
48//
49// This code defines a bigInt library for arbitrary-precision integers.
50// A bigInt is an array of integers storing the value in chunks of bpe bits,
51// little endian (buff[0] is the least significant word).
52// Negative bigInts are stored two's complement.
53// Some functions assume their parameters have at least one leading zero element.
54// Functions with an underscore at the end of the name have unpredictable behavior in case of overflow,
55// so the caller must make sure overflow won't happen.
56// For each function where a parameter is modified, that same
57// variable must not be used as another argument too.
58// So, you cannot square x by doing multMod_(x,x,n).
59// You must use squareMod_(x,n) instead, or do y=dup(x); multMod_(x,y,n).
60//
61// These functions are designed to avoid frequent dynamic memory allocation in the inner loop.
62// For most functions, if it needs a BigInt as a local variable it will actually use
63// a global, and will only allocate to it when it's not the right size. This ensures
64// that when a function is called repeatedly with same-sized parameters, it only allocates
65// memory on the first call.
66//
67// Note that for cryptographic purposes, the calls to Math.random() must
68// be replaced with calls to a better pseudorandom number generator.
69//
70// In the following, "bigInt" means a bigInt with at least one leading zero element,
71// and "integer" means a nonnegative integer less than radix. In some cases, integer
72// can be negative. Negative bigInts are 2s complement.
73//
74// The following functions do not modify their inputs, but dynamically allocate memory every time they are called:
75//
76// function bigInt2str(x,base) //convert a bigInt into a string in a given base, from base 2 up to base 95
77// function dup(x) //returns a copy of bigInt x
78// function findPrimes(n) //return array of all primes less than integer n
79// function int2bigInt(t,n,m) //convert integer t to a bigInt with at least n bits and m array elements
80// function str2bigInt(s,b,n,m) //convert string s in base b to a bigInt with at least n bits and m array elements
81// function trim(x,k) //return a copy of x with exactly k leading zero elements
82//
83// The following functions do not modify their inputs, so there is never a problem with the result being too big:
84//
85// function bitSize(x) //returns how many bits long the bigInt x is, not counting leading zeros
86// function equals(x,y) //is the bigInt x equal to the bigint y?
87// function equalsInt(x,y) //is bigint x equal to integer y?
88// function greater(x,y) //is x>y? (x and y are nonnegative bigInts)
89// function greaterShift(x,y,shift)//is (x <<(shift*bpe)) > y?
90// function isZero(x) //is the bigInt x equal to zero?
91// function millerRabin(x,b) //does one round of Miller-Rabin base integer b say that bigInt x is possibly prime (as opposed to definitely composite)?
92// function modInt(x,n) //return x mod n for bigInt x and integer n.
93// function negative(x) //is bigInt x negative?
94//
95// The following functions do not modify their inputs, but allocate memory and call functions with underscores
96//
97// function add(x,y) //return (x+y) for bigInts x and y.
98// function addInt(x,n) //return (x+n) where x is a bigInt and n is an integer.
99// function expand(x,n) //return a copy of x with at least n elements, adding leading zeros if needed
100// function inverseMod(x,n) //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
101// function mod(x,n) //return a new bigInt equal to (x mod n) for bigInts x and n.
102// function mult(x,y) //return x*y for bigInts x and y. This is faster when y<x.
103// function multMod(x,y,n) //return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
104// function powMod(x,y,n) //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
105// function randTruePrime(k) //return a new, random, k-bit, true prime using Maurer's algorithm.
106// function sub(x,y) //return (x-y) for bigInts x and y. Negative answers will be 2s complement
107//
108// The following functions write a bigInt result to one of the parameters, but
109// the result is never bigger than the original, so there can't be overflow problems:
110//
111// function divInt_(x,n) //do x=floor(x/n) for bigInt x and integer n, and return the remainder
112// function GCD_(x,y) //set x to the greatest common divisor of bigInts x and y, (y is destroyed).
113// function halve_(x) //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
114// function mod_(x,n) //do x=x mod n for bigInts x and n.
115// function rightShift_(x,n) //right shift bigInt x by n bits. 0 <= n < bpe.
116//
117// The following functions write a bigInt result to one of the parameters. The caller is responsible for
118// ensuring it is large enough to hold the result.
119//
120// function addInt_(x,n) //do x=x+n where x is a bigInt and n is an integer
121// function add_(x,y) //do x=x+y for bigInts x and y
122// function addShift_(x,y,ys) //do x=x+(y<<(ys*bpe))
123// function copy_(x,y) //do x=y on bigInts x and y
124// function copyInt_(x,n) //do x=n on bigInt x and integer n
125// function carry_(x) //do carries and borrows so each element of the bigInt x fits in bpe bits.
126// function divide_(x,y,q,r) //divide_ x by y giving quotient q and remainder r
127// function eGCD_(x,y,d,a,b) //sets a,b,d to positive big integers such that d = GCD_(x,y) = a*x-b*y
128// function inverseMod_(x,n) //do x=x**(-1) mod n, for bigInts x and n. Returns 1 (0) if inverse does (doesn't) exist
129// function inverseModInt_(x,n) //return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
130// function leftShift_(x,n) //left shift bigInt x by n bits. n<bpe.
131// function linComb_(x,y,a,b) //do x=a*x+b*y for bigInts x and y and integers a and b
132// function linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys
133// function mont_(x,y,n,np) //Montgomery multiplication (see comments where the function is defined)
134// function mult_(x,y) //do x=x*y for bigInts x and y.
135// function multInt_(x,n) //do x=x*n where x is a bigInt and n is an integer.
136// function multMod_(x,y,n) //do x=x*y mod n for bigInts x,y,n.
137// function powMod_(x,y,n) //do x=x**y mod n, where x,y,n are bigInts (n is odd) and ** is exponentiation. 0**0=1.
138// function randBigInt_(b,n,s) //do b = an n-bit random BigInt. if s=1, then nth bit (most significant bit) is set to 1. n>=1.
139// function randTruePrime_(ans,k) //do ans = a random k-bit true random prime (not just probable prime) with 1 in the msb.
140// function squareMod_(x,n) //do x=x*x mod n for bigInts x,n
141// function sub_(x,y) //do x=x-y for bigInts x and y. Negative answers will be 2s complement.
142// function subShift_(x,y,ys) //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement.
143//
144// The following functions are based on algorithms from the _Handbook of Applied Cryptography_
145// powMod_() = algorithm 14.94, Montgomery exponentiation
146// eGCD_,inverseMod_() = algorithm 14.61, Binary extended GCD_
147// GCD_() = algorothm 14.57, Lehmer's algorithm
148// mont_() = algorithm 14.36, Montgomery multiplication
149// divide_() = algorithm 14.20 Multiple-precision division
150// squareMod_() = algorithm 14.16 Multiple-precision squaring
151// randTruePrime_() = algorithm 4.62, Maurer's algorithm
152// millerRabin() = algorithm 4.24, Miller-Rabin algorithm
153//
154// Profiling shows:
155// randTruePrime_() spends:
156// 10% of its time in calls to powMod_()
157// 85% of its time in calls to millerRabin()
158// millerRabin() spends:
159// 99% of its time in calls to powMod_() (always with a base of 2)
160// powMod_() spends:
161// 94% of its time in calls to mont_() (almost always with x==y)
162//
163// This suggests there are several ways to speed up this library slightly:
164// - convert powMod_ to use a Montgomery form of k-ary window (or maybe a Montgomery form of sliding window)
165// -- this should especially focus on being fast when raising 2 to a power mod n
166// - convert randTruePrime_() to use a minimum r of 1/3 instead of 1/2 with the appropriate change to the test
167// - tune the parameters in randTruePrime_(), including c, m, and recLimit
168// - speed up the single loop in mont_() that takes 95% of the runtime, perhaps by reducing checking
169// within the loop when all the parameters are the same length.
170//
171// There are several ideas that look like they wouldn't help much at all:
172// - replacing trial division in randTruePrime_() with a sieve (that speeds up something taking almost no time anyway)
173// - increase bpe from 15 to 30 (that would help if we had a 32*32->64 multiplier, but not with JavaScript's 32*32->32)
174// - speeding up mont_(x,y,n,np) when x==y by doing a non-modular, non-Montgomery square
175// followed by a Montgomery reduction. The intermediate answer will be twice as long as x, so that
176// method would be slower. This is unfortunate because the code currently spends almost all of its time
177// doing mont_(x,x,...), both for randTruePrime_() and powMod_(). A faster method for Montgomery squaring
178// would have a large impact on the speed of randTruePrime_() and powMod_(). HAC has a couple of poorly-worded
179// sentences that seem to imply it's faster to do a non-modular square followed by a single
180// Montgomery reduction, but that's obviously wrong.
181////////////////////////////////////////////////////////////////////////////////////////
182
183//
184 //The whole library has been moved into the Baird.Crypto.BigInt scope by Giulio Cesare Solaroli <giulio.cesare@clipperz.com>
185//
186Baird.Crypto.BigInt.VERSION = "5.0";
187Baird.Crypto.BigInt.NAME = "Baird.Crypto.BigInt";
188
189MochiKit.Base.update(Baird.Crypto.BigInt, {
190 //globals
191 'bpe': 0, //bits stored per array element
192 'mask': 0, //AND this with an array element to chop it down to bpe bits
193 'radix': Baird.Crypto.BigInt.mask + 1,//equals 2^bpe. A single 1 bit to the left of the last bit of mask.
194
195 //the digits for converting to different bases
196 'digitsStr': '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-',
197
198//initialize the global variables
199for (bpe=0; (1<<(bpe+1)) > (1<<bpe); bpe++); //bpe=number of bits in the mantissa on this platform
200bpe>>=1; //bpe=number of bits in one element of the array representing the bigInt
201mask=(1<<bpe)-1; //AND the mask with an integer to get its bpe least significant bits
202radix=mask+1; //2^bpe. a single 1 bit to the left of the first bit of mask
203one=int2bigInt(1,1,1); //constant used in powMod_()
204
205//the following global variables are scratchpad memory to
206//reduce dynamic memory allocation in the inner loop
207t=new Array(0);
208ss=t; //used in mult_()
209s0=t; //used in multMod_(), squareMod_()
210s1=t; //used in powMod_(), multMod_(), squareMod_()
211s2=t; //used in powMod_(), multMod_()
212s3=t; //used in powMod_()
213s4=t; s5=t; //used in mod_()
214s6=t; //used in bigInt2str()
215s7=t; //used in powMod_()
216T=t; //used in GCD_()
217sa=t; //used in mont_()
218mr_x1=t; mr_r=t; mr_a=t; //used in millerRabin()
219eg_v=t; eg_u=t; eg_A=t; eg_B=t; eg_C=t; eg_D=t; //used in eGCD_(), inverseMod_()
220md_q1=t; md_q2=t; md_q3=t; md_r=t; md_r1=t; md_r2=t; md_tt=t; //used in mod_()
221
222primes=t; pows=t; s_i=t; s_i2=t; s_R=t; s_rm=t; s_q=t; s_n1=t;
223 s_a=t; s_r2=t; s_n=t; s_b=t; s_d=t; s_x1=t; s_x2=t, s_aa=t; //used in randTruePrime_()
224
225////////////////////////////////////////////////////////////////////////////////////////
226
227 //return array of all primes less than integer n
228 'findPrimes': function(n) {
229 var i,s,p,ans;
230 s=new Array(n);
231 for (i=0;i<n;i++)
232 s[i]=0;
233 s[0]=2;
234 p=0; //first p elements of s are primes, the rest are a sieve
235 for(;s[p]<n;) { //s[p] is the pth prime
236 for(i=s[p]*s[p]; i<n; i+=s[p]) //mark multiples of s[p]
237 s[i]=1;
238 p++;
239 s[p]=s[p-1]+1;
240 for(; s[p]<n && s[s[p]]; s[p]++); //find next prime (where s[p]==0)
241 }
242 ans=new Array(p);
243 for(i=0;i<p;i++)
244 ans[i]=s[i];
245 return ans;
246 },
247
248 //does a single round of Miller-Rabin base b consider x to be a possible prime?
249 //x is a bigInt, and b is an integer
250 'millerRabin': function(x,b) {
251 var i,j,k,s;
252
253 if (mr_x1.length!=x.length) {
254 mr_x1=dup(x);
255 mr_r=dup(x);
256 mr_a=dup(x);
257 }
258
259 copyInt_(mr_a,b);
260 copy_(mr_r,x);
261 copy_(mr_x1,x);
262
263 addInt_(mr_r,-1);
264 addInt_(mr_x1,-1);
265
266 //s=the highest power of two that divides mr_r
267 k=0;
268 for (i=0;i<mr_r.length;i++)
269 for (j=1;j<mask;j<<=1)
270 if (x[i] & j) {
271 s=(k<mr_r.length+bpe ? k : 0);
272 i=mr_r.length;
273 j=mask;
274 } else
275 k++;
276
277 if (s)
278 rightShift_(mr_r,s);
279
280 powMod_(mr_a,mr_r,x);
281
282 if (!equalsInt(mr_a,1) && !equals(mr_a,mr_x1)) {
283 j=1;
284 while (j<=s-1 && !equals(mr_a,mr_x1)) {
285 squareMod_(mr_a,x);
286 if (equalsInt(mr_a,1)) {
287 return 0;
288 }
289 j++;
290 }
291 if (!equals(mr_a,mr_x1)) {
292 return 0;
293 }
294 }
295
296 return 1;
297 },
298
299 //returns how many bits long the bigInt is, not counting leading zeros.
300 'bitSize': function(x) {
301 var j,z,w;
302 for (j=x.length-1; (x[j]==0) && (j>0); j--);
303 for (z=0,w=x[j]; w; (w>>=1),z++);
304 z+=bpe*j;
305 return z;
306 },
307
308 //return a copy of x with at least n elements, adding leading zeros if needed
309 'expand': function(x,n) {
310 var ans=int2bigInt(0,(x.length>n ? x.length : n)*bpe,0);
311 copy_(ans,x);
312 return ans;
313 },
314
315 //return a k-bit true random prime using Maurer's algorithm.
316 'randTruePrime': function(k) {
317 var ans=int2bigInt(0,k,0);
318 randTruePrime_(ans,k);
319 return trim(ans,1);
320 },
321
322 //return a new bigInt equal to (x mod n) for bigInts x and n.
323 'mod': function(x,n) {
324 var ans=dup(x);
325 mod_(ans,n);
326 return trim(ans,1);
327 },
328
329 //return (x+n) where x is a bigInt and n is an integer.
330 'addInt': function(x,n) {
331 var ans=expand(x,x.length+1);
332 addInt_(ans,n);
333 return trim(ans,1);
334 },
335
336 //return x*y for bigInts x and y. This is faster when y<x.
337 'mult': function(x,y) {
338 var ans=expand(x,x.length+y.length);
339 mult_(ans,y);
340 return trim(ans,1);
341 },
342
343 //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
344 'powMod': function(x,y,n) {
345 var ans=expand(x,n.length);
346 powMod_(ans,trim(y,2),trim(n,2),0); //this should work without the trim, but doesn't
347 return trim(ans,1);
348 },
349
350 //return (x-y) for bigInts x and y. Negative answers will be 2s complement
351 'sub': function(x,y) {
352 var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
353 sub_(ans,y);
354 return trim(ans,1);
355 },
356
357 //return (x+y) for bigInts x and y.
358 'add': function(x,y) {
359 var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
360 add_(ans,y);
361 return trim(ans,1);
362 },
363
364 //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
365 'inverseMod': function(x,n) {
366 var ans=expand(x,n.length);
367 var s;
368 s=inverseMod_(ans,n);
369 return s ? trim(ans,1) : null;
370 },
371
372 //return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
373 'multMod': function(x,y,n) {
374 var ans=expand(x,n.length);
375 multMod_(ans,y,n);
376 return trim(ans,1);
377 },
378
379 //generate a k-bit true random prime using Maurer's algorithm,
380 //and put it into ans. The bigInt ans must be large enough to hold it.
381 'randTruePrime_': function(ans,k) {
382 var c,m,pm,dd,j,r,B,divisible,z,zz,recSize;
383
384 if (primes.length==0)
385 primes=findPrimes(30000); //check for divisibility by primes <=30000
386
387 if (pows.length==0) {
388 pows=new Array(512);
389 for (j=0;j<512;j++) {
390 pows[j]=Math.pow(2,j/511.-1.);
391 }
392 }
393
394 //c and m should be tuned for a particular machine and value of k, to maximize speed
395 //this was: c=primes[primes.length-1]/k/k; //check using all the small primes. (c=0.1 in HAC)
396 c=0.1;
397 m=20; //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
398 recLimit=20; /*must be at least 2 (was 29)*/ //stop recursion when k <=recLimit
399
400 if (s_i2.length!=ans.length) {
401 s_i2=dup(ans);
402 s_R =dup(ans);
403 s_n1=dup(ans);
404 s_r2=dup(ans);
405 s_d =dup(ans);
406 s_x1=dup(ans);
407 s_x2=dup(ans);
408 s_b =dup(ans);
409 s_n =dup(ans);
410 s_i =dup(ans);
411 s_rm=dup(ans);
412 s_q =dup(ans);
413 s_a =dup(ans);
414 s_aa=dup(ans);
415 }
416
417 if (k <= recLimit) { //generate small random primes by trial division up to its square root
418 pm=(1<<((k+2)>>1))-1; //pm is binary number with all ones, just over sqrt(2^k)
419 copyInt_(ans,0);
420 for (dd=1;dd;) {
421 dd=0;
422 ans[0]= 1 | (1<<(k-1)) | Math.floor(Math.random()*(1<<k)); //random, k-bit, odd integer, with msb 1
423 for (j=1;(j<primes.length) && ((primes[j]&pm)==primes[j]);j++) { //trial division by all primes 3...sqrt(2^k)
424 if (0==(ans[0]%primes[j])) {
425 dd=1;
426 break;
427 }
428 }
429 }
430 carry_(ans);
431 return;
432 }
433
434 B=c*k*k; //try small primes up to B (or all the primes[] array if the largest is less than B).
435 if (k>2*m) //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
436 for (r=1; k-k*r<=m; )
437 r=pows[Math.floor(Math.random()*512)]; //r=Math.pow(2,Math.random()-1);
438 else
439 r=.5;
440
441 //simulation suggests the more complex algorithm using r=.333 is only slightly faster.
442
443 recSize=Math.floor(r*k)+1;
444
445 randTruePrime_(s_q,recSize);
446 copyInt_(s_i2,0);
447 s_i2[Math.floor((k-2)/bpe)] |= (1<<((k-2)%bpe)); //s_i2=2^(k-2)
448 divide_(s_i2,s_q,s_i,s_rm); //s_i=floor((2^(k-1))/(2q))
449
450 z=bitSize(s_i);
451
452 for (;;) {
453 for (;;) { //generate z-bit numbers until one falls in the range [0,s_i-1]
454 randBigInt_(s_R,z,0);
455 if (greater(s_i,s_R))
456 break;
457 } //now s_R is in the range [0,s_i-1]
458 addInt_(s_R,1); //now s_R is in the range [1,s_i]
459 add_(s_R,s_i); //now s_R is in the range [s_i+1,2*s_i]
460
461 copy_(s_n,s_q);
462 mult_(s_n,s_R);
463 multInt_(s_n,2);
464 addInt_(s_n,1); //s_n=2*s_R*s_q+1
465
466 copy_(s_r2,s_R);
467 multInt_(s_r2,2); //s_r2=2*s_R
468
469 //check s_n for divisibility by small primes up to B
470 for (divisible=0,j=0; (j<primes.length) && (primes[j]<B); j++)
471 if (modInt(s_n,primes[j])==0) {
472 divisible=1;
473 break;
474 }
475
476 if (!divisible) //if it passes small primes check, then try a single Miller-Rabin base 2
477 if (!millerRabin(s_n,2)) //this line represents 75% of the total runtime for randTruePrime_
478 divisible=1;
479
480 if (!divisible) { //if it passes that test, continue checking s_n
481 addInt_(s_n,-3);
482 for (j=s_n.length-1;(s_n[j]==0) && (j>0); j--); //strip leading zeros
483 for (zz=0,w=s_n[j]; w; (w>>=1),zz++);
484 zz+=bpe*j; //zz=number of bits in s_n, ignoring leading zeros
485 for (;;) { //generate z-bit numbers until one falls in the range [0,s_n-1]
486 randBigInt_(s_a,zz,0);
487 if (greater(s_n,s_a))
488 break;
489 } //now s_a is in the range [0,s_n-1]
490 addInt_(s_n,3); //now s_a is in the range [0,s_n-4]
491 addInt_(s_a,2); //now s_a is in the range [2,s_n-2]
492 copy_(s_b,s_a);
493 copy_(s_n1,s_n);
494 addInt_(s_n1,-1);
495 powMod_(s_b,s_n1,s_n); //s_b=s_a^(s_n-1) modulo s_n
496 addInt_(s_b,-1);
497 if (isZero(s_b)) {
498 copy_(s_b,s_a);
499 powMod_(s_b,s_r2,s_n);
500 addInt_(s_b,-1);
501 copy_(s_aa,s_n);
502 copy_(s_d,s_b);
503 GCD_(s_d,s_n); //if s_b and s_n are relatively prime, then s_n is a prime
504 if (equalsInt(s_d,1)) {
505 copy_(ans,s_aa);
506 return; //if we've made it this far, then s_n is absolutely guaranteed to be prime
507 }
508 }
509 }
510 }
511 },
512
513 //set b to an n-bit random BigInt. If s=1, then nth bit (most significant bit) is set to 1.
514 //array b must be big enough to hold the result. Must have n>=1
515 'randBigInt_': function(b,n,s) {
516 var i,a;
517 for (i=0;i<b.length;i++)
518 b[i]=0;
519 a=Math.floor((n-1)/bpe)+1; //# array elements to hold the BigInt
520 for (i=0;i<a;i++) {
521 b[i]=Math.floor(Math.random()*(1<<(bpe-1)));
522 }
523 b[a-1] &= (2<<((n-1)%bpe))-1;
524 if (s)
525 b[a-1] |= (1<<((n-1)%bpe));
526 },
527
528 //set x to the greatest common divisor of x and y.
529 //x,y are bigInts with the same number of elements. y is destroyed.
530 'GCD_': function(x,y) {
531 var i,xp,yp,A,B,C,D,q,sing;
532 if (T.length!=x.length)
533 T=dup(x);
534
535 sing=1;
536 while (sing) { //while y has nonzero elements other than y[0]
537 sing=0;
538 for (i=1;i<y.length;i++) //check if y has nonzero elements other than 0
539 if (y[i]) {
540 sing=1;
541 break;
542 }
543 if (!sing) break; //quit when y all zero elements except possibly y[0]
544
545 for (i=x.length;!x[i] && i>=0;i--); //find most significant element of x
546 xp=x[i];
547 yp=y[i];
548 A=1; B=0; C=0; D=1;
549 while ((yp+C) && (yp+D)) {
550 q =Math.floor((xp+A)/(yp+C));
551 qp=Math.floor((xp+B)/(yp+D));
552 if (q!=qp)
553 break;
554 t= A-q*C; A=C; C=t; // do (A,B,xp, C,D,yp) = (C,D,yp, A,B,xp) - q*(0,0,0, C,D,yp)
555 t= B-q*D; B=D; D=t;
556 t=xp-q*yp; xp=yp; yp=t;
557 }
558 if (B) {
559 copy_(T,x);
560 linComb_(x,y,A,B); //x=A*x+B*y
561 linComb_(y,T,D,C); //y=D*y+C*T
562 } else {
563 mod_(x,y);
564 copy_(T,x);
565 copy_(x,y);
566 copy_(y,T);
567 }
568 }
569 if (y[0]==0)
570 return;
571 t=modInt(x,y[0]);
572 copyInt_(x,y[0]);
573 y[0]=t;
574 while (y[0]) {
575 x[0]%=y[0];
576 t=x[0]; x[0]=y[0]; y[0]=t;
577 }
578 },
579
580//do x=x**(-1) mod n, for bigInts x and n.
581//If no inverse exists, it sets x to zero and returns 0, else it returns 1.
582//The x array must be at least as large as the n array.
583function inverseMod_(x,n) {
584 var k=1+2*Math.max(x.length,n.length);
585
586 if(!(x[0]&1) && !(n[0]&1)) { //if both inputs are even, then inverse doesn't exist
587 copyInt_(x,0);
588 return 0;
589 }
590
591 if (eg_u.length!=k) {
592 eg_u=new Array(k);
593 eg_v=new Array(k);
594 eg_A=new Array(k);
595 eg_B=new Array(k);
596 eg_C=new Array(k);
597 eg_D=new Array(k);
598 }
599
600 copy_(eg_u,x);
601 copy_(eg_v,n);
602 copyInt_(eg_A,1);
603 copyInt_(eg_B,0);
604 copyInt_(eg_C,0);
605 copyInt_(eg_D,1);
606 for (;;) {
607 while(!(eg_u[0]&1)) { //while eg_u is even
608 halve_(eg_u);
609 if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if eg_A==eg_B==0 mod 2
610 halve_(eg_A);
611 halve_(eg_B);
612 } else {
613 add_(eg_A,n); halve_(eg_A);
614 sub_(eg_B,x); halve_(eg_B);
615 }
616 }
617
618 while (!(eg_v[0]&1)) { //while eg_v is even
619 halve_(eg_v);
620 if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if eg_C==eg_D==0 mod 2
621 halve_(eg_C);
622 halve_(eg_D);
623 } else {
624 add_(eg_C,n); halve_(eg_C);
625 sub_(eg_D,x); halve_(eg_D);
626 }
627 }
628
629 if (!greater(eg_v,eg_u)) { //eg_v <= eg_u
630 sub_(eg_u,eg_v);
631 sub_(eg_A,eg_C);
632 sub_(eg_B,eg_D);
633 } else { //eg_v > eg_u
634 sub_(eg_v,eg_u);
635 sub_(eg_C,eg_A);
636 sub_(eg_D,eg_B);
637 }
638
639 if (equalsInt(eg_u,0)) {
640 if (negative(eg_C)) //make sure answer is nonnegative
641 add_(eg_C,n);
642 copy_(x,eg_C);
643
644 if (!equalsInt(eg_v,1)) { //if GCD_(x,n)!=1, then there is no inverse
645 copyInt_(x,0);
646 return 0;
647 }
648 return 1;
649 }
650 }
651}
652
653//return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
654function inverseModInt_(x,n) {
655 var a=1,b=0,t;
656 for (;;) {
657 if (x==1) return a;
658 if (x==0) return 0;
659 b-=a*Math.floor(n/x);
660 n%=x;
661
662 if (n==1) return b; //to avoid negatives, change this b to n-b, and each -= to +=
663 if (n==0) return 0;
664 a-=b*Math.floor(x/n);
665 x%=n;
666 }
667}
668
669//Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that:
670// v = GCD_(x,y) = a*x-b*y
671//The bigInts v, a, b, must have exactly as many elements as the larger of x and y.
672function eGCD_(x,y,v,a,b) {
673 var g=0;
674 var k=Math.max(x.length,y.length);
675 if (eg_u.length!=k) {
676 eg_u=new Array(k);
677 eg_A=new Array(k);
678 eg_B=new Array(k);
679 eg_C=new Array(k);
680 eg_D=new Array(k);
681 }
682 while(!(x[0]&1) && !(y[0]&1)) { //while x and y both even
683 halve_(x);
684 halve_(y);
685 g++;
686 }
687 copy_(eg_u,x);
688 copy_(v,y);
689 copyInt_(eg_A,1);
690 copyInt_(eg_B,0);
691 copyInt_(eg_C,0);
692 copyInt_(eg_D,1);
693 for (;;) {
694 while(!(eg_u[0]&1)) { //while u is even
695 halve_(eg_u);
696 if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if A==B==0 mod 2
697 halve_(eg_A);
698 halve_(eg_B);
699 } else {
700 add_(eg_A,y); halve_(eg_A);
701 sub_(eg_B,x); halve_(eg_B);
702 }
703 }
704
705 while (!(v[0]&1)) { //while v is even
706 halve_(v);
707 if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if C==D==0 mod 2
708 halve_(eg_C);
709 halve_(eg_D);
710 } else {
711 add_(eg_C,y); halve_(eg_C);
712 sub_(eg_D,x); halve_(eg_D);
713 }
714 }
715
716 if (!greater(v,eg_u)) { //v<=u
717 sub_(eg_u,v);
718 sub_(eg_A,eg_C);
719 sub_(eg_B,eg_D);
720 } else { //v>u
721 sub_(v,eg_u);
722 sub_(eg_C,eg_A);
723 sub_(eg_D,eg_B);
724 }
725 if (equalsInt(eg_u,0)) {
726 if (negative(eg_C)) { //make sure a (C)is nonnegative
727 add_(eg_C,y);
728 sub_(eg_D,x);
729 }
730 multInt_(eg_D,-1); ///make sure b (D) is nonnegative
731 copy_(a,eg_C);
732 copy_(b,eg_D);
733 leftShift_(v,g);
734 return;
735 }
736 }
737}
738
739
740//is bigInt x negative?
741function negative(x) {
742 return ((x[x.length-1]>>(bpe-1))&1);
743}
744
745
746//is (x << (shift*bpe)) > y?
747//x and y are nonnegative bigInts
748//shift is a nonnegative integer
749function greaterShift(x,y,shift) {
750 var kx=x.length, ky=y.length;
751 k=((kx+shift)<ky) ? (kx+shift) : ky;
752 for (i=ky-1-shift; i<kx && i>=0; i++)
753 if (x[i]>0)
754 return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger
755 for (i=kx-1+shift; i<ky; i++)
756 if (y[i]>0)
757 return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger
758 for (i=k-1; i>=shift; i--)
759 if (x[i-shift]>y[i]) return 1;
760 else if (x[i-shift]<y[i]) return 0;
761 return 0;
762}
763
764//is x > y? (x and y both nonnegative)
765function greater(x,y) {
766 var i;
767 var k=(x.length<y.length) ? x.length : y.length;
768
769 for (i=x.length;i<y.length;i++)
770 if (y[i])
771 return 0; //y has more digits
772
773 for (i=y.length;i<x.length;i++)
774 if (x[i])
775 return 1; //x has more digits
776
777 for (i=k-1;i>=0;i--)
778 if (x[i]>y[i])
779 return 1;
780 else if (x[i]<y[i])
781 return 0;
782 return 0;
783}
784
785//divide_ x by y giving quotient q and remainder r. (q=floor(x/y), r=x mod y). All 4 are bigints.
786//x must have at least one leading zero element.
787//y must be nonzero.
788//q and r must be arrays that are exactly the same length as x.
789//the x array must have at least as many elements as y.
790function divide_(x,y,q,r) {
791 var kx, ky;
792 var i,j,y1,y2,c,a,b;
793 copy_(r,x);
794 for (ky=y.length;y[ky-1]==0;ky--); //kx,ky is number of elements in x,y, not including leading zeros
795 for (kx=r.length;r[kx-1]==0 && kx>ky;kx--);
796
797 //normalize: ensure the most significant element of y has its highest bit set
798 b=y[ky-1];
799 for (a=0; b; a++)
800 b>>=1;
801 a=bpe-a; //a is how many bits to shift so that the high order bit of y is leftmost in its array element
802 leftShift_(y,a); //multiply both by 1<<a now, then divide_ both by that at the end
803 leftShift_(r,a);
804
805 copyInt_(q,0); // q=0
806 while (!greaterShift(y,r,kx-ky)) { // while (leftShift_(y,kx-ky) <= r) {
807 subShift_(r,y,kx-ky); // r=r-leftShift_(y,kx-ky)
808 q[kx-ky]++; // q[kx-ky]++;
809 } // }
810
811 for (i=kx-1; i>=ky; i--) {
812 if (r[i]==y[ky-1])
813 q[i-ky]=mask;
814 else
815 q[i-ky]=Math.floor((r[i]*radix+r[i-1])/y[ky-1]);
816
817 //The following for(;;) loop is equivalent to the commented while loop,
818 //except that the uncommented version avoids overflow.
819 //The commented loop comes from HAC, which assumes r[-1]==y[-1]==0
820 // while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2])
821 // q[i-ky]--;
822 for (;;) {
823 y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
824 c=y2>>bpe;
825 y2=y2 & mask;
826 y1=c+q[i-ky]*y[ky-1];
827 c=y1>>bpe;
828 y1=y1 & mask;
829
830 if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i])
831 q[i-ky]--;
832 else
833 break;
834 }
835
836 linCombShift_(r,y,-q[i-ky],i-ky); //r=r-q[i-ky]*leftShift_(y,i-ky)
837 if (negative(r)) {
838 addShift_(r,y,i-ky); //r=r+leftShift_(y,i-ky)
839 q[i-ky]--;
840 }
841 }
842
843 rightShift_(y,a); //undo the normalization step
844 rightShift_(r,a); //undo the normalization step
845}
846
847//do carries and borrows so each element of the bigInt x fits in bpe bits.
848function carry_(x) {
849 var i,k,c,b;
850 k=x.length;
851 c=0;
852 for (i=0;i<k;i++) {
853 c+=x[i];
854 b=0;
855 if (c<0) {
856 b=-(c>>bpe);
857 c+=b*radix;
858 }
859 x[i]=c & mask;
860 c=(c>>bpe)-b;
861 }
862}
863
864//return x mod n for bigInt x and integer n.
865function modInt(x,n) {
866 var i,c=0;
867 for (i=x.length-1; i>=0; i--)
868 c=(c*radix+x[i])%n;
869 return c;
870}
871
872//convert the integer t into a bigInt with at least the given number of bits.
873//the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word)
874//Pad the array with leading zeros so that it has at least minSize elements.
875//There will always be at least one leading 0 element.
876function int2bigInt(t,bits,minSize) {
877 var i,k;
878 k=Math.ceil(bits/bpe)+1;
879 k=minSize>k ? minSize : k;
880 buff=new Array(k);
881 copyInt_(buff,t);
882 return buff;
883}
884
885//return the bigInt given a string representation in a given base.
886//Pad the array with leading zeros so that it has at least minSize elements.
887//If base=-1, then it reads in a space-separated list of array elements in decimal.
888//The array will always have at least one leading zero, unless base=-1.
889function str2bigInt(s,base,minSize) {
890 var d, i, j, x, y, kk;
891 var k=s.length;
892 if (base==-1) { //comma-separated list of array elements in decimal
893 x=new Array(0);
894 for (;;) {
895 y=new Array(x.length+1);
896 for (i=0;i<x.length;i++)
897 y[i+1]=x[i];
898 y[0]=parseInt(s,10);
899 x=y;
900 d=s.indexOf(',',0);
901 if (d<1)
902 break;
903 s=s.substring(d+1);
904 if (s.length==0)
905 break;
906 }
907 if (x.length<minSize) {
908 y=new Array(minSize);
909 copy_(y,x);
910 return y;
911 }
912 return x;
913 }
914
915 x=int2bigInt(0,base*k,0);
916 for (i=0;i<k;i++) {
917 d=digitsStr.indexOf(s.substring(i,i+1),0);
918 if (base<=36 && d>=36) //convert lowercase to uppercase if base<=36
919 d-=26;
920 if (d<base && d>=0) { //ignore illegal characters
921 multInt_(x,base);
922 addInt_(x,d);
923 }
924 }
925
926 for (k=x.length;k>0 && !x[k-1];k--); //strip off leading zeros
927 k=minSize>k+1 ? minSize : k+1;
928 y=new Array(k);
929 kk=k<x.length ? k : x.length;
930 for (i=0;i<kk;i++)
931 y[i]=x[i];
932 for (;i<k;i++)
933 y[i]=0;
934 return y;
935}
936
937//is bigint x equal to integer y?
938//y must have less than bpe bits
939function equalsInt(x,y) {
940 var i;
941 if (x[0]!=y)
942 return 0;
943 for (i=1;i<x.length;i++)
944 if (x[i])
945 return 0;
946 return 1;
947}
948
949//are bigints x and y equal?
950//this works even if x and y are different lengths and have arbitrarily many leading zeros
951function equals(x,y) {
952 var i;
953 var k=x.length<y.length ? x.length : y.length;
954 for (i=0;i<k;i++)
955 if (x[i]!=y[i])
956 return 0;
957 if (x.length>y.length) {
958 for (;i<x.length;i++)
959 if (x[i])
960 return 0;
961 } else {
962 for (;i<y.length;i++)
963 if (y[i])
964 return 0;
965 }
966 return 1;
967}
968
969//is the bigInt x equal to zero?
970function isZero(x) {
971 var i;
972 for (i=0;i<x.length;i++)
973 if (x[i])
974 return 0;
975 return 1;
976}
977
978//convert a bigInt into a string in a given base, from base 2 up to base 95.
979//Base -1 prints the contents of the array representing the number.
980function bigInt2str(x,base) {
981 var i,t,s="";
982
983 if (s6.length!=x.length)
984 s6=dup(x);
985 else
986 copy_(s6,x);
987
988 if (base==-1) { //return the list of array contents
989 for (i=x.length-1;i>0;i--)
990 s+=x[i]+',';
991 s+=x[0];
992 }
993 else { //return it in the given base
994 while (!isZero(s6)) {
995 t=divInt_(s6,base); //t=s6 % base; s6=floor(s6/base);
996 s=digitsStr.substring(t,t+1)+s;
997 }
998 }
999 if (s.length==0)
1000 s="0";
1001 return s;
1002}
1003
1004//returns a duplicate of bigInt x
1005function dup(x) {
1006 var i;
1007 buff=new Array(x.length);
1008 copy_(buff,x);
1009 return buff;
1010}
1011
1012//do x=y on bigInts x and y. x must be an array at least as big as y (not counting the leading zeros in y).
1013function copy_(x,y) {
1014 var i;
1015 var k=x.length<y.length ? x.length : y.length;
1016 for (i=0;i<k;i++)
1017 x[i]=y[i];
1018 for (i=k;i<x.length;i++)
1019 x[i]=0;
1020}
1021
1022//do x=y on bigInt x and integer y.
1023function copyInt_(x,n) {
1024 var i,c;
1025 for (c=n,i=0;i<x.length;i++) {
1026 x[i]=c & mask;
1027 c>>=bpe;
1028 }
1029}
1030
1031//do x=x+n where x is a bigInt and n is an integer.
1032//x must be large enough to hold the result.
1033function addInt_(x,n) {
1034 var i,k,c,b;
1035 x[0]+=n;
1036 k=x.length;
1037 c=0;
1038 for (i=0;i<k;i++) {
1039 c+=x[i];
1040 b=0;
1041 if (c<0) {
1042 b=-(c>>bpe);
1043 c+=b*radix;
1044 }
1045 x[i]=c & mask;
1046 c=(c>>bpe)-b;
1047 if (!c) return; //stop carrying as soon as the carry_ is zero
1048 }
1049}
1050
1051//right shift bigInt x by n bits. 0 <= n < bpe.
1052function rightShift_(x,n) {
1053 var i;
1054 var k=Math.floor(n/bpe);
1055 if (k) {
1056 for (i=0;i<x.length-k;i++) //right shift x by k elements
1057 x[i]=x[i+k];
1058 for (;i<x.length;i++)
1059 x[i]=0;
1060 n%=bpe;
1061 }
1062 for (i=0;i<x.length-1;i++) {
1063 x[i]=mask & ((x[i+1]<<(bpe-n)) | (x[i]>>n));
1064 }
1065 x[i]>>=n;
1066}
1067
1068//do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
1069function halve_(x) {
1070 var i;
1071 for (i=0;i<x.length-1;i++) {
1072 x[i]=mask & ((x[i+1]<<(bpe-1)) | (x[i]>>1));
1073 }
1074 x[i]=(x[i]>>1) | (x[i] & (radix>>1)); //most significant bit stays the same
1075}
1076
1077//left shift bigInt x by n bits.
1078function leftShift_(x,n) {
1079 var i;
1080 var k=Math.floor(n/bpe);
1081 if (k) {
1082 for (i=x.length; i>=k; i--) //left shift x by k elements
1083 x[i]=x[i-k];
1084 for (;i>=0;i--)
1085 x[i]=0;
1086 n%=bpe;
1087 }
1088 if (!n)
1089 return;
1090 for (i=x.length-1;i>0;i--) {
1091 x[i]=mask & ((x[i]<<n) | (x[i-1]>>(bpe-n)));
1092 }
1093 x[i]=mask & (x[i]<<n);
1094}
1095
1096//do x=x*n where x is a bigInt and n is an integer.
1097//x must be large enough to hold the result.
1098function multInt_(x,n) {
1099 var i,k,c,b;
1100 if (!n)
1101 return;
1102 k=x.length;
1103 c=0;
1104 for (i=0;i<k;i++) {
1105 c+=x[i]*n;
1106 b=0;
1107 if (c<0) {
1108 b=-(c>>bpe);
1109 c+=b*radix;
1110 }
1111 x[i]=c & mask;
1112 c=(c>>bpe)-b;
1113 }
1114}
1115
1116//do x=floor(x/n) for bigInt x and integer n, and return the remainder
1117function divInt_(x,n) {
1118 var i,r=0,s;
1119 for (i=x.length-1;i>=0;i--) {
1120 s=r*radix+x[i];
1121 x[i]=Math.floor(s/n);
1122 r=s%n;
1123 }
1124 return r;
1125}
1126
1127//do the linear combination x=a*x+b*y for bigInts x and y, and integers a and b.
1128//x must be large enough to hold the answer.
1129function linComb_(x,y,a,b) {
1130 var i,c,k,kk;
1131 k=x.length<y.length ? x.length : y.length;
1132 kk=x.length;
1133 for (c=0,i=0;i<k;i++) {
1134 c+=a*x[i]+b*y[i];
1135 x[i]=c & mask;
1136 c>>=bpe;
1137 }
1138 for (i=k;i<kk;i++) {
1139 c+=a*x[i];
1140 x[i]=c & mask;
1141 c>>=bpe;
1142 }
1143}
1144
1145//do the linear combination x=a*x+b*(y<<(ys*bpe)) for bigInts x and y, and integers a, b and ys.
1146//x must be large enough to hold the answer.
1147function linCombShift_(x,y,b,ys) {
1148 var i,c,k,kk;
1149 k=x.length<ys+y.length ? x.length : ys+y.length;
1150 kk=x.length;
1151 for (c=0,i=ys;i<k;i++) {
1152 c+=x[i]+b*y[i-ys];
1153 x[i]=c & mask;
1154 c>>=bpe;
1155 }
1156 for (i=k;c && i<kk;i++) {
1157 c+=x[i];
1158 x[i]=c & mask;
1159 c>>=bpe;
1160 }
1161}
1162
1163//do x=x+(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
1164//x must be large enough to hold the answer.
1165function addShift_(x,y,ys) {
1166 var i,c,k,kk;
1167 k=x.length<ys+y.length ? x.length : ys+y.length;
1168 kk=x.length;
1169 for (c=0,i=ys;i<k;i++) {
1170 c+=x[i]+y[i-ys];
1171 x[i]=c & mask;
1172 c>>=bpe;
1173 }
1174 for (i=k;c && i<kk;i++) {
1175 c+=x[i];
1176 x[i]=c & mask;
1177 c>>=bpe;
1178 }
1179}
1180
1181//do x=x-(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
1182//x must be large enough to hold the answer.
1183function subShift_(x,y,ys) {
1184 var i,c,k,kk;
1185 k=x.length<ys+y.length ? x.length : ys+y.length;
1186 kk=x.length;
1187 for (c=0,i=ys;i<k;i++) {
1188 c+=x[i]-y[i-ys];
1189 x[i]=c & mask;
1190 c>>=bpe;
1191 }
1192 for (i=k;c && i<kk;i++) {
1193 c+=x[i];
1194 x[i]=c & mask;
1195 c>>=bpe;
1196 }
1197}
1198
1199//do x=x-y for bigInts x and y.
1200//x must be large enough to hold the answer.
1201//negative answers will be 2s complement
1202function sub_(x,y) {
1203 var i,c,k,kk;
1204 k=x.length<y.length ? x.length : y.length;
1205 for (c=0,i=0;i<k;i++) {
1206 c+=x[i]-y[i];
1207 x[i]=c & mask;
1208 c>>=bpe;
1209 }
1210 for (i=k;c && i<x.length;i++) {
1211 c+=x[i];
1212 x[i]=c & mask;
1213 c>>=bpe;
1214 }
1215}
1216
1217//do x=x+y for bigInts x and y.
1218//x must be large enough to hold the answer.
1219function add_(x,y) {
1220 var i,c,k,kk;
1221 k=x.length<y.length ? x.length : y.length;
1222 for (c=0,i=0;i<k;i++) {
1223 c+=x[i]+y[i];
1224 x[i]=c & mask;
1225 c>>=bpe;
1226 }
1227 for (i=k;c && i<x.length;i++) {
1228 c+=x[i];
1229 x[i]=c & mask;
1230 c>>=bpe;
1231 }
1232}
1233
1234//do x=x*y for bigInts x and y. This is faster when y<x.
1235function mult_(x,y) {
1236 var i;
1237 if (ss.length!=2*x.length)
1238 ss=new Array(2*x.length);
1239 copyInt_(ss,0);
1240 for (i=0;i<y.length;i++)
1241 if (y[i])
1242 linCombShift_(ss,x,y[i],i); //ss=1*ss+y[i]*(x<<(i*bpe))
1243 copy_(x,ss);
1244}
1245
1246//do x=x mod n for bigInts x and n.
1247function mod_(x,n) {
1248 if (s4.length!=x.length)
1249 s4=dup(x);
1250 else
1251 copy_(s4,x);
1252 if (s5.length!=x.length)
1253 s5=dup(x);
1254 divide_(s4,n,s5,x); //x = remainder of s4 / n
1255}
1256
1257//do x=x*y mod n for bigInts x,y,n.
1258//for greater speed, let y<x.
1259function multMod_(x,y,n) {
1260 var i;
1261 if (s0.length!=2*x.length)
1262 s0=new Array(2*x.length);
1263 copyInt_(s0,0);
1264 for (i=0;i<y.length;i++)
1265 if (y[i])
1266 linCombShift_(s0,x,y[i],i); //s0=1*s0+y[i]*(x<<(i*bpe))
1267 mod_(s0,n);
1268 copy_(x,s0);
1269}
1270
1271//do x=x*x mod n for bigInts x,n.
1272function squareMod_(x,n) {
1273 var i,j,d,c,kx,kn,k;
1274 for (kx=x.length; kx>0 && !x[kx-1]; kx--); //ignore leading zeros in x
1275 k=kx>n.length ? 2*kx : 2*n.length; //k=# elements in the product, which is twice the elements in the larger of x and n
1276 if (s0.length!=k)
1277 s0=new Array(k);
1278 copyInt_(s0,0);
1279 for (i=0;i<kx;i++) {
1280 c=s0[2*i]+x[i]*x[i];
1281 s0[2*i]=c & mask;
1282 c>>=bpe;
1283 for (j=i+1;j<kx;j++) {
1284 c=s0[i+j]+2*x[i]*x[j]+c;
1285 s0[i+j]=(c & mask);
1286 c>>=bpe;
1287 }
1288 s0[i+kx]=c;
1289 }
1290 mod_(s0,n);
1291 copy_(x,s0);
1292}
1293
1294//return x with exactly k leading zero elements
1295function trim(x,k) {
1296 var i,y;
1297 for (i=x.length; i>0 && !x[i-1]; i--);
1298 y=new Array(i+k);
1299 copy_(y,x);
1300 return y;
1301}
1302
1303//do x=x**y mod n, where x,y,n are bigInts and ** is exponentiation. 0**0=1.
1304//this is faster when n is odd. x usually needs to have as many elements as n.
1305function powMod_(x,y,n) {
1306 var k1,k2,kn,np;
1307 if(s7.length!=n.length)
1308 s7=dup(n);
1309
1310 //for even modulus, use a simple square-and-multiply algorithm,
1311 //rather than using the more complex Montgomery algorithm.
1312 if ((n[0]&1)==0) {
1313 copy_(s7,x);
1314 copyInt_(x,1);
1315 while(!equalsInt(y,0)) {
1316 if (y[0]&1)
1317 multMod_(x,s7,n);
1318 divInt_(y,2);
1319 squareMod_(s7,n);
1320 }
1321 return;
1322 }
1323
1324 //calculate np from n for the Montgomery multiplications
1325 copyInt_(s7,0);
1326 for (kn=n.length;kn>0 && !n[kn-1];kn--);
1327 np=radix-inverseModInt_(modInt(n,radix),radix);
1328 s7[kn]=1;
1329 multMod_(x ,s7,n); // x = x * 2**(kn*bp) mod n
1330
1331 if (s3.length!=x.length)
1332 s3=dup(x);
1333 else
1334 copy_(s3,x);
1335
1336 for (k1=y.length-1;k1>0 & !y[k1]; k1--); //k1=first nonzero element of y
1337 if (y[k1]==0) { //anything to the 0th power is 1
1338 copyInt_(x,1);
1339 return;
1340 }
1341 for (k2=1<<(bpe-1);k2 && !(y[k1] & k2); k2>>=1); //k2=position of first 1 bit in y[k1]
1342 for (;;) {
1343 if (!(k2>>=1)) { //look at next bit of y
1344 k1--;
1345 if (k1<0) {
1346 mont_(x,one,n,np);
1347 return;
1348 }
1349 k2=1<<(bpe-1);
1350 }
1351 mont_(x,x,n,np);
1352
1353 if (k2 & y[k1]) //if next bit is a 1
1354 mont_(x,s3,n,np);
1355 }
1356}
1357
1358//do x=x*y*Ri mod n for bigInts x,y,n,
1359// where Ri = 2**(-kn*bpe) mod n, and kn is the
1360// number of elements in the n array, not
1361// counting leading zeros.
1362//x must be large enough to hold the answer.
1363//It's OK if x and y are the same variable.
1364//must have:
1365// x,y < n
1366// n is odd
1367// np = -(n^(-1)) mod radix
1368function mont_(x,y,n,np) {
1369 var i,j,c,ui,t;
1370 var kn=n.length;
1371 var ky=y.length;
1372
1373 if (sa.length!=kn)
1374 sa=new Array(kn);
1375
1376 for (;kn>0 && n[kn-1]==0;kn--); //ignore leading zeros of n
1377 //this function sometimes gives wrong answers when the next line is uncommented
1378 //for (;ky>0 && y[ky-1]==0;ky--); //ignore leading zeros of y
1379
1380 copyInt_(sa,0);
1381
1382 //the following loop consumes 95% of the runtime for randTruePrime_() and powMod_() for large keys
1383 for (i=0; i<kn; i++) {
1384 t=sa[0]+x[i]*y[0];
1385 ui=((t & mask) * np) & mask; //the inner "& mask" is needed on Macintosh MSIE, but not windows MSIE
1386 c=(t+ui*n[0]) >> bpe;
1387 t=x[i];
1388
1389 //do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe
1390 for (j=1;j<ky;j++) {
1391 c+=sa[j]+t*y[j]+ui*n[j];
1392 sa[j-1]=c & mask;
1393 c>>=bpe;
1394 }
1395 for (;j<kn;j++) {
1396 c+=sa[j]+ui*n[j];
1397 sa[j-1]=c & mask;
1398 c>>=bpe;
1399 }
1400 sa[j-1]=c & mask;
1401 }
1402
1403 if (!greater(n,sa))
1404 sub_(sa,n);
1405 copy_(x,sa);
1406}
1407
1408
1409
1410
1411//#############################################################################
1412//#############################################################################
1413//#############################################################################
1414//#############################################################################
1415//#############################################################################
1416//#############################################################################
1417//#############################################################################
1418
1419
1420
1421
1422
1423//#############################################################################
1424
1425Clipperz.Crypto.BigInt = function (aValue, aBase) {
1426 varbase;
1427 varvalue;
1428
1429 if (typeof(aValue) == 'object') {
1430 this._internalValue = aValue;
1431 } else {
1432 if (typeof(aValue) == 'undefined') {
1433 value = "0";
1434 } else {
1435 value = aValue + "";
1436 }
1437
1438 if (typeof(aBase) == 'undefined') {
1439 base = 10;
1440 } else {
1441 base = aBase;
1442 }
1443
1444 this._internalValue = str2bigInt(value, base, 1, 1);
1445 }
1446
1447 return this;
1448}
1449
1450//=============================================================================
1451
1452MochiKit.Base.update(Clipperz.Crypto.BigInt.prototype, {
1453
1454 //-------------------------------------------------------------------------
1455
1456 'internalValue': function () {
1457 return this._internalValue;
1458 },
1459
1460 //-------------------------------------------------------------------------
1461
1462 'isBigInt': true,
1463
1464 //-------------------------------------------------------------------------
1465
1466 'toString': function(aBase) {
1467 return this.asString(aBase);
1468 },
1469
1470 //-------------------------------------------------------------------------
1471
1472 'asString': function (aBase) {
1473 varbase;
1474
1475 if (typeof(aBase) == 'undefined') {
1476 base = 10;
1477 } else {
1478 base = aBase;
1479 }
1480
1481 return bigInt2str(this.internalValue(), base).toLowerCase();
1482 },
1483
1484 //-------------------------------------------------------------------------
1485
1486 'equals': function (aValue) {
1487 var result;
1488
1489 if (aValue.isBigInt) {
1490 result = equals(this.internalValue(), aValue.internalValue());
1491 } else if (typeof(aValue) == "number") {
1492 result = equalsInt(this.internalValue(), aValue);
1493 } else {
1494 throw Clipperz.Crypt.BigInt.exception.UnknownType;
1495 }
1496
1497 return result;
1498 },
1499
1500 //-------------------------------------------------------------------------
1501
1502 'add': function (aValue) {
1503 var result;
1504
1505 if (aValue.isBigInt) {
1506 result = add(this.internalValue(), aValue.internalValue());
1507 } else {
1508 result = addInt(this.internalValue(), aValue);
1509 }
1510
1511 return new Clipperz.Crypto.BigInt(result);
1512 },
1513
1514 //-------------------------------------------------------------------------
1515
1516 'subtract': function (aValue) {
1517 var result;
1518 var value;
1519
1520 if (aValue.isBigInt) {
1521 value = aValue;
1522 } else {
1523 value = new Clipperz.Crypto.BigInt(aValue);
1524 }
1525
1526 result = sub(this.internalValue(), value.internalValue());
1527
1528 return new Clipperz.Crypto.BigInt(result);
1529 },
1530
1531 //-------------------------------------------------------------------------
1532
1533 'multiply': function (aValue, aModule) {
1534 var result;
1535 var value;
1536
1537 if (aValue.isBigInt) {
1538 value = aValue;
1539 } else {
1540 value = new Clipperz.Crypto.BigInt(aValue);
1541 }
1542
1543 if (typeof(aModule) == 'undefined') {
1544 result = mult(this.internalValue(), value.internalValue());
1545 } else {
1546 result = multMod(this.internalValue(), value.internalValue(), aModule);
1547 }
1548
1549 return new Clipperz.Crypto.BigInt(result);
1550 },
1551
1552 //-------------------------------------------------------------------------
1553
1554 'module': function (aModule) {
1555 varresult;
1556 var module;
1557
1558 if (aModule.isBigInt) {
1559 module = aModule;
1560 } else {
1561 module = new Clipperz.Crypto.BigInt(aModule);
1562 }
1563
1564 result = mod(this.internalValue(), module.internalValue());
1565
1566 return new Clipperz.Crypto.BigInt(result);
1567 },
1568
1569 //-------------------------------------------------------------------------
1570
1571 'powerModule': function(aValue, aModule) {
1572 varresult;
1573 varvalue;
1574 var module;
1575
1576 if (aValue.isBigInt) {
1577 value = aValue;
1578 } else {
1579 value = new Clipperz.Crypto.BigInt(aValue);
1580 }
1581
1582 if (aModule.isBigInt) {
1583 module = aModule;
1584 } else {
1585 module = new Clipperz.Crypto.BigInt(aModule);
1586 }
1587
1588 if (aValue == -1) {
1589 result = inverseMod(this.internalValue(), module.internalValue());
1590 } else {
1591 result = powMod(this.internalValue(), value.internalValue(), module.internalValue());
1592 }
1593
1594 return new Clipperz.Crypto.BigInt(result);
1595 },
1596
1597 //-------------------------------------------------------------------------
1598
1599 'bitSize': function() {
1600 return bitSize(this.internalValue());
1601 },
1602
1603 //-------------------------------------------------------------------------
1604 __syntaxFix__: "syntax fix"
1605
1606});
1607
1608//#############################################################################
1609
1610Clipperz.Crypto.BigInt.randomPrime = function(aBitSize) {
1611 return new Clipperz.Crypto.BigInt(randTruePrime(aBitSize));
1612}
1613
1614//#############################################################################
1615//#############################################################################
1616//#############################################################################
1617
1618Clipperz.Crypto.BigInt.equals = function(a, b) {
1619 return a.equals(b);
1620}
1621
1622Clipperz.Crypto.BigInt.add = function(a, b) {
1623 return a.add(b);
1624}
1625
1626Clipperz.Crypto.BigInt.subtract = function(a, b) {
1627 return a.subtract(b);
1628}
1629
1630Clipperz.Crypto.BigInt.multiply = function(a, b, module) {
1631 return a.multiply(b, module);
1632}
1633
1634Clipperz.Crypto.BigInt.module = function(a, module) {
1635 return a.module(module);
1636}
1637
1638Clipperz.Crypto.BigInt.powerModule = function(a, b, module) {
1639 return a.powerModule(b, module);
1640}
1641
1642Clipperz.Crypto.BigInt.exception = {
1643 UnknownType: new MochiKit.Base.NamedError("Clipperz.Crypto.BigInt.exception.UnknownType")
1644}
diff --git a/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js
new file mode 100644
index 0000000..0d76b9c
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js
@@ -0,0 +1,500 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 //throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
26//}
27if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
28if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
29
30Clipperz.Crypto.ECC.BinaryField.Curve = function(args) {
31 args = args || {};
32
33 this._modulus = args.modulus;
34
35 this._a = args.a;
36 this._b = args.b;
37 this._G = args.G;
38 this._r = args.r;
39 this._h = args.h;
40
41 this._finiteField = null;
42
43 return this;
44}
45
46Clipperz.Crypto.ECC.BinaryField.Curve.prototype = MochiKit.Base.update(null, {
47
48 'asString': function() {
49 return "Clipperz.Crypto.ECC.BinaryField.Curve";
50 },
51
52 //-----------------------------------------------------------------------------
53
54 'modulus': function() {
55 return this._modulus;
56 },
57
58 'a': function() {
59 return this._a;
60 },
61
62 'b': function() {
63 return this._b;
64 },
65
66 'G': function() {
67 return this._G;
68 },
69
70 'r': function() {
71 return this._r;
72 },
73
74 'h': function() {
75 return this._h;
76 },
77
78 //-----------------------------------------------------------------------------
79
80 'finiteField': function() {
81 if (this._finiteField == null) {
82 this._finiteField = new Clipperz.Crypto.ECC.BinaryField.FiniteField({modulus:this.modulus()})
83 }
84
85 return this._finiteField;
86 },
87
88 //-----------------------------------------------------------------------------
89
90 'negate': function(aPointA) {
91 var result;
92
93 result = new Clipperz.Crypto.ECC.Point({x:aPointA.x(), y:this.finiteField().add(aPointA.y(), aPointA.x())})
94
95 return result;
96 },
97
98 //-----------------------------------------------------------------------------
99
100 'add': function(aPointA, aPointB) {
101 var result;
102
103 if (aPointA.isZero()) {
104 result = aPointB;
105 } else if (aPointB.isZero()) {
106 result = aPointA;
107 } else if ((aPointA.x().compare(aPointB.x()) == 0) && ((aPointA.y().compare(aPointB.y()) != 0) || aPointB.x().isZero())) {
108 result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
109 } else {
110 varf2m;
111 var x, y;
112 var lambda;
113 var aX, aY, bX, bY;
114
115 aX = aPointA.x()._value;
116 aY = aPointA.y()._value;
117 bX = aPointB.x()._value;
118 bY = aPointB.y()._value;
119
120 f2m = this.finiteField();
121
122 if (aPointA.x().compare(aPointB.x()) != 0) {
123 lambda =f2m._fastMultiply(
124 f2m._add(aY, bY),
125 f2m._inverse(f2m._add(aX, bX))
126 );
127 x = f2m._add(this.a()._value, f2m._square(lambda));
128 f2m._overwriteAdd(x, lambda);
129 f2m._overwriteAdd(x, aX);
130 f2m._overwriteAdd(x, bX);
131 } else {
132 lambda = f2m._add(bX, f2m._fastMultiply(bY, f2m._inverse(bX)));
133 x = f2m._add(this.a()._value, f2m._square(lambda));
134 f2m._overwriteAdd(x, lambda);
135 }
136
137 y = f2m._fastMultiply(f2m._add(bX, x), lambda);
138 f2m._overwriteAdd(y, x);
139 f2m._overwriteAdd(y, bY);
140
141 result = new Clipperz.Crypto.ECC.BinaryField.Point({x:new Clipperz.Crypto.ECC.BinaryField.Value(x), y:new Clipperz.Crypto.ECC.BinaryField.Value(y)})
142 }
143
144 return result;
145 },
146
147 //-----------------------------------------------------------------------------
148
149 'addTwice': function(aPointA) {
150 return this.add(aPointA, aPointA);
151 },
152
153 //-----------------------------------------------------------------------------
154
155 'overwriteAdd': function(aPointA, aPointB) {
156 if (aPointA.isZero()) {
157 // result = aPointB;
158 aPointA._x._value = aPointB._x._value;
159 aPointA._y._value = aPointB._y._value;
160 } else if (aPointB.isZero()) {
161 // result = aPointA;
162 } else if ((aPointA.x().compare(aPointB.x()) == 0) && ((aPointA.y().compare(aPointB.y()) != 0) || aPointB.x().isZero())) {
163 // result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
164 aPointA._x = Clipperz.Crypto.ECC.BinaryField.Value.O;
165 aPointA._y = Clipperz.Crypto.ECC.BinaryField.Value.O;
166 } else {
167 varf2m;
168 var x, y;
169 var lambda;
170 var aX, aY, bX, bY;
171
172 aX = aPointA.x()._value;
173 aY = aPointA.y()._value;
174 bX = aPointB.x()._value;
175 bY = aPointB.y()._value;
176
177 f2m = this.finiteField();
178
179 if (aPointA.x().compare(aPointB.x()) != 0) {
180 lambda =f2m._fastMultiply(
181 f2m._add(aY, bY),
182 f2m._inverse(f2m._add(aX, bX))
183 );
184 x = f2m._add(this.a()._value, f2m._square(lambda));
185 f2m._overwriteAdd(x, lambda);
186 f2m._overwriteAdd(x, aX);
187 f2m._overwriteAdd(x, bX);
188 } else {
189 lambda = f2m._add(bX, f2m._fastMultiply(bY, f2m._inverse(bX)));
190 x = f2m._add(this.a()._value, f2m._square(lambda));
191 f2m._overwriteAdd(x, lambda);
192 }
193
194 y = f2m._fastMultiply(f2m._add(bX, x), lambda);
195 f2m._overwriteAdd(y, x);
196 f2m._overwriteAdd(y, bY);
197
198 // result = new Clipperz.Crypto.ECC.BinaryField.Point({x:new Clipperz.Crypto.ECC.BinaryField.Value(x), y:new Clipperz.Crypto.ECC.BinaryField.Value(y)})
199 aPointA._x._value = x;
200 aPointA._y._value = y;
201
202 }
203
204 return result;
205 },
206
207 //-----------------------------------------------------------------------------
208
209 'multiply': function(aValue, aPoint) {
210 var result;
211
212//console.profile();
213 result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
214
215 if (aValue.isZero() == false) {
216 var k, Q;
217 var i;
218 var countIndex; countIndex = 0;
219
220 if (aValue.compare(Clipperz.Crypto.ECC.BinaryField.Value.O) > 0) {
221 k = aValue;
222 Q = aPoint;
223 } else {
224 Clipperz.logError("The Clipperz.Crypto.ECC.BinaryFields.Value does not work with negative values!!!!");
225 k = aValue.negate();
226 Q = this.negate(aPoint);
227 }
228
229 for (i=k.bitSize()-1; i>=0; i--) {
230 result = this.add(result, result);
231 // this.overwriteAdd(result, result);
232 if (k.isBitSet(i)) {
233 result = this.add(result, Q);
234 // this.overwriteAdd(result, Q);
235 }
236
237 // if (countIndex==100) {Clipperz.log("multiply.break"); break;} else countIndex++;
238 }
239 }
240//console.profileEnd();
241
242 return result;
243 },
244
245 //-----------------------------------------------------------------------------
246
247 'deferredMultiply': function(aValue, aPoint) {
248 var deferredResult;
249 var result;
250
251Clipperz.log(">>> deferredMultiply - value: " + aValue + ", point: " + aPoint);
252//console.profile("ECC.Curve.multiply");
253 deferredResult = new MochiKit.Async.Deferred();
254//deferredResult.addCallback(function(res) {console.profile("ECC.Curve.deferredMultiply"); return res;} );
255//deferredResult.addBoth(function(res) {Clipperz.logDebug("# 1: " + res); return res;});
256
257 result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
258//deferredResult.addBoth(function(res) {Clipperz.logDebug("# 2: " + res); return res;});
259
260 if (aValue.isZero() == false) {
261 var k, Q;
262 var i;
263 var countIndex; countIndex = 0;
264
265 if (aValue.compare(Clipperz.Crypto.ECC.BinaryField.Value.O) > 0) {
266 k = aValue;
267 Q = aPoint;
268 } else {
269 Clipperz.logError("The Clipperz.Crypto.ECC.BinaryFields.Value does not work with negative values!!!!");
270 k = aValue.negate();
271 Q = this.negate(aPoint);
272 }
273
274
275 for (i=k.bitSize()-1; i>=0; i--) {
276 deferredResult.addMethod(this, "addTwice");
277 //# result = this.add(result, result);
278 // this.overwriteAdd(result, result);
279 if (k.isBitSet(i)) {
280 deferredResult.addMethod(this, "add", Q);
281 //# result = this.add(result, Q);
282 // this.overwriteAdd(result, Q);
283 }
284 if (i%20 == 0) {deferredResult.addCallback(MochiKit.Async.wait, 0.1);}
285 }
286 }
287//#console.profileEnd();
288//deferredResult.addBoth(function(res) {console.profileEnd(); return res;});
289 deferredResult.callback(result);
290
291 //# return result;
292 return deferredResult;
293 },
294
295 //-----------------------------------------------------------------------------
296 __syntaxFix__: "syntax fix"
297});
298
299
300//#############################################################################
301
302Clipperz.Crypto.ECC.StandardCurves = {};
303
304MochiKit.Base.update(Clipperz.Crypto.ECC.StandardCurves, {
305/*
306 '_K571': null,
307 'K571': function() {
308 if (Clipperz.Crypto.ECC.StandardCurves._K571 == null) {
309 Clipperz.Crypto.ECC.StandardCurves._K571 = new Clipperz.Crypto.ECC.BinaryField.Curve({
310 modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000425', 16),
311 a: new Clipperz.Crypto.ECC.BinaryField.Value('0', 16),
312 b: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
313 G: new Clipperz.Crypto.ECC.BinaryField.Point({
314 x: new Clipperz.Crypto.ECC.BinaryField.Value('026eb7a8 59923fbc 82189631 f8103fe4 ac9ca297 0012d5d4 60248048 01841ca4 43709584 93b205e6 47da304d b4ceb08c bbd1ba39 494776fb 988b4717 4dca88c7 e2945283 a01c8972', 16),
315 y: new Clipperz.Crypto.ECC.BinaryField.Value('0349dc80 7f4fbf37 4f4aeade 3bca9531 4dd58cec 9f307a54 ffc61efc 006d8a2c 9d4979c0 ac44aea7 4fbebbb9 f772aedc b620b01a 7ba7af1b 320430c8 591984f6 01cd4c14 3ef1c7a3', 16)
316 }),
317 r: new Clipperz.Crypto.ECC.BinaryField.Value('02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 131850e1 f19a63e4 b391a8db 917f4138 b630d84b e5d63938 1e91deb4 5cfe778f 637c1001', 16),
318 h: new Clipperz.Crypto.ECC.BinaryField.Value('4', 16)
319 });
320 }
321
322 return Clipperz.Crypto.ECC.StandardCurves._K571;
323 },
324
325
326
327 '_K283': null,
328 'K283': function() { //f(z) = z^283 + z^12 + z^7 + z^5 + 1
329 if (Clipperz.Crypto.ECC.StandardCurves._K283 == null) {
330 Clipperz.Crypto.ECC.StandardCurves._K283 = new Clipperz.Crypto.ECC.BinaryField.Curve({
331 modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
332 a: new Clipperz.Crypto.ECC.BinaryField.Value('0', 16),
333 b: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
334 G: new Clipperz.Crypto.ECC.BinaryField.Point({
335 x: new Clipperz.Crypto.ECC.BinaryField.Value('0503213f 78ca4488 3f1a3b81 62f188e5 53cd265f 23c1567a 16876913 b0c2ac24 58492836', 16),
336 y: new Clipperz.Crypto.ECC.BinaryField.Value('01ccda38 0f1c9e31 8d90f95d 07e5426f e87e45c0 e8184698 e4596236 4e341161 77dd2259', 16)
337 }),
338 r: new Clipperz.Crypto.ECC.BinaryField.Value('01ffffff ffffffff ffffffff ffffffff ffffe9ae 2ed07577 265dff7f 94451e06 1e163c61', 16),
339 h: new Clipperz.Crypto.ECC.BinaryField.Value('4', 16)
340 });
341 }
342
343 return Clipperz.Crypto.ECC.StandardCurves._K283;
344 },
345*/
346 //-----------------------------------------------------------------------------
347
348 '_B571': null,
349 'B571': function() { //f(z) = z^571 + z^10 + z^5 + z^2 + 1
350 if (Clipperz.Crypto.ECC.StandardCurves._B571 == null) {
351 Clipperz.Crypto.ECC.StandardCurves._B571 = new Clipperz.Crypto.ECC.BinaryField.Curve({
352 modulus: new Clipperz.Crypto.ECC.BinaryField.Value('80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425', 16),
353 a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
354 b: new Clipperz.Crypto.ECC.BinaryField.Value('02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a', 16),
355 G: new Clipperz.Crypto.ECC.BinaryField.Point({
356 x: new Clipperz.Crypto.ECC.BinaryField.Value('0303001d 34b85629 6c16c0d4 0d3cd775 0a93d1d2 955fa80a a5f40fc8 db7b2abd bde53950 f4c0d293 cdd711a3 5b67fb14 99ae6003 8614f139 4abfa3b4 c850d927 e1e7769c 8eec2d19', 16),
357 y: new Clipperz.Crypto.ECC.BinaryField.Value('037bf273 42da639b 6dccfffe b73d69d7 8c6c27a6 009cbbca 1980f853 3921e8a6 84423e43 bab08a57 6291af8f 461bb2a8 b3531d2f 0485c19b 16e2f151 6e23dd3c 1a4827af 1b8ac15b', 16)
358 }),
359 r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff e661ce18 ff559873 08059b18 6823851e c7dd9ca1 161de93d 5174d66e 8382e9bb 2fe84e47', 16),
360 h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
361
362 // S: new Clipperz.Crypto.ECC.BinaryField.Value('2aa058f73a0e33ab486b0f610410c53a7f132310', 10),
363 // n: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 16)
364 });
365
366 //-----------------------------------------------------------------------------
367 //
368 //Guide to Elliptic Curve Cryptography
369 //Darrel Hankerson, Alfred Menezes, Scott Vanstone
370 //- Pag: 56, Alorithm 2.45 (with a typo!!!)
371 //
372 //-----------------------------------------------------------------------------
373 //
374 // http://www.milw0rm.com/papers/136
375 //
376 // -------------------------------------------------------------------------
377 // Polynomial Reduction Algorithm Modulo f571
378 // -------------------------------------------------------------------------
379 //
380 // Input: Polynomial p(x) of degree 1140 or less, stored as
381 // an array of 2T machinewords.
382 // Output: p(x) mod f571(x)
383 //
384 // FOR i = T-1, ..., 0 DO
385 // SET X := P[i+T]
386 // P[i] := P[i] ^ (X<<5) ^ (X<<7) ^ (X<<10) ^ (X<<15)
387 // P[i+1] := P[i+1] ^ (X>>17) ^ (X>>22) ^ (X>>25) ^ (X>>27)
388 //
389 // SET X := P[T-1] >> 27
390 // P[0] := P[0] ^ X ^ (X<<2) ^ (X<<5) ^ (X<<10)
391 // P[T-1] := P[T-1] & 0x07ffffff
392 //
393 // RETURN P[T-1],...,P[0]
394 //
395 // -------------------------------------------------------------------------
396 //
397 Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module;
398 Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module = function(aValue) {
399 varresult;
400
401 if (aValue.bitSize() > 1140) {
402 Clipperz.logWarning("ECC.StandarCurves.B571.finiteField().module: falling back to default implementation");
403 result = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule(aValue);
404 } else {
405 varC, T;
406 var i;
407
408 C = aValue._value.slice(0);
409 for (i=35; i>=18; i--) {
410 T = C[i];
411 C[i-18] = (((C[i-18] ^ (T<<5) ^ (T<<7) ^ (T<<10) ^ (T<<15)) & 0xffffffff) >>> 0);
412 C[i-17] = ((C[i-17] ^ (T>>>27) ^ (T>>>25) ^ (T>>>22) ^ (T>>>17)) >>> 0);
413 }
414 T = (C[17] >>> 27);
415 C[0] = ((C[0] ^ T ^ ((T<<2) ^ (T<<5) ^ (T<<10)) & 0xffffffff) >>> 0);
416 C[17] = (C[17] & 0x07ffffff);
417
418 for(i=18; i<=35; i++) {
419 C[i] = 0;
420 }
421
422 result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
423 }
424
425 return result;
426 };
427 }
428
429 return Clipperz.Crypto.ECC.StandardCurves._B571;
430 },
431
432 //-----------------------------------------------------------------------------
433
434 '_B283': null,
435 'B283': function() { //f(z) = z^283 + z^12 + z^7 + z^5 + 1
436 if (Clipperz.Crypto.ECC.StandardCurves._B283 == null) {
437 Clipperz.Crypto.ECC.StandardCurves._B283 = new Clipperz.Crypto.ECC.BinaryField.Curve({
438 // modulus: new Clipperz.Crypto.ECC.BinaryField.Value('10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
439 modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
440 a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
441 b: new Clipperz.Crypto.ECC.BinaryField.Value('027b680a c8b8596d a5a4af8a 19a0303f ca97fd76 45309fa2 a581485a f6263e31 3b79a2f5', 16),
442 G: new Clipperz.Crypto.ECC.BinaryField.Point({
443 x: new Clipperz.Crypto.ECC.BinaryField.Value('05f93925 8db7dd90 e1934f8c 70b0dfec 2eed25b8 557eac9c 80e2e198 f8cdbecd 86b12053', 16),
444 y: new Clipperz.Crypto.ECC.BinaryField.Value('03676854 fe24141c b98fe6d4 b20d02b4 516ff702 350eddb0 826779c8 13f0df45 be8112f4', 16)
445 }),
446 r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffef90 399660fc 938a9016 5b042a7c efadb307', 16),
447 h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
448
449 // S: new Clipperz.Crypto.ECC.BinaryField.Value('2aa058f73a0e33ab486b0f610410c53a7f132310', 10),
450 // n: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 16)
451 });
452
453 //-----------------------------------------------------------------------------
454 //
455 //Guide to Elliptic Curve Cryptography
456 //Darrel Hankerson, Alfred Menezes, Scott Vanstone
457 //- Pag: 56, Alorithm 2.43
458 //
459 //-----------------------------------------------------------------------------
460 Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module;
461 Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module = function(aValue) {
462 varresult;
463
464 if (aValue.bitSize() > 564) {
465 Clipperz.logWarning("ECC.StandarCurves.B283.finiteField().module: falling back to default implementation");
466 result = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule(aValue);
467 } else {
468 varC, T;
469 var i;
470
471 C = aValue._value.slice(0);
472 for (i=17; i>=9; i--) {
473 T = C[i];
474 C[i-9] = (((C[i-9] ^ (T<<5) ^ (T<<10) ^ (T<<12) ^ (T<<17)) & 0xffffffff) >>> 0);
475 C[i-8] = ((C[i-8] ^ (T>>>27) ^ (T>>>22) ^ (T>>>20) ^ (T>>>15)) >>> 0);
476 }
477 T = (C[8] >>> 27);
478 C[0] = ((C[0] ^ T ^ ((T<<5) ^ (T<<7) ^ (T<<12)) & 0xffffffff) >>> 0);
479 C[8] = (C[8] & 0x07ffffff);
480
481 for(i=9; i<=17; i++) {
482 C[i] = 0;
483 }
484
485 result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
486 }
487
488 return result;
489 };
490 }
491
492 return Clipperz.Crypto.ECC.StandardCurves._B283;
493 },
494
495 //-----------------------------------------------------------------------------
496 __syntaxFix__: "syntax fix"
497});
498
499//#############################################################################
500
diff --git a/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js
new file mode 100644
index 0000000..7b7c2c6
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js
@@ -0,0 +1,519 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 //throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
26//}
27if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
28if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
29
30Clipperz.Crypto.ECC.BinaryField.FiniteField = function(args) {
31 args = args || {};
32 this._modulus = args.modulus;
33
34 return this;
35}
36
37Clipperz.Crypto.ECC.BinaryField.FiniteField.prototype = MochiKit.Base.update(null, {
38
39 'asString': function() {
40 return "Clipperz.Crypto.ECC.BinaryField.FiniteField (" + this.modulus().asString() + ")";
41 },
42
43 //-----------------------------------------------------------------------------
44
45 'modulus': function() {
46 return this._modulus;
47 },
48
49 //-----------------------------------------------------------------------------
50
51 '_module': function(aValue) {
52 varresult;
53 var modulusComparison;
54
55 modulusComparison = Clipperz.Crypto.ECC.BinaryField.Value._compare(aValue, this.modulus()._value);
56
57 if (modulusComparison < 0) {
58 result = aValue;
59 } else if (modulusComparison == 0) {
60 result = [0];
61 } else {
62 var modulusBitSize;
63 var resultBitSize;
64
65 result = aValue;
66
67 modulusBitSize = this.modulus().bitSize();
68 resultBitSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(result);
69 while (resultBitSize >= modulusBitSize) {
70 Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(result, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(this.modulus()._value, resultBitSize - modulusBitSize));
71 resultBitSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(result);
72 }
73 }
74
75 return result;
76 },
77
78 'module': function(aValue) {
79 return new Clipperz.Crypto.ECC.BinaryField.Value(this._module(aValue._value.slice(0)));
80 },
81
82 //-----------------------------------------------------------------------------
83
84 '_add': function(a, b) {
85 return Clipperz.Crypto.ECC.BinaryField.Value._xor(a, b);
86 },
87
88 '_overwriteAdd': function(a, b) {
89 Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(a, b);
90 },
91
92 'add': function(a, b) {
93 return new Clipperz.Crypto.ECC.BinaryField.Value(this._add(a._value, b._value));
94 },
95
96 //-----------------------------------------------------------------------------
97
98 'negate': function(aValue) {
99 return aValue.clone();
100 },
101
102 //-----------------------------------------------------------------------------
103
104 '_multiply': function(a, b) {
105 var result;
106 var valueToXor;
107 var i,c;
108
109 result = [0];
110 valueToXor = b;
111 c = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(a);
112 for (i=0; i<c; i++) {
113 if (Clipperz.Crypto.ECC.BinaryField.Value._isBitSet(a, i) === true) {
114 Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(result, valueToXor);
115 }
116 valueToXor = Clipperz.Crypto.ECC.BinaryField.Value._overwriteShiftLeft(valueToXor, 1);
117 }
118 result = this._module(result);
119
120 return result;
121 },
122
123 'multiply': function(a, b) {
124 return new Clipperz.Crypto.ECC.BinaryField.Value(this._multiply(a._value, b._value));
125 },
126
127 //-----------------------------------------------------------------------------
128
129 '_fastMultiply': function(a, b) {
130 var result;
131 var B;
132 var i,c;
133
134 result = [0];
135 B = b.slice(0); //Is this array copy avoidable?
136 c = 32;
137 for (i=0; i<c; i++) {
138 var ii, cc;
139
140 cc = a.length;
141 for (ii=0; ii<cc; ii++) {
142 if (((a[ii] >>> i) & 0x01) == 1) {
143 Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(result, B, ii);
144 }
145 }
146
147 if (i < (c-1)) {
148 B = Clipperz.Crypto.ECC.BinaryField.Value._overwriteShiftLeft(B, 1);
149 }
150 }
151 result = this._module(result);
152
153 return result;
154 },
155
156 'fastMultiply': function(a, b) {
157 return new Clipperz.Crypto.ECC.BinaryField.Value(this._fastMultiply(a._value, b._value));
158 },
159
160 //-----------------------------------------------------------------------------
161 //
162 //Guide to Elliptic Curve Cryptography
163 //Darrel Hankerson, Alfred Menezes, Scott Vanstone
164 //- Pag: 49, Alorithm 2.34
165 //
166 //-----------------------------------------------------------------------------
167
168 '_square': function(aValue) {
169 var result;
170 var value;
171 var c,i;
172 var precomputedValues;
173
174 value = aValue;
175 result = new Array(value.length * 2);
176 precomputedValues = Clipperz.Crypto.ECC.BinaryField.FiniteField.squarePrecomputedBytes;
177
178 c = value.length;
179 for (i=0; i<c; i++) {
180 result[i*2] = precomputedValues[(value[i] & 0x000000ff)];
181 result[i*2] |= ((precomputedValues[(value[i] & 0x0000ff00) >>> 8]) << 16);
182
183 result[i*2 + 1] = precomputedValues[(value[i] & 0x00ff0000) >>> 16];
184 result[i*2 + 1] |= ((precomputedValues[(value[i] & 0xff000000) >>> 24]) << 16);
185 }
186
187 return this._module(result);
188 },
189
190 'square': function(aValue) {
191 return new Clipperz.Crypto.ECC.BinaryField.Value(this._square(aValue._value));
192 },
193
194 //-----------------------------------------------------------------------------
195
196 '_inverse': function(aValue) {
197 varresult;
198 var b, c;
199 var u, v;
200
201 // b = Clipperz.Crypto.ECC.BinaryField.Value.I._value;
202 b = [1];
203 // c = Clipperz.Crypto.ECC.BinaryField.Value.O._value;
204 c = [0];
205 u = this._module(aValue);
206 v = this.modulus()._value.slice(0);
207
208 while (Clipperz.Crypto.ECC.BinaryField.Value._bitSize(u) > 1) {
209 varbitDifferenceSize;
210
211 bitDifferenceSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(u) - Clipperz.Crypto.ECC.BinaryField.Value._bitSize(v);
212 if (bitDifferenceSize < 0) {
213 var swap;
214
215 swap = u;
216 u = v;
217 v = swap;
218
219 swap = c;
220 c = b;
221 b = swap;
222
223 bitDifferenceSize = -bitDifferenceSize;
224 }
225
226 u = this._add(u, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(v, bitDifferenceSize));
227 b = this._add(b, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(c, bitDifferenceSize));
228 // this._overwriteAdd(u, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(v, bitDifferenceSize));
229 // this._overwriteAdd(b, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(c, bitDifferenceSize));
230 }
231
232 result = this._module(b);
233
234 return result;
235 },
236
237 'inverse': function(aValue) {
238 return new Clipperz.Crypto.ECC.BinaryField.Value(this._inverse(aValue._value));
239 },
240
241 //-----------------------------------------------------------------------------
242 __syntaxFix__: "syntax fix"
243});
244
245
246Clipperz.Crypto.ECC.BinaryField.FiniteField.squarePrecomputedBytes = [
247 0x0000, // 0 = 0000 0000 -> 0000 0000 0000 0000
248 0x0001, // 1 = 0000 0001 -> 0000 0000 0000 0001
249 0x0004, // 2 = 0000 0010 -> 0000 0000 0000 0100
250 0x0005, // 3 = 0000 0011 -> 0000 0000 0000 0101
251 0x0010, // 4 = 0000 0100 -> 0000 0000 0001 0000
252 0x0011, // 5 = 0000 0101 -> 0000 0000 0001 0001
253 0x0014, // 6 = 0000 0110 -> 0000 0000 0001 0100
254 0x0015, // 7 = 0000 0111 -> 0000 0000 0001 0101
255 0x0040, // 8 = 0000 1000 -> 0000 0000 0100 0000
256 0x0041, // 9 = 0000 1001 -> 0000 0000 0100 0001
257 0x0044, // 10 = 0000 1010 -> 0000 0000 0100 0100
258 0x0045, // 11 = 0000 1011 -> 0000 0000 0100 0101
259 0x0050, // 12 = 0000 1100 -> 0000 0000 0101 0000
260 0x0051, // 13 = 0000 1101 -> 0000 0000 0101 0001
261 0x0054, // 14 = 0000 1110 -> 0000 0000 0101 0100
262 0x0055, // 15 = 0000 1111 -> 0000 0000 0101 0101
263
264 0x0100, // 16 = 0001 0000 -> 0000 0001 0000 0000
265 0x0101, // 17 = 0001 0001 -> 0000 0001 0000 0001
266 0x0104, // 18 = 0001 0010 -> 0000 0001 0000 0100
267 0x0105, // 19 = 0001 0011 -> 0000 0001 0000 0101
268 0x0110, // 20 = 0001 0100 -> 0000 0001 0001 0000
269 0x0111, // 21 = 0001 0101 -> 0000 0001 0001 0001
270 0x0114, // 22 = 0001 0110 -> 0000 0001 0001 0100
271 0x0115, // 23 = 0001 0111 -> 0000 0001 0001 0101
272 0x0140, // 24 = 0001 1000 -> 0000 0001 0100 0000
273 0x0141, // 25 = 0001 1001 -> 0000 0001 0100 0001
274 0x0144, // 26 = 0001 1010 -> 0000 0001 0100 0100
275 0x0145, // 27 = 0001 1011 -> 0000 0001 0100 0101
276 0x0150, // 28 = 0001 1100 -> 0000 0001 0101 0000
277 0x0151, // 28 = 0001 1101 -> 0000 0001 0101 0001
278 0x0154, // 30 = 0001 1110 -> 0000 0001 0101 0100
279 0x0155, // 31 = 0001 1111 -> 0000 0001 0101 0101
280
281 0x0400, // 32 = 0010 0000 -> 0000 0100 0000 0000
282 0x0401, // 33 = 0010 0001 -> 0000 0100 0000 0001
283 0x0404, // 34 = 0010 0010 -> 0000 0100 0000 0100
284 0x0405, // 35 = 0010 0011 -> 0000 0100 0000 0101
285 0x0410, // 36 = 0010 0100 -> 0000 0100 0001 0000
286 0x0411, // 37 = 0010 0101 -> 0000 0100 0001 0001
287 0x0414, // 38 = 0010 0110 -> 0000 0100 0001 0100
288 0x0415, // 39 = 0010 0111 -> 0000 0100 0001 0101
289 0x0440, // 40 = 0010 1000 -> 0000 0100 0100 0000
290 0x0441, // 41 = 0010 1001 -> 0000 0100 0100 0001
291 0x0444, // 42 = 0010 1010 -> 0000 0100 0100 0100
292 0x0445, // 43 = 0010 1011 -> 0000 0100 0100 0101
293 0x0450, // 44 = 0010 1100 -> 0000 0100 0101 0000
294 0x0451, // 45 = 0010 1101 -> 0000 0100 0101 0001
295 0x0454, // 46 = 0010 1110 -> 0000 0100 0101 0100
296 0x0455, // 47 = 0010 1111 -> 0000 0100 0101 0101
297
298 0x0500, // 48 = 0011 0000 -> 0000 0101 0000 0000
299 0x0501, // 49 = 0011 0001 -> 0000 0101 0000 0001
300 0x0504, // 50 = 0011 0010 -> 0000 0101 0000 0100
301 0x0505, // 51 = 0011 0011 -> 0000 0101 0000 0101
302 0x0510, // 52 = 0011 0100 -> 0000 0101 0001 0000
303 0x0511, // 53 = 0011 0101 -> 0000 0101 0001 0001
304 0x0514, // 54 = 0011 0110 -> 0000 0101 0001 0100
305 0x0515, // 55 = 0011 0111 -> 0000 0101 0001 0101
306 0x0540, // 56 = 0011 1000 -> 0000 0101 0100 0000
307 0x0541, // 57 = 0011 1001 -> 0000 0101 0100 0001
308 0x0544, // 58 = 0011 1010 -> 0000 0101 0100 0100
309 0x0545, // 59 = 0011 1011 -> 0000 0101 0100 0101
310 0x0550, // 60 = 0011 1100 -> 0000 0101 0101 0000
311 0x0551, // 61 = 0011 1101 -> 0000 0101 0101 0001
312 0x0554, // 62 = 0011 1110 -> 0000 0101 0101 0100
313 0x0555, // 63 = 0011 1111 -> 0000 0101 0101 0101
314
315 0x1000, // 64 = 0100 0000 -> 0001 0000 0000 0000
316 0x1001, // 65 = 0100 0001 -> 0001 0000 0000 0001
317 0x1004, // 66 = 0100 0010 -> 0001 0000 0000 0100
318 0x1005, // 67 = 0100 0011 -> 0001 0000 0000 0101
319 0x1010, // 68 = 0100 0100 -> 0001 0000 0001 0000
320 0x1011, // 69 = 0100 0101 -> 0001 0000 0001 0001
321 0x1014, // 70 = 0100 0110 -> 0001 0000 0001 0100
322 0x1015, // 71 = 0100 0111 -> 0001 0000 0001 0101
323 0x1040, // 72 = 0100 1000 -> 0001 0000 0100 0000
324 0x1041, // 73 = 0100 1001 -> 0001 0000 0100 0001
325 0x1044, // 74 = 0100 1010 -> 0001 0000 0100 0100
326 0x1045, // 75 = 0100 1011 -> 0001 0000 0100 0101
327 0x1050, // 76 = 0100 1100 -> 0001 0000 0101 0000
328 0x1051, // 77 = 0100 1101 -> 0001 0000 0101 0001
329 0x1054, // 78 = 0100 1110 -> 0001 0000 0101 0100
330 0x1055, // 79 = 0100 1111 -> 0001 0000 0101 0101
331
332 0x1100, // 80 = 0101 0000 -> 0001 0001 0000 0000
333 0x1101, // 81 = 0101 0001 -> 0001 0001 0000 0001
334 0x1104, // 82 = 0101 0010 -> 0001 0001 0000 0100
335 0x1105, // 83 = 0101 0011 -> 0001 0001 0000 0101
336 0x1110, // 84 = 0101 0100 -> 0001 0001 0001 0000
337 0x1111, // 85 = 0101 0101 -> 0001 0001 0001 0001
338 0x1114, // 86 = 0101 0110 -> 0001 0001 0001 0100
339 0x1115, // 87 = 0101 0111 -> 0001 0001 0001 0101
340 0x1140, // 88 = 0101 1000 -> 0001 0001 0100 0000
341 0x1141, // 89 = 0101 1001 -> 0001 0001 0100 0001
342 0x1144, // 90 = 0101 1010 -> 0001 0001 0100 0100
343 0x1145, // 91 = 0101 1011 -> 0001 0001 0100 0101
344 0x1150, // 92 = 0101 1100 -> 0001 0001 0101 0000
345 0x1151, // 93 = 0101 1101 -> 0001 0001 0101 0001
346 0x1154, // 94 = 0101 1110 -> 0001 0001 0101 0100
347 0x1155, // 95 = 0101 1111 -> 0001 0001 0101 0101
348
349 0x1400, // 96 = 0110 0000 -> 0001 0100 0000 0000
350 0x1401, // 97 = 0110 0001 -> 0001 0100 0000 0001
351 0x1404, // 98 = 0110 0010 -> 0001 0100 0000 0100
352 0x1405, // 99 = 0110 0011 -> 0001 0100 0000 0101
353 0x1410, //100 = 0110 0100 -> 0001 0100 0001 0000
354 0x1411, //101 = 0110 0101 -> 0001 0100 0001 0001
355 0x1414, //102 = 0110 0110 -> 0001 0100 0001 0100
356 0x1415, //103 = 0110 0111 -> 0001 0100 0001 0101
357 0x1440, //104 = 0110 1000 -> 0001 0100 0100 0000
358 0x1441, //105 = 0110 1001 -> 0001 0100 0100 0001
359 0x1444, //106 = 0110 1010 -> 0001 0100 0100 0100
360 0x1445, //107 = 0110 1011 -> 0001 0100 0100 0101
361 0x1450, //108 = 0110 1100 -> 0001 0100 0101 0000
362 0x1451, //109 = 0110 1101 -> 0001 0100 0101 0001
363 0x1454, //110 = 0110 1110 -> 0001 0100 0101 0100
364 0x1455, //111 = 0110 1111 -> 0001 0100 0101 0101
365
366 0x1500, //112 = 0111 0000 -> 0001 0101 0000 0000
367 0x1501, //113 = 0111 0001 -> 0001 0101 0000 0001
368 0x1504, //114 = 0111 0010 -> 0001 0101 0000 0100
369 0x1505, //115 = 0111 0011 -> 0001 0101 0000 0101
370 0x1510, //116 = 0111 0100 -> 0001 0101 0001 0000
371 0x1511, //117 = 0111 0101 -> 0001 0101 0001 0001
372 0x1514, //118 = 0111 0110 -> 0001 0101 0001 0100
373 0x1515, //119 = 0111 0111 -> 0001 0101 0001 0101
374 0x1540, //120 = 0111 1000 -> 0001 0101 0100 0000
375 0x1541, //121 = 0111 1001 -> 0001 0101 0100 0001
376 0x1544, //122 = 0111 1010 -> 0001 0101 0100 0100
377 0x1545, //123 = 0111 1011 -> 0001 0101 0100 0101
378 0x1550, //124 = 0111 1100 -> 0001 0101 0101 0000
379 0x1551, //125 = 0111 1101 -> 0001 0101 0101 0001
380 0x1554, //126 = 0111 1110 -> 0001 0101 0101 0100
381 0x1555, //127 = 0111 1111 -> 0001 0101 0101 0101
382
383 0x4000, //128 = 1000 0000 -> 0100 0000 0000 0000
384 0x4001, //129 = 1000 0001 -> 0100 0000 0000 0001
385 0x4004, //130 = 1000 0010 -> 0100 0000 0000 0100
386 0x4005, //131 = 1000 0011 -> 0100 0000 0000 0101
387 0x4010, //132 = 1000 0100 -> 0100 0000 0001 0000
388 0x4011, //133 = 1000 0101 -> 0100 0000 0001 0001
389 0x4014, //134 = 1000 0110 -> 0100 0000 0001 0100
390 0x4015, //135 = 1000 0111 -> 0100 0000 0001 0101
391 0x4040, //136 = 1000 1000 -> 0100 0000 0100 0000
392 0x4041, //137 = 1000 1001 -> 0100 0000 0100 0001
393 0x4044, //138 = 1000 1010 -> 0100 0000 0100 0100
394 0x4045, //139 = 1000 1011 -> 0100 0000 0100 0101
395 0x4050, //140 = 1000 1100 -> 0100 0000 0101 0000
396 0x4051, //141 = 1000 1101 -> 0100 0000 0101 0001
397 0x4054, //142 = 1000 1110 -> 0100 0000 0101 0100
398 0x4055, //143 = 1000 1111 -> 0100 0000 0101 0101
399
400 0x4100, //144 = 1001 0000 -> 0100 0001 0000 0000
401 0x4101, //145 = 1001 0001 -> 0100 0001 0000 0001
402 0x4104, //146 = 1001 0010 -> 0100 0001 0000 0100
403 0x4105, //147 = 1001 0011 -> 0100 0001 0000 0101
404 0x4110, //148 = 1001 0100 -> 0100 0001 0001 0000
405 0x4111, //149 = 1001 0101 -> 0100 0001 0001 0001
406 0x4114, //150 = 1001 0110 -> 0100 0001 0001 0100
407 0x4115, //151 = 1001 0111 -> 0100 0001 0001 0101
408 0x4140, //152 = 1001 1000 -> 0100 0001 0100 0000
409 0x4141, //153 = 1001 1001 -> 0100 0001 0100 0001
410 0x4144, //154 = 1001 1010 -> 0100 0001 0100 0100
411 0x4145, //155 = 1001 1011 -> 0100 0001 0100 0101
412 0x4150, //156 = 1001 1100 -> 0100 0001 0101 0000
413 0x4151, //157 = 1001 1101 -> 0100 0001 0101 0001
414 0x4154, //158 = 1001 1110 -> 0100 0001 0101 0100
415 0x4155, //159 = 1001 1111 -> 0100 0001 0101 0101
416
417 0x4400, //160 = 1010 0000 -> 0100 0100 0000 0000
418 0x4401, //161 = 1010 0001 -> 0100 0100 0000 0001
419 0x4404, //162 = 1010 0010 -> 0100 0100 0000 0100
420 0x4405, //163 = 1010 0011 -> 0100 0100 0000 0101
421 0x4410, //164 = 1010 0100 -> 0100 0100 0001 0000
422 0x4411, //165 = 1010 0101 -> 0100 0100 0001 0001
423 0x4414, //166 = 1010 0110 -> 0100 0100 0001 0100
424 0x4415, //167 = 1010 0111 -> 0100 0100 0001 0101
425 0x4440, //168 = 1010 1000 -> 0100 0100 0100 0000
426 0x4441, //169 = 1010 1001 -> 0100 0100 0100 0001
427 0x4444, //170 = 1010 1010 -> 0100 0100 0100 0100
428 0x4445, //171 = 1010 1011 -> 0100 0100 0100 0101
429 0x4450, //172 = 1010 1100 -> 0100 0100 0101 0000
430 0x4451, //173 = 1010 1101 -> 0100 0100 0101 0001
431 0x4454, //174 = 1010 1110 -> 0100 0100 0101 0100
432 0x4455, //175 = 1010 1111 -> 0100 0100 0101 0101
433
434 0x4500, //176 = 1011 0000 -> 0100 0101 0000 0000
435 0x4501, //177 = 1011 0001 -> 0100 0101 0000 0001
436 0x4504, //178 = 1011 0010 -> 0100 0101 0000 0100
437 0x4505, //179 = 1011 0011 -> 0100 0101 0000 0101
438 0x4510, //180 = 1011 0100 -> 0100 0101 0001 0000
439 0x4511, //181 = 1011 0101 -> 0100 0101 0001 0001
440 0x4514, //182 = 1011 0110 -> 0100 0101 0001 0100
441 0x4515, //183 = 1011 0111 -> 0100 0101 0001 0101
442 0x4540, //184 = 1011 1000 -> 0100 0101 0100 0000
443 0x4541, //185 = 1011 1001 -> 0100 0101 0100 0001
444 0x4544, //186 = 1011 1010 -> 0100 0101 0100 0100
445 0x4545, //187 = 1011 1011 -> 0100 0101 0100 0101
446 0x4550, //188 = 1011 1100 -> 0100 0101 0101 0000
447 0x4551, //189 = 1011 1101 -> 0100 0101 0101 0001
448 0x4554, //190 = 1011 1110 -> 0100 0101 0101 0100
449 0x4555, //191 = 1011 1111 -> 0100 0101 0101 0101
450
451 0x5000, //192 = 1100 0000 -> 0101 0000 0000 0000
452 0x5001, //193 = 1100 0001 -> 0101 0000 0000 0001
453 0x5004, //194 = 1100 0010 -> 0101 0000 0000 0100
454 0x5005, //195 = 1100 0011 -> 0101 0000 0000 0101
455 0x5010, //196 = 1100 0100 -> 0101 0000 0001 0000
456 0x5011, //197 = 1100 0101 -> 0101 0000 0001 0001
457 0x5014, //198 = 1100 0110 -> 0101 0000 0001 0100
458 0x5015, //199 = 1100 0111 -> 0101 0000 0001 0101
459 0x5040, //200 = 1100 1000 -> 0101 0000 0100 0000
460 0x5041, //201 = 1100 1001 -> 0101 0000 0100 0001
461 0x5044, //202 = 1100 1010 -> 0101 0000 0100 0100
462 0x5045, //203 = 1100 1011 -> 0101 0000 0100 0101
463 0x5050, //204 = 1100 1100 -> 0101 0000 0101 0000
464 0x5051, //205 = 1100 1101 -> 0101 0000 0101 0001
465 0x5054, //206 = 1100 1110 -> 0101 0000 0101 0100
466 0x5055, //207 = 1100 1111 -> 0101 0000 0101 0101
467
468 0x5100, //208 = 1101 0000 -> 0101 0001 0000 0000
469 0x5101, //209 = 1101 0001 -> 0101 0001 0000 0001
470 0x5104, //210 = 1101 0010 -> 0101 0001 0000 0100
471 0x5105, //211 = 1101 0011 -> 0101 0001 0000 0101
472 0x5110, //212 = 1101 0100 -> 0101 0001 0001 0000
473 0x5111, //213 = 1101 0101 -> 0101 0001 0001 0001
474 0x5114, //214 = 1101 0110 -> 0101 0001 0001 0100
475 0x5115, //215 = 1101 0111 -> 0101 0001 0001 0101
476 0x5140, //216 = 1101 1000 -> 0101 0001 0100 0000
477 0x5141, //217 = 1101 1001 -> 0101 0001 0100 0001
478 0x5144, //218 = 1101 1010 -> 0101 0001 0100 0100
479 0x5145, //219 = 1101 1011 -> 0101 0001 0100 0101
480 0x5150, //220 = 1101 1100 -> 0101 0001 0101 0000
481 0x5151, //221 = 1101 1101 -> 0101 0001 0101 0001
482 0x5154, //222 = 1101 1110 -> 0101 0001 0101 0100
483 0x5155, //223 = 1101 1111 -> 0101 0001 0101 0101
484
485 0x5400, //224 = 1110 0000 -> 0101 0100 0000 0000
486 0x5401, //225 = 1110 0001 -> 0101 0100 0000 0001
487 0x5404, //226 = 1110 0010 -> 0101 0100 0000 0100
488 0x5405, //227 = 1110 0011 -> 0101 0100 0000 0101
489 0x5410, //228 = 1110 0100 -> 0101 0100 0001 0000
490 0x5411, //229 = 1110 0101 -> 0101 0100 0001 0001
491 0x5414, //230 = 1110 0110 -> 0101 0100 0001 0100
492 0x5415, //231 = 1110 0111 -> 0101 0100 0001 0101
493 0x5440, //232 = 1110 1000 -> 0101 0100 0100 0000
494 0x5441, //233 = 1110 1001 -> 0101 0100 0100 0001
495 0x5444, //234 = 1110 1010 -> 0101 0100 0100 0100
496 0x5445, //235 = 1110 1011 -> 0101 0100 0100 0101
497 0x5450, //236 = 1110 1100 -> 0101 0100 0101 0000
498 0x5451, //237 = 1110 1101 -> 0101 0100 0101 0001
499 0x5454, //238 = 1110 1110 -> 0101 0100 0101 0100
500 0x5455, //239 = 1110 1111 -> 0101 0100 0101 0101
501
502 0x5500, //240 = 1111 0000 -> 0101 0101 0000 0000
503 0x5501, //241 = 1111 0001 -> 0101 0101 0000 0001
504 0x5504, //242 = 1111 0010 -> 0101 0101 0000 0100
505 0x5505, //243 = 1111 0011 -> 0101 0101 0000 0101
506 0x5510, //244 = 1111 0100 -> 0101 0101 0001 0000
507 0x5511, //245 = 1111 0101 -> 0101 0101 0001 0001
508 0x5514, //246 = 1111 0110 -> 0101 0101 0001 0100
509 0x5515, //247 = 1111 0111 -> 0101 0101 0001 0101
510 0x5540, //248 = 1111 1000 -> 0101 0101 0100 0000
511 0x5541, //249 = 1111 1001 -> 0101 0101 0100 0001
512 0x5544, //250 = 1111 1010 -> 0101 0101 0100 0100
513 0x5545, //251 = 1111 1011 -> 0101 0101 0100 0101
514 0x5550, //252 = 1111 1100 -> 0101 0101 0101 0000
515 0x5551, //253 = 1111 1101 -> 0101 0101 0101 0001
516 0x5554, //254 = 1111 1110 -> 0101 0101 0101 0100
517 0x5555 //255 = 1111 1111 -> 0101 0101 0101 0101
518
519]
diff --git a/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Point.js b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Point.js
new file mode 100644
index 0000000..fef3220
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Point.js
@@ -0,0 +1,62 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 //throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
26//}
27if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
28if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
29
30Clipperz.Crypto.ECC.BinaryField.Point = function(args) {
31 args = args || {};
32 this._x = args.x;
33 this._y = args.y;
34
35 return this;
36}
37
38Clipperz.Crypto.ECC.BinaryField.Point.prototype = MochiKit.Base.update(null, {
39
40 'asString': function() {
41 return "Clipperz.Crypto.ECC.BinaryField.Point (" + this.x() + ", " + this.y() + ")";
42 },
43
44 //-----------------------------------------------------------------------------
45
46 'x': function() {
47 return this._x;
48 },
49
50 'y': function() {
51 return this._y;
52 },
53
54 //-----------------------------------------------------------------------------
55
56 'isZero': function() {
57 return (this.x().isZero() && this.y().isZero())
58 },
59
60 //-----------------------------------------------------------------------------
61 __syntaxFix__: "syntax fix"
62});
diff --git a/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Value.js b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Value.js
new file mode 100644
index 0000000..634772a
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Value.js
@@ -0,0 +1,379 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 //throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
26//}
27if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
28if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
29if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
30if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
31
32Clipperz.Crypto.ECC.BinaryField.Value = function(aValue, aBase, aBitSize) {
33 if (aValue.constructor == String) {
34 varvalue;
35 varstringLength;
36 var numberOfWords;
37 vari,c;
38
39 if (aBase != 16) {
40 throw Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedBase;
41 }
42
43 value = aValue.replace(/ /g, '');
44 stringLength = value.length;
45 numberOfWords = Math.ceil(stringLength / 8);
46 this._value = new Array(numberOfWords);
47
48 c = numberOfWords;
49 for (i=0; i<c; i++) {
50 varword;
51
52 if (i < (c-1)) {
53 word = parseInt(value.substr(stringLength-((i+1)*8), 8), 16);
54 } else {
55 word = parseInt(value.substr(0, stringLength-(i*8)), 16);
56 }
57
58 this._value[i] = word;
59 }
60 } else if (aValue.constructor == Array) {
61 var itemsToCopy;
62
63 itemsToCopy = aValue.length;
64 while (aValue[itemsToCopy - 1] == 0) {
65 itemsToCopy --;
66 }
67
68 this._value = aValue.slice(0, itemsToCopy);
69 } else if (aValue.constructor == Number) {
70 this._value = [aValue];
71 } else {
72 // throw Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedConstructorValueType;
73 }
74
75 this._bitSize == aBitSize || null;
76
77 return this;
78}
79
80Clipperz.Crypto.ECC.BinaryField.Value.prototype = MochiKit.Base.update(null, {
81
82 'value': function() {
83 return this._value;
84 },
85
86 //-----------------------------------------------------------------------------
87
88 'wordSize': function() {
89 return this._value.length
90 },
91
92 //-----------------------------------------------------------------------------
93
94 'clone': function() {
95 return new Clipperz.Crypto.ECC.BinaryField.Value(this._value.slice(0), null, this._bitSize);
96 },
97
98 //-----------------------------------------------------------------------------
99
100 'isZero': function() {
101 return (this.compare(Clipperz.Crypto.ECC.BinaryField.Value.O) == 0);
102 },
103
104 //-----------------------------------------------------------------------------
105
106 'asString': function(aBase) {
107 varresult;
108 var i,c;
109
110 if (aBase != 16) {
111 throw Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedBase;
112 }
113
114 result = "";
115 c = this.wordSize();
116 for (i=0; i<c; i++) {
117 varwordAsString;
118
119 // wordAsString = ("00000000" + this.value()[i].toString(16));
120 wordAsString = ("00000000" + this._value[i].toString(16));
121 wordAsString = wordAsString.substring(wordAsString.length - 8);
122 result = wordAsString + result;
123 }
124
125 result = result.replace(/^(00)*/, "");
126
127 if (result == "") {
128 result = "0";
129 }
130
131 return result;
132 },
133
134 //-----------------------------------------------------------------------------
135
136 'shiftLeft': function(aNumberOfBitsToShift) {
137 //this method seems like it is never called. :-(
138 return new Clipperz.Crypto.ECC.BinaryField.Value(Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(this._value, aNumberOfBitsToShift));
139 },
140
141 //-----------------------------------------------------------------------------
142
143 'bitSize': function() {
144 if (this._bitSize == null) {
145 this._bitSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(this._value);
146 }
147
148 return this._bitSize;
149 },
150
151 //-----------------------------------------------------------------------------
152
153 'isBitSet': function(aBitPosition) {
154 return Clipperz.Crypto.ECC.BinaryField.Value._isBitSet(this._value, aBitPosition);
155 },
156
157 //-----------------------------------------------------------------------------
158
159 'xor': function(aValue) {
160 return new Clipperz.Crypto.ECC.BinaryField.Value(Clipperz.Crypto.ECC.BinaryField.Value._xor(this._value, aValue._value));
161 },
162
163 //-----------------------------------------------------------------------------
164
165 'compare': function(aValue) {
166 return Clipperz.Crypto.ECC.BinaryField.Value._compare(this._value, aValue._value);
167 },
168
169 //-----------------------------------------------------------------------------
170 __syntaxFix__: "syntax fix"
171});
172
173Clipperz.Crypto.ECC.BinaryField.Value.O = new Clipperz.Crypto.ECC.BinaryField.Value('0', 16);
174Clipperz.Crypto.ECC.BinaryField.Value.I = new Clipperz.Crypto.ECC.BinaryField.Value('1', 16);
175
176Clipperz.Crypto.ECC.BinaryField.Value._xor = function(a, b, aFirstItemOffset) {
177 var result;
178 var resultSize;
179 var i,c;
180 var firstItemOffset;
181
182 firstItemOffset = aFirstItemOffset || 0;
183 resultSize = Math.max((a.length - firstItemOffset), b.length) + firstItemOffset;
184
185 result = new Array(resultSize);
186
187 c = firstItemOffset;
188 for (i=0; i<c; i++) {
189 result[i] = a[i];
190 }
191
192 c = resultSize;
193 for (i=firstItemOffset; i<c; i++) {
194 result[i] = (((a[i] || 0) ^ (b[i - firstItemOffset] || 0)) >>> 0);
195 }
196
197 return result;
198};
199
200Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor = function(a, b, aFirstItemOffset) {
201 var i,c;
202 var firstItemOffset;
203
204 firstItemOffset = aFirstItemOffset || 0;
205
206 c = Math.max((a.length - firstItemOffset), b.length) + firstItemOffset;
207 for (i=firstItemOffset; i<c; i++) {
208 a[i] = (((a[i] || 0) ^ (b[i - firstItemOffset] || 0)) >>> 0);
209 }
210};
211
212Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft = function(aWordArray, aNumberOfBitsToShift) {
213 var numberOfWordsToShift;
214 varnumberOfBitsToShift;
215 var result;
216 varoverflowValue;
217 var nextOverflowValue;
218 vari,c;
219
220 numberOfWordsToShift = Math.floor(aNumberOfBitsToShift / 32);
221 numberOfBitsToShift = aNumberOfBitsToShift % 32;
222
223 result = new Array(aWordArray.length + numberOfWordsToShift);
224
225 c = numberOfWordsToShift;
226 for (i=0; i<c; i++) {
227 result[i] = 0;
228 }
229
230 overflowValue = 0;
231 nextOverflowValue = 0;
232
233 c = aWordArray.length;
234 for (i=0; i<c; i++) {
235 varvalue;
236 varresultWord;
237
238 // value = this.value()[i];
239 value = aWordArray[i];
240
241 if (numberOfBitsToShift > 0) {
242 nextOverflowValue = (value >>> (32 - numberOfBitsToShift));
243 value = value & (0xffffffff >>> numberOfBitsToShift);
244 resultWord = (((value << numberOfBitsToShift) | overflowValue) >>> 0);
245 } else {
246 resultWord = value;
247 }
248
249 result[i+numberOfWordsToShift] = resultWord;
250 overflowValue = nextOverflowValue;
251 }
252
253 if (overflowValue != 0) {
254 result[aWordArray.length + numberOfWordsToShift] = overflowValue;
255 }
256
257 return result;
258};
259
260Clipperz.Crypto.ECC.BinaryField.Value._overwriteShiftLeft = function(aWordArray, aNumberOfBitsToShift) {
261 var numberOfWordsToShift;
262 varnumberOfBitsToShift;
263 var result;
264 varoverflowValue;
265 vari,c;
266
267 numberOfWordsToShift = Math.floor(aNumberOfBitsToShift / 32);
268 numberOfBitsToShift = aNumberOfBitsToShift % 32;
269
270 result = new Array(aWordArray.length + numberOfWordsToShift);
271
272 c = numberOfWordsToShift;
273 for (i=0; i<c; i++) {
274 result[i] = 0;
275 }
276
277 overflowValue = 0;
278 nextOverflowValue = 0;
279
280 c = aWordArray.length;
281 for (i=0; i<c; i++) {
282 varvalue;
283 varresultWord;
284
285 // value = this.value()[i];
286 value = aWordArray[i];
287
288 if (numberOfBitsToShift > 0) {
289 var nextOverflowValue;
290
291 nextOverflowValue = (value >>> (32 - numberOfBitsToShift));
292 value = value & (0xffffffff >>> numberOfBitsToShift);
293 resultWord = (((value << numberOfBitsToShift) | overflowValue) >>> 0);
294 } else {
295 resultWord = value;
296 }
297
298 result[i+numberOfWordsToShift] = resultWord;
299 overflowValue = nextOverflowValue;
300 }
301
302 if (overflowValue != 0) {
303 result[aWordArray.length + numberOfWordsToShift] = overflowValue;
304 }
305
306 return result;
307};
308
309Clipperz.Crypto.ECC.BinaryField.Value._bitSize = function(aWordArray) {
310 varresult;
311 varnotNullElements;
312 var mostValuableWord;
313 var matchingBitsInMostImportantWord;
314 var mask;
315 var i,c;
316
317 notNullElements = aWordArray.length;
318
319 if ((aWordArray.length == 1) && (aWordArray[0] == 0)) {
320 result = 0;
321 } else {
322 notNullElements --;
323 while((notNullElements > 0) && (aWordArray[notNullElements] == 0)) {
324 notNullElements --;
325 }
326
327 result = notNullElements * 32;
328 mostValuableWord = aWordArray[notNullElements];
329
330 matchingBits = 32;
331 mask = 0x80000000;
332
333 while ((matchingBits > 0) && ((mostValuableWord & mask) == 0)) {
334 matchingBits --;
335 mask >>>= 1;
336 }
337
338 result += matchingBits;
339 }
340
341 return result;
342};
343
344Clipperz.Crypto.ECC.BinaryField.Value._isBitSet = function(aWordArray, aBitPosition) {
345 var result;
346 varbyteIndex;
347 var bitIndexInSelectedByte;
348
349 byteIndex = Math.floor(aBitPosition / 32);
350 bitIndexInSelectedByte = aBitPosition % 32;
351
352 if (byteIndex <= aWordArray.length) {
353 result = ((aWordArray[byteIndex] & (1 << bitIndexInSelectedByte)) != 0);
354 } else {
355 result = false;
356 }
357
358 return result;
359};
360
361Clipperz.Crypto.ECC.BinaryField.Value._compare = function(a,b) {
362 varresult;
363 var i,c;
364
365 result = MochiKit.Base.compare(a.length, b.length);
366
367 c = a.length;
368 for (i=0; (i<c) && (result==0); i++) {
369 result = MochiKit.Base.compare(a[c-i-1], b[c-i-1]);
370 }
371
372 return result;
373};
374
375
376Clipperz.Crypto.ECC.BinaryField.Value['exception']= {
377 'UnsupportedBase': new MochiKit.Base.NamedError("Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedBase"),
378 'UnsupportedConstructorValueType':new MochiKit.Base.NamedError("Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedConstructorValueType")
379};
diff --git a/frontend/delta/js/Clipperz/Crypto/ECC/StandardCurves.js b/frontend/delta/js/Clipperz/Crypto/ECC/StandardCurves.js
new file mode 100644
index 0000000..239e264
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/ECC/StandardCurves.js
@@ -0,0 +1,229 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//try { if (typeof(Clipperz.Crypto.ECC.BinaryField.Curve) == 'undefined') { throw ""; }} catch (e) {
25 //throw "Clipperz.Crypto.ECC depends on Clipperz.Crypto.ECC.BinaryField.Curve!";
26//}
27//try { if (typeof(Clipperz.Crypto.ECC.Koblitz.Curve) == 'undefined') { throw ""; }} catch (e) {
28 //throw "Clipperz.Crypto.ECC depends on Clipperz.Crypto.ECC.Koblitz.Curve!";
29//}
30
31Clipperz.Crypto.ECC.StandardCurves = {};
32
33MochiKit.Base.update(Clipperz.Crypto.ECC.StandardCurves, {
34
35 //==============================================================================
36
37 '_K571': null,
38 'K571': function() { //f(z) = z^571 + z^10 + z^5 + z^2 + 1
39 if ((Clipperz.Crypto.ECC.StandardCurves._K571 == null) && (typeof(Clipperz.Crypto.ECC.Koblitz.Curve) != 'undefined')) {
40 Clipperz.Crypto.ECC.StandardCurves._K571 = new Clipperz.Crypto.ECC.Koblitz.Curve({
41 modulus: new Clipperz.Crypto.ECC.Koblitz.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000425', 16),
42 a: new Clipperz.Crypto.ECC.Koblitz.Value('0', 16),
43 b: new Clipperz.Crypto.ECC.Koblitz.Value('1', 16),
44 G: new Clipperz.Crypto.ECC.Koblitz.Point({
45 x: new Clipperz.Crypto.ECC.Koblitz.Value('026eb7a8 59923fbc 82189631 f8103fe4 ac9ca297 0012d5d4 60248048 01841ca4 43709584 93b205e6 47da304d b4ceb08c bbd1ba39 494776fb 988b4717 4dca88c7 e2945283 a01c8972', 16),
46 y: new Clipperz.Crypto.ECC.Koblitz.Value('0349dc80 7f4fbf37 4f4aeade 3bca9531 4dd58cec 9f307a54 ffc61efc 006d8a2c 9d4979c0 ac44aea7 4fbebbb9 f772aedc b620b01a 7ba7af1b 320430c8 591984f6 01cd4c14 3ef1c7a3', 16)
47 }),
48 r: new Clipperz.Crypto.ECC.Koblitz.Value('02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 131850e1 f19a63e4 b391a8db 917f4138 b630d84b e5d63938 1e91deb4 5cfe778f 637c1001', 16),
49 h: new Clipperz.Crypto.ECC.Koblitz.Value('4', 16),
50 primeFactor: new Clipperz.Crypto.ECC.Koblitz.Value('02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 131850e1 f19a63e4 b391a8db 917f4138 b630d84b e5d63938 1e91deb4 5cfe778f 637c1001', 16)
51 });
52 }
53
54 return Clipperz.Crypto.ECC.StandardCurves._K571;
55 },
56
57 //-----------------------------------------------------------------------------
58
59 '_K283': null,
60 'K283': function() { //f(z) = z^283 + z^12 + z^7 + z^5 + 1
61 if ((Clipperz.Crypto.ECC.StandardCurves._K283 == null) && (typeof(Clipperz.Crypto.ECC.Koblitz.Curve) != 'undefined')) {
62 Clipperz.Crypto.ECC.StandardCurves._K283 = new Clipperz.Crypto.ECC.Koblitz.Curve({
63 modulus: new Clipperz.Crypto.ECC.Koblitz.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
64 a: new Clipperz.Crypto.ECC.Koblitz.Value('0', 16),
65 b: new Clipperz.Crypto.ECC.Koblitz.Value('1', 16),
66 G: new Clipperz.Crypto.ECC.Koblitz.Point({
67 x: new Clipperz.Crypto.ECC.Koblitz.Value('0503213f 78ca4488 3f1a3b81 62f188e5 53cd265f 23c1567a 16876913 b0c2ac24 58492836', 16),
68 y: new Clipperz.Crypto.ECC.Koblitz.Value('01ccda38 0f1c9e31 8d90f95d 07e5426f e87e45c0 e8184698 e4596236 4e341161 77dd2259', 16)
69 }),
70 r: new Clipperz.Crypto.ECC.Koblitz.Value('01ffffff ffffffff ffffffff ffffffff ffffe9ae 2ed07577 265dff7f 94451e06 1e163c61', 16),
71 h: new Clipperz.Crypto.ECC.Koblitz.Value('4', 16),
72 primeFactor: new Clipperz.Crypto.ECC.Koblitz.Value('01ffffff ffffffff ffffffff ffffffff ffffe9ae 2ed07577 265dff7f 94451e06 1e163c61', 16)
73 });
74 }
75
76 return Clipperz.Crypto.ECC.StandardCurves._K283;
77 },
78
79 //==============================================================================
80
81 '_B571': null,
82 'B571': function() { //f(z) = z^571 + z^10 + z^5 + z^2 + 1
83 if ((Clipperz.Crypto.ECC.StandardCurves._B571 == null) && (typeof(Clipperz.Crypto.ECC.BinaryField.Curve) != 'undefined')) {
84 Clipperz.Crypto.ECC.StandardCurves._B571 = new Clipperz.Crypto.ECC.BinaryField.Curve({
85 modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000425', 16),
86 a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
87 b: new Clipperz.Crypto.ECC.BinaryField.Value('02f40e7e 2221f295 de297117 b7f3d62f 5c6a97ff cb8ceff1 cd6ba8ce 4a9a18ad 84ffabbd 8efa5933 2be7ad67 56a66e29 4afd185a 78ff12aa 520e4de7 39baca0c 7ffeff7f 2955727a', 16),
88 G: new Clipperz.Crypto.ECC.BinaryField.Point({
89 x: new Clipperz.Crypto.ECC.BinaryField.Value('0303001d 34b85629 6c16c0d4 0d3cd775 0a93d1d2 955fa80a a5f40fc8 db7b2abd bde53950 f4c0d293 cdd711a3 5b67fb14 99ae6003 8614f139 4abfa3b4 c850d927 e1e7769c 8eec2d19', 16),
90 y: new Clipperz.Crypto.ECC.BinaryField.Value('037bf273 42da639b 6dccfffe b73d69d7 8c6c27a6 009cbbca 1980f853 3921e8a6 84423e43 bab08a57 6291af8f 461bb2a8 b3531d2f 0485c19b 16e2f151 6e23dd3c 1a4827af 1b8ac15b', 16)
91 }),
92 r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff e661ce18 ff559873 08059b18 6823851e c7dd9ca1 161de93d 5174d66e 8382e9bb 2fe84e47', 16),
93 h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
94
95 // S: new Clipperz.Crypto.ECC.BinaryField.Value('2aa058f73a0e33ab486b0f610410c53a7f132310', 10),
96 // n: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 16)
97 });
98
99 //-----------------------------------------------------------------------------
100 //
101 //Guide to Elliptic Curve Cryptography
102 //Darrel Hankerson, Alfred Menezes, Scott Vanstone
103 //- Pag: 56, Alorithm 2.45 (with a typo!!!)
104 //
105 //-----------------------------------------------------------------------------
106 //
107 // http://www.milw0rm.com/papers/136
108 //
109 // -------------------------------------------------------------------------
110 // Polynomial Reduction Algorithm Modulo f571
111 // -------------------------------------------------------------------------
112 //
113 // Input: Polynomial p(x) of degree 1140 or less, stored as
114 // an array of 2T machinewords.
115 // Output: p(x) mod f571(x)
116 //
117 // FOR i = T-1, ..., 0 DO
118 // SET X := P[i+T]
119 // P[i] := P[i] ^ (X<<5) ^ (X<<7) ^ (X<<10) ^ (X<<15)
120 // P[i+1] := P[i+1] ^ (X>>17) ^ (X>>22) ^ (X>>25) ^ (X>>27)
121 //
122 // SET X := P[T-1] >> 27
123 // P[0] := P[0] ^ X ^ (X<<2) ^ (X<<5) ^ (X<<10)
124 // P[T-1] := P[T-1] & 0x07ffffff
125 //
126 // RETURN P[T-1],...,P[0]
127 //
128 // -------------------------------------------------------------------------
129 //
130 Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module;
131 Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module = function(aValue) {
132 varresult;
133
134 if (aValue.bitSize() > 1140) {
135 Clipperz.logWarning("ECC.StandarCurves.B571.finiteField().module: falling back to default implementation");
136 result = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule(aValue);
137 } else {
138 varC, T;
139 var i;
140
141 C = aValue._value.slice(0);
142 for (i=35; i>=18; i--) {
143 T = C[i];
144 C[i-18] = (((C[i-18] ^ (T<<5) ^ (T<<7) ^ (T<<10) ^ (T<<15)) & 0xffffffff) >>> 0);
145 C[i-17] = ((C[i-17] ^ (T>>>27) ^ (T>>>25) ^ (T>>>22) ^ (T>>>17)) >>> 0);
146 }
147 T = (C[17] >>> 27);
148 C[0] = ((C[0] ^ T ^ ((T<<2) ^ (T<<5) ^ (T<<10)) & 0xffffffff) >>> 0);
149 C[17] = (C[17] & 0x07ffffff);
150
151 for(i=18; i<=35; i++) {
152 C[i] = 0;
153 }
154
155 result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
156 }
157
158 return result;
159 };
160 }
161
162 return Clipperz.Crypto.ECC.StandardCurves._B571;
163 },
164
165 //-----------------------------------------------------------------------------
166
167 '_B283': null,
168 'B283': function() { //f(z) = z^283 + z^12 + z^7 + z^5 + 1
169 if ((Clipperz.Crypto.ECC.StandardCurves._B283 == null) && (typeof(Clipperz.Crypto.ECC.BinaryField.Curve) != 'undefined')) {
170 Clipperz.Crypto.ECC.StandardCurves._B283 = new Clipperz.Crypto.ECC.BinaryField.Curve({
171 modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
172 a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
173 b: new Clipperz.Crypto.ECC.BinaryField.Value('027b680a c8b8596d a5a4af8a 19a0303f ca97fd76 45309fa2 a581485a f6263e31 3b79a2f5', 16),
174 G: new Clipperz.Crypto.ECC.BinaryField.Point({
175 x: new Clipperz.Crypto.ECC.BinaryField.Value('05f93925 8db7dd90 e1934f8c 70b0dfec 2eed25b8 557eac9c 80e2e198 f8cdbecd 86b12053', 16),
176 y: new Clipperz.Crypto.ECC.BinaryField.Value('03676854 fe24141c b98fe6d4 b20d02b4 516ff702 350eddb0 826779c8 13f0df45 be8112f4', 16)
177 }),
178 r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffef90 399660fc 938a9016 5b042a7c efadb307', 16),
179 h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
180 });
181
182 //-----------------------------------------------------------------------------
183 //
184 //Guide to Elliptic Curve Cryptography
185 //Darrel Hankerson, Alfred Menezes, Scott Vanstone
186 //- Pag: 56, Alorithm 2.43
187 //
188 //-----------------------------------------------------------------------------
189 Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module;
190 Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module = function(aValue) {
191 varresult;
192
193 if (aValue.bitSize() > 564) {
194 Clipperz.logWarning("ECC.StandarCurves.B283.finiteField().module: falling back to default implementation");
195 result = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule(aValue);
196 } else {
197 varC, T;
198 var i;
199
200 C = aValue._value.slice(0);
201 for (i=17; i>=9; i--) {
202 T = C[i];
203 C[i-9] = (((C[i-9] ^ (T<<5) ^ (T<<10) ^ (T<<12) ^ (T<<17)) & 0xffffffff) >>> 0);
204 C[i-8] = ((C[i-8] ^ (T>>>27) ^ (T>>>22) ^ (T>>>20) ^ (T>>>15)) >>> 0);
205 }
206 T = (C[8] >>> 27);
207 C[0] = ((C[0] ^ T ^ ((T<<5) ^ (T<<7) ^ (T<<12)) & 0xffffffff) >>> 0);
208 C[8] = (C[8] & 0x07ffffff);
209
210 for(i=9; i<=17; i++) {
211 C[i] = 0;
212 }
213
214 result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
215 }
216
217 return result;
218 };
219 }
220
221 return Clipperz.Crypto.ECC.StandardCurves._B283;
222 },
223
224 //==============================================================================
225 __syntaxFix__: "syntax fix"
226});
227
228
229
diff --git a/frontend/delta/js/Clipperz/Crypto/PRNG.js b/frontend/delta/js/Clipperz/Crypto/PRNG.js
new file mode 100644
index 0000000..c539f06
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/PRNG.js
@@ -0,0 +1,841 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
26}
27
28try { if (typeof(Clipperz.Crypto.SHA) == 'undefined') { throw ""; }} catch (e) {
29 throw "Clipperz.Crypto.PRNG depends on Clipperz.Crypto.SHA!";
30}
31
32try { if (typeof(Clipperz.Crypto.AES) == 'undefined') { throw ""; }} catch (e) {
33 throw "Clipperz.Crypto.PRNG depends on Clipperz.Crypto.AES!";
34}
35
36if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { Clipperz.Crypto.PRNG = {}; }
37
38//#############################################################################
39
40Clipperz.Crypto.PRNG.EntropyAccumulator = function(args) {
41 args = args || {};
42 //MochiKit.Base.bindMethods(this);
43
44 this._stack = new Clipperz.ByteArray();
45 this._maxStackLengthBeforeHashing = args.maxStackLengthBeforeHashing || 256;
46 return this;
47}
48
49Clipperz.Crypto.PRNG.EntropyAccumulator.prototype = MochiKit.Base.update(null, {
50
51 'toString': function() {
52 return "Clipperz.Crypto.PRNG.EntropyAccumulator";
53 },
54
55 //-------------------------------------------------------------------------
56
57 'stack': function() {
58 return this._stack;
59 },
60
61 'setStack': function(aValue) {
62 this._stack = aValue;
63 },
64
65 'resetStack': function() {
66 this.stack().reset();
67 },
68
69 'maxStackLengthBeforeHashing': function() {
70 return this._maxStackLengthBeforeHashing;
71 },
72
73 //-------------------------------------------------------------------------
74
75 'addRandomByte': function(aValue) {
76 this.stack().appendByte(aValue);
77
78 if (this.stack().length() > this.maxStackLengthBeforeHashing()) {
79 this.setStack(Clipperz.Crypto.SHA.sha_d256(this.stack()));
80 }
81 },
82
83 //-------------------------------------------------------------------------
84 __syntaxFix__: "syntax fix"
85});
86
87//#############################################################################
88
89Clipperz.Crypto.PRNG.RandomnessSource = function(args) {
90 args = args || {};
91 MochiKit.Base.bindMethods(this);
92
93 this._generator = args.generator || null;
94 this._sourceId = args.sourceId || null;
95 this._boostMode = args.boostMode || false;
96
97 this._nextPoolIndex = 0;
98
99 return this;
100}
101
102Clipperz.Crypto.PRNG.RandomnessSource.prototype = MochiKit.Base.update(null, {
103
104 'generator': function() {
105 return this._generator;
106 },
107
108 'setGenerator': function(aValue) {
109 this._generator = aValue;
110 },
111
112 //-------------------------------------------------------------------------
113
114 'boostMode': function() {
115 return this._boostMode;
116 },
117
118 'setBoostMode': function(aValue) {
119 this._boostMode = aValue;
120 },
121
122 //-------------------------------------------------------------------------
123
124 'sourceId': function() {
125 return this._sourceId;
126 },
127
128 'setSourceId': function(aValue) {
129 this._sourceId = aValue;
130 },
131
132 //-------------------------------------------------------------------------
133
134 'nextPoolIndex': function() {
135 return this._nextPoolIndex;
136 },
137
138 'incrementNextPoolIndex': function() {
139 this._nextPoolIndex = ((this._nextPoolIndex + 1) % this.generator().numberOfEntropyAccumulators());
140 },
141
142 //-------------------------------------------------------------------------
143
144 'updateGeneratorWithValue': function(aRandomValue) {
145 if (this.generator() != null) {
146 this.generator().addRandomByte(this.sourceId(), this.nextPoolIndex(), aRandomValue);
147 this.incrementNextPoolIndex();
148 }
149 },
150
151 //-------------------------------------------------------------------------
152 __syntaxFix__: "syntax fix"
153});
154
155//#############################################################################
156
157Clipperz.Crypto.PRNG.TimeRandomnessSource = function(args) {
158 args = args || {};
159 //MochiKit.Base.bindMethods(this);
160
161 this._intervalTime = args.intervalTime || 1000;
162
163 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
164
165 this.collectEntropy();
166 return this;
167}
168
169Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
170
171 'intervalTime': function() {
172 return this._intervalTime;
173 },
174
175 //-------------------------------------------------------------------------
176
177 'collectEntropy': function() {
178 varnow;
179 varentropyByte;
180 var intervalTime;
181 now = new Date();
182 entropyByte = (now.getTime() & 0xff);
183
184 intervalTime = this.intervalTime();
185 if (this.boostMode() == true) {
186 intervalTime = intervalTime / 9;
187 }
188
189 this.updateGeneratorWithValue(entropyByte);
190 setTimeout(this.collectEntropy, intervalTime);
191 },
192
193 //-------------------------------------------------------------------------
194
195 'numberOfRandomBits': function() {
196 return 5;
197 },
198
199 //-------------------------------------------------------------------------
200
201 'pollingFrequency': function() {
202 return 10;
203 },
204
205 //-------------------------------------------------------------------------
206 __syntaxFix__: "syntax fix"
207});
208
209//*****************************************************************************
210
211Clipperz.Crypto.PRNG.MouseRandomnessSource = function(args) {
212 args = args || {};
213
214 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
215
216 this._numberOfBitsToCollectAtEachEvent = 4;
217 this._randomBitsCollector = 0;
218 this._numberOfRandomBitsCollected = 0;
219
220 MochiKit.Signal.connect(document, 'onmousemove', this, 'collectEntropy');
221
222 return this;
223}
224
225Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
226
227 //-------------------------------------------------------------------------
228
229 'numberOfBitsToCollectAtEachEvent': function() {
230 return this._numberOfBitsToCollectAtEachEvent;
231 },
232
233 //-------------------------------------------------------------------------
234
235 'randomBitsCollector': function() {
236 return this._randomBitsCollector;
237 },
238
239 'setRandomBitsCollector': function(aValue) {
240 this._randomBitsCollector = aValue;
241 },
242
243 'appendRandomBitsToRandomBitsCollector': function(aValue) {
244 var collectedBits;
245 var numberOfRandomBitsCollected;
246
247 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
248 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
249 this.setRandomBitsCollector(collectetBits);
250 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
251
252 if (numberOfRandomBitsCollected == 8) {
253 this.updateGeneratorWithValue(collectetBits);
254 numberOfRandomBitsCollected = 0;
255 this.setRandomBitsCollector(0);
256 }
257
258 this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
259 },
260
261 //-------------------------------------------------------------------------
262
263 'numberOfRandomBitsCollected': function() {
264 return this._numberOfRandomBitsCollected;
265 },
266
267 'setNumberOfRandomBitsCollected': function(aValue) {
268 this._numberOfRandomBitsCollected = aValue;
269 },
270
271 //-------------------------------------------------------------------------
272
273 'collectEntropy': function(anEvent) {
274 var mouseLocation;
275 var randomBit;
276 var mask;
277
278 mask = 0xffffffff >>> (32 - this.numberOfBitsToCollectAtEachEvent());
279
280 mouseLocation = anEvent.mouse().client;
281 randomBit = ((mouseLocation.x ^ mouseLocation.y) & mask);
282 this.appendRandomBitsToRandomBitsCollector(randomBit)
283 },
284
285 //-------------------------------------------------------------------------
286
287 'numberOfRandomBits': function() {
288 return 1;
289 },
290
291 //-------------------------------------------------------------------------
292
293 'pollingFrequency': function() {
294 return 10;
295 },
296
297 //-------------------------------------------------------------------------
298 __syntaxFix__: "syntax fix"
299});
300
301//*****************************************************************************
302
303Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) {
304 args = args || {};
305 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
306
307 this._randomBitsCollector = 0;
308 this._numberOfRandomBitsCollected = 0;
309
310 MochiKit.Signal.connect(document, 'onkeypress', this, 'collectEntropy');
311
312 return this;
313}
314
315Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
316
317 //-------------------------------------------------------------------------
318
319 'randomBitsCollector': function() {
320 return this._randomBitsCollector;
321 },
322
323 'setRandomBitsCollector': function(aValue) {
324 this._randomBitsCollector = aValue;
325 },
326
327 'appendRandomBitToRandomBitsCollector': function(aValue) {
328 var collectedBits;
329 var numberOfRandomBitsCollected;
330
331 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
332 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
333 this.setRandomBitsCollector(collectetBits);
334 numberOfRandomBitsCollected ++;
335
336 if (numberOfRandomBitsCollected == 8) {
337 this.updateGeneratorWithValue(collectetBits);
338 numberOfRandomBitsCollected = 0;
339 this.setRandomBitsCollector(0);
340 }
341
342 this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
343 },
344
345 //-------------------------------------------------------------------------
346
347 'numberOfRandomBitsCollected': function() {
348 return this._numberOfRandomBitsCollected;
349 },
350
351 'setNumberOfRandomBitsCollected': function(aValue) {
352 this._numberOfRandomBitsCollected = aValue;
353 },
354
355 //-------------------------------------------------------------------------
356
357 'collectEntropy': function(anEvent) {
358/*
359 var mouseLocation;
360 var randomBit;
361
362 mouseLocation = anEvent.mouse().client;
363
364 randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1);
365 this.appendRandomBitToRandomBitsCollector(randomBit);
366*/
367 },
368
369 //-------------------------------------------------------------------------
370
371 'numberOfRandomBits': function() {
372 return 1;
373 },
374
375 //-------------------------------------------------------------------------
376
377 'pollingFrequency': function() {
378 return 10;
379 },
380
381 //-------------------------------------------------------------------------
382 __syntaxFix__: "syntax fix"
383});
384
385//#############################################################################
386
387Clipperz.Crypto.PRNG.Fortuna = function(args) {
388 vari,c;
389
390 args = args || {};
391
392 this._key = args.seed || null;
393 if (this._key == null) {
394 this._counter = 0;
395 this._key = new Clipperz.ByteArray();
396 } else {
397 this._counter = 1;
398 }
399
400 this._aesKey = null;
401
402 this._firstPoolReseedLevel = args.firstPoolReseedLevel || 32 || 64;
403 this._numberOfEntropyAccumulators = args.numberOfEntropyAccumulators || 32;
404
405 this._accumulators = [];
406 c = this.numberOfEntropyAccumulators();
407 for (i=0; i<c; i++) {
408 this._accumulators.push(new Clipperz.Crypto.PRNG.EntropyAccumulator());
409 }
410
411 this._randomnessSources = [];
412 this._reseedCounter = 0;
413
414 return this;
415}
416
417Clipperz.Crypto.PRNG.Fortuna.prototype = MochiKit.Base.update(null, {
418
419 'toString': function() {
420 return "Clipperz.Crypto.PRNG.Fortuna";
421 },
422
423 //-------------------------------------------------------------------------
424
425 'key': function() {
426 return this._key;
427 },
428
429 'setKey': function(aValue) {
430 this._key = aValue;
431 this._aesKey = null;
432 },
433
434 'aesKey': function() {
435 if (this._aesKey == null) {
436 this._aesKey = new Clipperz.Crypto.AES.Key({key:this.key()});
437 }
438
439 return this._aesKey;
440 },
441
442 'accumulators': function() {
443 return this._accumulators;
444 },
445
446 'firstPoolReseedLevel': function() {
447 return this._firstPoolReseedLevel;
448 },
449
450 //-------------------------------------------------------------------------
451
452 'reseedCounter': function() {
453 return this._reseedCounter;
454 },
455
456 'incrementReseedCounter': function() {
457 this._reseedCounter = this._reseedCounter +1;
458 },
459
460 //-------------------------------------------------------------------------
461
462 'reseed': function() {
463 varnewKeySeed;
464 var reseedCounter;
465 varreseedCounterMask;
466 var i, c;
467
468 newKeySeed = this.key();
469 this.incrementReseedCounter();
470 reseedCounter = this.reseedCounter();
471
472 c = this.numberOfEntropyAccumulators();
473 reseedCounterMask = 0xffffffff >>> (32 - c);
474 for (i=0; i<c; i++) {
475 if ((i == 0) || ((reseedCounter & (reseedCounterMask >>> (c - i))) == 0)) {
476 newKeySeed.appendBlock(this.accumulators()[i].stack());
477 this.accumulators()[i].resetStack();
478 }
479 }
480
481 if (reseedCounter == 1) {
482 c = this.randomnessSources().length;
483 for (i=0; i<c; i++) {
484 this.randomnessSources()[i].setBoostMode(false);
485 }
486 }
487
488 this.setKey(Clipperz.Crypto.SHA.sha_d256(newKeySeed));
489 if (reseedCounter == 1) {
490Clipperz.log("### PRNG.readyToGenerateRandomBytes");
491 MochiKit.Signal.signal(this, 'readyToGenerateRandomBytes');
492 }
493 MochiKit.Signal.signal(this, 'reseeded');
494 },
495
496 //-------------------------------------------------------------------------
497
498 'isReadyToGenerateRandomValues': function() {
499 return this.reseedCounter() != 0;
500 },
501
502 //-------------------------------------------------------------------------
503
504 'entropyLevel': function() {
505 return this.accumulators()[0].stack().length() + (this.reseedCounter() * this.firstPoolReseedLevel());
506 },
507
508 //-------------------------------------------------------------------------
509
510 'counter': function() {
511 return this._counter;
512 },
513
514 'incrementCounter': function() {
515 this._counter += 1;
516 },
517
518 'counterBlock': function() {
519 var result;
520
521 result = new Clipperz.ByteArray().appendWords(this.counter(), 0, 0, 0);
522
523 return result;
524 },
525
526 //-------------------------------------------------------------------------
527
528 'getRandomBlock': function() {
529 var result;
530
531 result = new Clipperz.ByteArray(Clipperz.Crypto.AES.encryptBlock(this.aesKey(), this.counterBlock().arrayValues()));
532 this.incrementCounter();
533
534 return result;
535 },
536
537 //-------------------------------------------------------------------------
538
539 'getRandomBytes': function(aSize) {
540 var result;
541
542 if (this.isReadyToGenerateRandomValues()) {
543 var i,c;
544 var newKey;
545
546 result = new Clipperz.ByteArray();
547
548 c = Math.ceil(aSize / (128 / 8));
549 for (i=0; i<c; i++) {
550 result.appendBlock(this.getRandomBlock());
551 }
552
553 if (result.length() != aSize) {
554 result = result.split(0, aSize);
555 }
556
557 newKey = this.getRandomBlock().appendBlock(this.getRandomBlock());
558 this.setKey(newKey);
559 } else {
560Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
561 throw Clipperz.Crypto.PRNG.exception.NotEnoughEntropy;
562 }
563
564 return result;
565 },
566
567 //-------------------------------------------------------------------------
568
569 'addRandomByte': function(aSourceId, aPoolId, aRandomValue) {
570 varselectedAccumulator;
571
572 selectedAccumulator = this.accumulators()[aPoolId];
573 selectedAccumulator.addRandomByte(aRandomValue);
574
575 if (aPoolId == 0) {
576 MochiKit.Signal.signal(this, 'addedRandomByte')
577 if (selectedAccumulator.stack().length() > this.firstPoolReseedLevel()) {
578 this.reseed();
579 }
580 }
581 },
582
583 //-------------------------------------------------------------------------
584
585 'numberOfEntropyAccumulators': function() {
586 return this._numberOfEntropyAccumulators;
587 },
588
589 //-------------------------------------------------------------------------
590
591 'randomnessSources': function() {
592 return this._randomnessSources;
593 },
594
595 'addRandomnessSource': function(aRandomnessSource) {
596 aRandomnessSource.setGenerator(this);
597 aRandomnessSource.setSourceId(this.randomnessSources().length);
598 this.randomnessSources().push(aRandomnessSource);
599
600 if (this.isReadyToGenerateRandomValues() == false) {
601 aRandomnessSource.setBoostMode(true);
602 }
603 },
604
605 //-------------------------------------------------------------------------
606
607 'deferredEntropyCollection': function(aValue) {
608 var result;
609
610
611 if (this.isReadyToGenerateRandomValues()) {
612 result = aValue;
613 } else {
614 var deferredResult;
615
616 deferredResult = new Clipperz.Async.Deferred("PRNG.deferredEntropyCollection");
617 deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue));
618 MochiKit.Signal.connect(this,
619 'readyToGenerateRandomBytes',
620 deferredResult,
621 'callback');
622
623 result = deferredResult;
624 }
625
626 return result;
627 },
628
629 //-------------------------------------------------------------------------
630
631 'fastEntropyAccumulationForTestingPurpose': function() {
632 while (! this.isReadyToGenerateRandomValues()) {
633 this.addRandomByte(Math.floor(Math.random() * 32), Math.floor(Math.random() * 32), Math.floor(Math.random() * 256));
634 }
635 },
636
637 //-------------------------------------------------------------------------
638
639 'dump': function(appendToDoc) {
640 var tbl;
641 var i,c;
642
643 tbl = document.createElement("table");
644 tbl.border = 0;
645 with (tbl.style) {
646 border = "1px solid lightgrey";
647 fontFamily = 'Helvetica, Arial, sans-serif';
648 fontSize = '8pt';
649 //borderCollapse = "collapse";
650 }
651 var hdr = tbl.createTHead();
652 var hdrtr = hdr.insertRow(0);
653 // document.createElement("tr");
654 {
655 var ntd;
656
657 ntd = hdrtr.insertCell(0);
658 ntd.style.borderBottom = "1px solid lightgrey";
659 ntd.style.borderRight = "1px solid lightgrey";
660 ntd.appendChild(document.createTextNode("#"));
661
662 ntd = hdrtr.insertCell(1);
663 ntd.style.borderBottom = "1px solid lightgrey";
664 ntd.style.borderRight = "1px solid lightgrey";
665 ntd.appendChild(document.createTextNode("s"));
666
667 ntd = hdrtr.insertCell(2);
668 ntd.colSpan = this.firstPoolReseedLevel();
669 ntd.style.borderBottom = "1px solid lightgrey";
670 ntd.style.borderRight = "1px solid lightgrey";
671 ntd.appendChild(document.createTextNode("base values"));
672
673 ntd = hdrtr.insertCell(3);
674 ntd.colSpan = 20;
675 ntd.style.borderBottom = "1px solid lightgrey";
676 ntd.appendChild(document.createTextNode("extra values"));
677
678 }
679
680 c = this.accumulators().length;
681 for (i=0; i<c ; i++) {
682 varcurrentAccumulator;
683 var bdytr;
684 var bdytd;
685 var ii, cc;
686
687 currentAccumulator = this.accumulators()[i]
688
689 bdytr = tbl.insertRow(true);
690
691 bdytd = bdytr.insertCell(0);
692 bdytd.style.borderRight = "1px solid lightgrey";
693 bdytd.style.color = "lightgrey";
694 bdytd.appendChild(document.createTextNode("" + i));
695
696 bdytd = bdytr.insertCell(1);
697 bdytd.style.borderRight = "1px solid lightgrey";
698 bdytd.style.color = "gray";
699 bdytd.appendChild(document.createTextNode("" + currentAccumulator.stack().length()));
700
701
702 cc = Math.max(currentAccumulator.stack().length(), this.firstPoolReseedLevel());
703 for (ii=0; ii<cc; ii++) {
704 var cellText;
705
706 bdytd = bdytr.insertCell(ii + 2);
707
708 if (ii < currentAccumulator.stack().length()) {
709 cellText = Clipperz.ByteArray.byteToHex(currentAccumulator.stack().byteAtIndex(ii));
710 } else {
711 cellText = "_";
712 }
713
714 if (ii == (this.firstPoolReseedLevel() - 1)) {
715 bdytd.style.borderRight = "1px solid lightgrey";
716 }
717
718 bdytd.appendChild(document.createTextNode(cellText));
719 }
720
721 }
722
723
724 if (appendToDoc) {
725 var ne = document.createElement("div");
726 ne.id = "entropyGeneratorStatus";
727 with (ne.style) {
728 fontFamily = "Courier New, monospace";
729 fontSize = "12px";
730 lineHeight = "16px";
731 borderTop = "1px solid black";
732 padding = "10px";
733 }
734 if (document.getElementById(ne.id)) {
735 MochiKit.DOM.swapDOM(ne.id, ne);
736 } else {
737 document.body.appendChild(ne);
738 }
739 ne.appendChild(tbl);
740 }
741
742 return tbl;
743 },
744
745 //-----------------------------------------------------------------------------
746 __syntaxFix__: "syntax fix"
747});
748
749//#############################################################################
750
751Clipperz.Crypto.PRNG.Random = function(args) {
752 args = args || {};
753 //MochiKit.Base.bindMethods(this);
754
755 return this;
756}
757
758Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
759
760 'toString': function() {
761 return "Clipperz.Crypto.PRNG.Random";
762 },
763
764 //-------------------------------------------------------------------------
765
766 'getRandomBytes': function(aSize) {
767//Clipperz.Profile.start("Clipperz.Crypto.PRNG.Random.getRandomBytes");
768 varresult;
769 var i,c;
770
771 result = new Clipperz.ByteArray()
772 c = aSize || 1;
773 for (i=0; i<c; i++) {
774 result.appendByte((Math.random()*255) & 0xff);
775 }
776
777//Clipperz.Profile.stop("Clipperz.Crypto.PRNG.Random.getRandomBytes");
778 return result;
779 },
780
781 //-------------------------------------------------------------------------
782 __syntaxFix__: "syntax fix"
783});
784
785//#############################################################################
786
787_clipperz_crypt_prng_defaultPRNG = null;
788
789Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
790 if (_clipperz_crypt_prng_defaultPRNG == null) {
791 _clipperz_crypt_prng_defaultPRNG = new Clipperz.Crypto.PRNG.Fortuna();
792
793 //.............................................................
794 //
795 // TimeRandomnessSource
796 //
797 //.............................................................
798 {
799 var newRandomnessSource;
800
801 newRandomnessSource = new Clipperz.Crypto.PRNG.TimeRandomnessSource({intervalTime:111});
802 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
803 }
804
805 //.............................................................
806 //
807 // MouseRandomnessSource
808 //
809 //.............................................................
810 {
811 varnewRandomnessSource;
812
813 newRandomnessSource = new Clipperz.Crypto.PRNG.MouseRandomnessSource();
814 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
815 }
816
817 //.............................................................
818 //
819 // KeyboardRandomnessSource
820 //
821 //.............................................................
822 {
823 varnewRandomnessSource;
824
825 newRandomnessSource = new Clipperz.Crypto.PRNG.KeyboardRandomnessSource();
826 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
827 }
828
829 }
830
831 return _clipperz_crypt_prng_defaultPRNG;
832};
833
834//#############################################################################
835
836Clipperz.Crypto.PRNG.exception = {
837 NotEnoughEntropy: new MochiKit.Base.NamedError("Clipperz.Crypto.PRNG.exception.NotEnoughEntropy")
838};
839
840
841MochiKit.DOM.addLoadEvent(Clipperz.Crypto.PRNG.defaultRandomGenerator);
diff --git a/frontend/delta/js/Clipperz/Crypto/RSA.js b/frontend/delta/js/Clipperz/Crypto/RSA.js
new file mode 100644
index 0000000..5a480f1
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/RSA.js
@@ -0,0 +1,146 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.RSA depends on Clipperz.Crypto.BigInt!";
26}
27
28if (typeof(Clipperz.Crypto.RSA) == 'undefined') { Clipperz.Crypto.RSA = {}; }
29
30Clipperz.Crypto.RSA.VERSION = "0.1";
31Clipperz.Crypto.RSA.NAME = "Clipperz.RSA";
32
33//#############################################################################
34
35MochiKit.Base.update(Clipperz.Crypto.RSA, {
36
37 //-------------------------------------------------------------------------
38
39 'publicKeyWithValues': function (e, d, n) {
40 varresult;
41
42 result = {};
43
44 if (e.isBigInt) {
45 result.e = e;
46 } else {
47 result.e = new Clipperz.Crypto.BigInt(e, 16);
48 }
49
50 if (d.isBigInt) {
51 result.d = d;
52 } else {
53 result.d = new Clipperz.Crypto.BigInt(d, 16);
54 }
55
56 if (n.isBigInt) {
57 result.n = n;
58 } else {
59 result.n = new Clipperz.Crypto.BigInt(n, 16);
60 }
61
62 return result;
63 },
64
65 'privateKeyWithValues': function(e, d, n) {
66 return Clipperz.Crypto.RSA.publicKeyWithValues(e, d, n);
67 },
68
69 //-----------------------------------------------------------------------------
70
71 'encryptUsingPublicKey': function (aKey, aMessage) {
72 varmessageValue;
73 varresult;
74
75 messageValue = new Clipperz.Crypto.BigInt(aMessage, 16);
76 result = messageValue.powerModule(aKey.e, aKey.n);
77
78 return result.asString(16);
79 },
80
81 //.............................................................................
82
83 'decryptUsingPublicKey': function (aKey, aMessage) {
84 return Clipperz.Crypto.RSA.encryptUsingPublicKey(aKey, aMessage);
85 },
86
87 //-----------------------------------------------------------------------------
88
89 'encryptUsingPrivateKey': function (aKey, aMessage) {
90 varmessageValue;
91 varresult;
92
93 messageValue = new Clipperz.Crypto.BigInt(aMessage, 16);
94 result = messageValue.powerModule(aKey.d, aKey.n);
95
96 return result.asString(16);
97 },
98
99 //.............................................................................
100
101 'decryptUsingPrivateKey': function (aKey, aMessage) {
102 return Clipperz.Crypto.RSA.encryptUsingPrivateKey(aKey, aMessage);
103 },
104
105 //-----------------------------------------------------------------------------
106
107 'generatePublicKey': function(aNumberOfBits) {
108 varresult;
109 vare;
110 vard;
111 varn;
112
113 e = new Clipperz.Crypto.BigInt("10001", 16);
114
115 {
116 var p, q;
117 varphi;
118
119 do {
120 p = Clipperz.Crypto.BigInt.randomPrime(aNumberOfBits);
121 } while (p.module(e).equals(1));
122
123 do {
124 q = Clipperz.Crypto.BigInt.randomPrime(aNumberOfBits);
125 } while ((q.equals(p)) || (q.module(e).equals(1)));
126
127 n = p.multiply(q);
128 phi = (p.subtract(1).multiply(q.subtract(1)));
129 d = e.powerModule(-1, phi);
130 }
131
132 result = Clipperz.Crypto.RSA.publicKeyWithValues(e, d, n);
133
134 return result;
135 },
136
137 //-------------------------------------------------------------------------
138
139 __syntaxFix__: "syntax fix"
140
141 //-------------------------------------------------------------------------
142
143});
144
145//#############################################################################
146
diff --git a/frontend/delta/js/Clipperz/Crypto/SHA.js b/frontend/delta/js/Clipperz/Crypto/SHA.js
new file mode 100644
index 0000000..f8bfe6e
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/SHA.js
@@ -0,0 +1,296 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
26}
27
28if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
29if (typeof(Clipperz.Crypto.SHA) == 'undefined') { Clipperz.Crypto.SHA = {}; }
30
31Clipperz.Crypto.SHA.VERSION = "0.3";
32Clipperz.Crypto.SHA.NAME = "Clipperz.Crypto.SHA";
33
34MochiKit.Base.update(Clipperz.Crypto.SHA, {
35
36 '__repr__': function () {
37 return "[" + this.NAME + " " + this.VERSION + "]";
38 },
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-----------------------------------------------------------------------------
45
46 'rotateRight': function(aValue, aNumberOfBits) {
47//Clipperz.Profile.start("Clipperz.Crypto.SHA.rotateRight");
48 var result;
49
50 result = (aValue >>> aNumberOfBits) | (aValue << (32 - aNumberOfBits));
51
52//Clipperz.Profile.stop("Clipperz.Crypto.SHA.rotateRight");
53 return result;
54 },
55
56 'shiftRight': function(aValue, aNumberOfBits) {
57//Clipperz.Profile.start("Clipperz.Crypto.SHA.shiftRight");
58 var result;
59
60 result = aValue >>> aNumberOfBits;
61
62//Clipperz.Profile.stop("Clipperz.Crypto.SHA.shiftRight");
63 return result;
64 },
65
66 //-----------------------------------------------------------------------------
67
68 'safeAdd': function() {
69//Clipperz.Profile.start("Clipperz.Crypto.SHA.safeAdd");
70 varresult;
71 vari, c;
72
73 result = arguments[0];
74 c = arguments.length;
75 for (i=1; i<c; i++) {
76 varlowerBytesSum;
77
78 lowerBytesSum = (result & 0xffff) + (arguments[i] & 0xffff);
79 result = (((result >> 16) + (arguments[i] >> 16) + (lowerBytesSum >> 16)) << 16) | (lowerBytesSum & 0xffff);
80 }
81
82//Clipperz.Profile.stop("Clipperz.Crypto.SHA.safeAdd");
83 return result;
84 },
85
86 //-----------------------------------------------------------------------------
87
88 'sha256_array': function(aValue) {
89//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha256_array");
90 varresult;
91 varmessage;
92 var h0, h1, h2, h3, h4, h5, h6, h7;
93 vark;
94 varmessageLength;
95 varmessageLengthInBits;
96 var_i, _c;
97 var charBits;
98 var rotateRight;
99 var shiftRight;
100 var safeAdd;
101 varbytesPerBlock;
102 var currentMessageIndex;
103
104 bytesPerBlock = 512/8;
105 rotateRight = Clipperz.Crypto.SHA.rotateRight;
106 shiftRight = Clipperz.Crypto.SHA.shiftRight;
107 safeAdd = Clipperz.Crypto.SHA.safeAdd;
108
109 charBits = 8;
110
111 h0 = 0x6a09e667;
112 h1 = 0xbb67ae85;
113 h2 = 0x3c6ef372;
114 h3 = 0xa54ff53a;
115 h4 = 0x510e527f;
116 h5 = 0x9b05688c;
117 h6 = 0x1f83d9ab;
118 h7 = 0x5be0cd19;
119
120 k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
121 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
122 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
123 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
124 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
125 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
126 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
127 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
128
129 message = aValue;
130 messageLength = message.length;
131
132 //Pre-processing:
133 message.push(0x80); //append a single "1" bit to message
134
135 _c = (512 - (((messageLength + 1) * charBits) % 512) - 64) / charBits;
136 if (_c < 0) {
137 _c = _c + (512 / charBits);
138 }
139
140 for (_i=0; _i<_c; _i++) {
141 message.push(0x00); //append "0" bits until message length ≡ 448 ≡ -64 (mod 512)
142 }
143
144 messageLengthInBits = messageLength * charBits;
145 message.push(0x00); //the 4 most high byte are alway 0 as message length is represented with a 32bit value;
146 message.push(0x00);
147 message.push(0x00);
148 message.push(0x00);
149 message.push((messageLengthInBits >> 24)& 0xff);
150 message.push((messageLengthInBits >> 16)& 0xff);
151 message.push((messageLengthInBits >> 8) & 0xff);
152 message.push( messageLengthInBits & 0xff);
153
154 currentMessageIndex = 0;
155 while(currentMessageIndex < message.length) {
156 varw;
157 vara, b, c, d, e, f, g, h;
158
159 w = Array(64);
160
161 _c = 16;
162 for (_i=0; _i<_c; _i++) {
163 var _j;
164
165 _j = currentMessageIndex + _i*4;
166 w[_i] = (message[_j] << 24) | (message[_j + 1] << 16) | (message[_j + 2] << 8) | (message[_j + 3] << 0);
167 }
168
169 _c = 64;
170 for (_i=16; _i<_c; _i++) {
171 vars0, s1;
172
173 s0 = (rotateRight(w[_i-15], 7)) ^ (rotateRight(w[_i-15], 18)) ^ (shiftRight(w[_i-15], 3));
174 s1 = (rotateRight(w[_i-2], 17)) ^ (rotateRight(w[_i-2], 19)) ^ (shiftRight(w[_i-2], 10));
175 w[_i] = safeAdd(w[_i-16], s0, w[_i-7], s1);
176 }
177
178 a=h0; b=h1; c=h2; d=h3; e=h4; f=h5; g=h6; h=h7;
179
180 _c = 64;
181 for (_i=0; _i<_c; _i++) {
182 var s0, s1, ch, maj, t1, t2;
183
184 s0 = (rotateRight(a, 2)) ^ (rotateRight(a, 13)) ^ (rotateRight(a, 22));
185 maj = (a & b) ^ (a & c) ^ (b & c);
186 t2 = safeAdd(s0, maj);
187 s1 = (rotateRight(e, 6)) ^ (rotateRight(e, 11)) ^ (rotateRight(e, 25));
188 ch = (e & f) ^ ((~e) & g);
189 t1 = safeAdd(h, s1, ch, k[_i], w[_i]);
190
191 h = g;
192 g = f;
193 f = e;
194 e = safeAdd(d, t1);
195 d = c;
196 c = b;
197 b = a;
198 a = safeAdd(t1, t2);
199 }
200
201 h0 = safeAdd(h0, a);
202 h1 = safeAdd(h1, b);
203 h2 = safeAdd(h2, c);
204 h3 = safeAdd(h3, d);
205 h4 = safeAdd(h4, e);
206 h5 = safeAdd(h5, f);
207 h6 = safeAdd(h6, g);
208 h7 = safeAdd(h7, h);
209
210 currentMessageIndex += bytesPerBlock;
211 }
212
213 result = new Array(256/8);
214 result[0] = (h0 >> 24)& 0xff;
215 result[1] = (h0 >> 16)& 0xff;
216 result[2] = (h0 >> 8)& 0xff;
217 result[3] = h0 & 0xff;
218
219 result[4] = (h1 >> 24)& 0xff;
220 result[5] = (h1 >> 16)& 0xff;
221 result[6] = (h1 >> 8)& 0xff;
222 result[7] = h1 & 0xff;
223
224 result[8] = (h2 >> 24)& 0xff;
225 result[9] = (h2 >> 16)& 0xff;
226 result[10] = (h2 >> 8)& 0xff;
227 result[11] = h2 & 0xff;
228
229 result[12] = (h3 >> 24)& 0xff;
230 result[13] = (h3 >> 16)& 0xff;
231 result[14] = (h3 >> 8)& 0xff;
232 result[15] = h3 & 0xff;
233
234 result[16] = (h4 >> 24)& 0xff;
235 result[17] = (h4 >> 16)& 0xff;
236 result[18] = (h4 >> 8)& 0xff;
237 result[19] = h4 & 0xff;
238
239 result[20] = (h5 >> 24)& 0xff;
240 result[21] = (h5 >> 16)& 0xff;
241 result[22] = (h5 >> 8)& 0xff;
242 result[23] = h5 & 0xff;
243
244 result[24] = (h6 >> 24)& 0xff;
245 result[25] = (h6 >> 16)& 0xff;
246 result[26] = (h6 >> 8)& 0xff;
247 result[27] = h6 & 0xff;
248
249 result[28] = (h7 >> 24)& 0xff;
250 result[29] = (h7 >> 16)& 0xff;
251 result[30] = (h7 >> 8)& 0xff;
252 result[31] = h7 & 0xff;
253
254//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256_array");
255 return result;
256 },
257
258 //-----------------------------------------------------------------------------
259
260 'sha256': function(aValue) {
261//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha256");
262 var result;
263 var resultArray;
264 varvalueArray;
265
266 valueArray = aValue.arrayValues();
267 resultArray = Clipperz.Crypto.SHA.sha256_array(valueArray);
268
269 result = new Clipperz.ByteArray(resultArray);
270
271//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256");
272 return result;
273 },
274
275 //-----------------------------------------------------------------------------
276
277 'sha_d256': function(aValue) {
278//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha_d256");
279 var result;
280 var resultArray;
281 varvalueArray;
282
283 valueArray = aValue.arrayValues();
284 resultArray = Clipperz.Crypto.SHA.sha256_array(valueArray);
285 resultArray = Clipperz.Crypto.SHA.sha256_array(resultArray);
286
287 result = new Clipperz.ByteArray(resultArray);
288
289//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256");
290 return result;
291 },
292
293 //-----------------------------------------------------------------------------
294 __syntaxFix__: "syntax fix"
295
296});
diff --git a/frontend/delta/js/Clipperz/Crypto/SRP.js b/frontend/delta/js/Clipperz/Crypto/SRP.js
new file mode 100644
index 0000000..597e72d
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/SRP.js
@@ -0,0 +1,316 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
26}
27
28try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) {
29 throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.BigInt!";
30}
31
32try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
33 throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.PRNG!";
34}
35
36if (typeof(Clipperz.Crypto.SRP) == 'undefined') { Clipperz.Crypto.SRP = {}; }
37
38Clipperz.Crypto.SRP.VERSION = "0.1";
39Clipperz.Crypto.SRP.NAME = "Clipperz.Crypto.SRP";
40
41//#############################################################################
42
43MochiKit.Base.update(Clipperz.Crypto.SRP, {
44
45 '_n': null,
46 '_g': null,
47 //-------------------------------------------------------------------------
48
49 'n': function() {
50 if (Clipperz.Crypto.SRP._n == null) {
51 Clipperz.Crypto.SRP._n = new Clipperz.Crypto.BigInt("115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16);
52 }
53
54 return Clipperz.Crypto.SRP._n;
55 },
56
57 //-------------------------------------------------------------------------
58
59 'g': function() {
60 if (Clipperz.Crypto.SRP._g == null) {
61 Clipperz.Crypto.SRP._g = new Clipperz.Crypto.BigInt(2); //eventually 5 (as suggested on the Diffi-Helmann documentation)
62 }
63
64 return Clipperz.Crypto.SRP._g;
65 },
66
67 //-----------------------------------------------------------------------------
68
69 'exception': {
70 'InvalidValue': new MochiKit.Base.NamedError("Clipperz.Crypto.SRP.exception.InvalidValue")
71 },
72
73 //-------------------------------------------------------------------------
74 __syntaxFix__: "syntax fix"
75
76});
77
78//#############################################################################
79//
80 // S R P C o n n e c t i o n version 1.0
81//
82//=============================================================================
83Clipperz.Crypto.SRP.Connection = function (args) {
84 args = args || {};
85
86 this._C = args.C;
87 this._P = args.P;
88 this.hash = args.hash;
89
90 this._a = null;
91 this._A = null;
92
93 this._s = null;
94 this._B = null;
95
96 this._x = null;
97
98 this._u = null;
99 this._K = null;
100 this._M1 = null;
101 this._M2 = null;
102
103 this._sessionKey = null;
104
105 return this;
106}
107
108Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
109
110 'toString': function () {
111 return "Clipperz.Crypto.SRP.Connection (username: " + this.username() + "). Status: " + this.statusDescription();
112 },
113
114 //-------------------------------------------------------------------------
115
116 'C': function () {
117 return this._C;
118 },
119
120 //-------------------------------------------------------------------------
121
122 'P': function () {
123 return this._P;
124 },
125
126 //-------------------------------------------------------------------------
127
128 'a': function () {
129 if (this._a == null) {
130 this._a = new Clipperz.Crypto.BigInt(Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2), 16);
131 // this._a = new Clipperz.Crypto.BigInt("37532428169486597638072888476611365392249575518156687476805936694442691012367", 10);
132 }
133
134 return this._a;
135 },
136
137 //-------------------------------------------------------------------------
138
139 'A': function () {
140 if (this._A == null) {
141 //Warning: this value should be strictly greater than zero: how should we perform this check?
142 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n());
143
144 if (this._A.equals(0)) {
145 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
146 throw Clipperz.Crypto.SRP.exception.InvalidValue;
147 }
148 }
149
150 return this._A;
151 },
152
153 //-------------------------------------------------------------------------
154
155 's': function () {
156 return this._s;
157 },
158
159 'set_s': function(aValue) {
160 this._s = aValue;
161 },
162
163 //-------------------------------------------------------------------------
164
165 'B': function () {
166 return this._B;
167 },
168
169 'set_B': function(aValue) {
170 //Warning: this value should be strictly greater than zero: how should we perform this check?
171 if (! aValue.equals(0)) {
172 this._B = aValue;
173 } else {
174 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
175 throw Clipperz.Crypto.SRP.exception.InvalidValue;
176 }
177 },
178
179 //-------------------------------------------------------------------------
180
181 'x': function () {
182 if (this._x == null) {
183 this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16);
184 }
185
186 return this._x;
187 },
188
189 //-------------------------------------------------------------------------
190
191 'u': function () {
192 if (this._u == null) {
193 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16);
194 }
195
196 return this._u;
197 },
198
199 //-------------------------------------------------------------------------
200
201 'S': function () {
202 if (this._S == null) {
203 var bigint;
204 varsrp;
205
206 bigint = Clipperz.Crypto.BigInt;
207 srp = Clipperz.Crypto.SRP;
208
209 this._S =bigint.powerModule(
210 bigint.subtract(this.B(), bigint.powerModule(srp.g(), this.x(), srp.n())),
211 bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
212 srp.n()
213 )
214 }
215
216 return this._S;
217 },
218
219 //-------------------------------------------------------------------------
220
221 'K': function () {
222 if (this._K == null) {
223 this._K = this.stringHash(this.S().asString());
224 }
225
226 return this._K;
227 },
228
229 //-------------------------------------------------------------------------
230
231 'M1': function () {
232 if (this._M1 == null) {
233 this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
234 }
235
236 return this._M1;
237 },
238
239 //-------------------------------------------------------------------------
240
241 'M2': function () {
242 if (this._M2 == null) {
243 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
244 }
245
246 return this._M2;
247 },
248
249 //=========================================================================
250
251 'serverSideCredentialsWithSalt': function(aSalt) {
252 var result;
253 var s, x, v;
254
255 s = aSalt;
256 x = this.stringHash(s + this.P());
257 v = Clipperz.Crypto.SRP.g().powerModule(new Clipperz.Crypto.BigInt(x, 16), Clipperz.Crypto.SRP.n());
258
259 result = {};
260 result['C'] = this.C();
261 result['s'] = s;
262 result['v'] = v.asString(16);
263
264 return result;
265 },
266
267 'serverSideCredentials': function() {
268 var result;
269 var s;
270
271 s = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
272
273 result = this.serverSideCredentialsWithSalt(s);
274
275 return result;
276 },
277
278 //=========================================================================
279/*
280 'computeServerSide_S': function(b) {
281 var result;
282 var v;
283 var bigint;
284 varsrp;
285
286 bigint = Clipperz.Crypto.BigInt;
287 srp = Clipperz.Crypto.SRP;
288
289 v = new Clipperz.Crypto.BigInt(srpConnection.serverSideCredentialsWithSalt(this.s().asString(16, 64)).v, 16);
290 // _S = (this.A().multiply(this.v().modPow(this.u(), this.n()))).modPow(this.b(), this.n());
291 result = bigint.powerModule(
292 bigint.multiply(
293 this.A(),
294 bigint.powerModule(v, this.u(), srp.n())
295 ), new Clipperz.Crypto.BigInt(b, 10), srp.n()
296 );
297
298 return result;
299 },
300*/
301 //=========================================================================
302
303 'stringHash': function(aValue) {
304 varresult;
305
306 result = this.hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
307
308 return result;
309 },
310
311 //=========================================================================
312 __syntaxFix__: "syntax fix"
313
314});
315
316//#############################################################################
diff --git a/frontend/delta/js/Clipperz/DOM.js b/frontend/delta/js/Clipperz/DOM.js
new file mode 100644
index 0000000..1d52a4b
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/DOM.js
@@ -0,0 +1,134 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.DOM) == 'undefined') { Clipperz.DOM = {}; }
26
27Clipperz.DOM.VERSION = "0.1";
28Clipperz.DOM.NAME = "Clipperz.DOM";
29
30MochiKit.Base.update(Clipperz.DOM, {
31
32 //-------------------------------------------------------------------------
33
34 '__repr__': function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36 },
37
38 //-------------------------------------------------------------------------
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-------------------------------------------------------------------------
45
46 'selectOptionMatchingValue': function (aSelectElement, aValue, shouldUseCaseInsensitiveTest) {
47 var selectedOptionIndex;
48 var i, c;
49
50 selectedOptionIndex = -1;
51
52 c = aSelectElement.options.length;
53 for (i=0; (i<c) && (selectedOptionIndex == -1); i++) {
54 if (shouldUseCaseInsensitiveTest == true) {
55 if (aSelectElement.options[i].value.toLowerCase() == aValue.toLowerCase()) {
56 selectedOptionIndex = i;
57 }
58 } else {
59 if (aSelectElement.options[i].value == aValue) {
60 selectedOptionIndex = i;
61 }
62 }
63 }
64
65 if (selectedOptionIndex != -1) {
66 aSelectElement.selectedIndex = selectedOptionIndex;
67 }
68 },
69
70 //-------------------------------------------------------------------------
71
72 'setFormContents': function(aNode, someValues) {
73 var node;
74 var values;
75 var i, c;
76
77 values = {};
78 c = someValues[0].length;
79 for (i=0; i<c; i++) {
80 values[someValues[0][i]] = someValues[1][i];
81 }
82
83 // var m = MochiKit.Base;
84 // var self = MochiKit.DOM;
85 if (typeof(aNode) == "undefined" || aNode === null) {
86 node = MochiKit.DOM._document.body;
87 } else {
88 node = MochiKit.DOM.getElement(aNode);
89 }
90
91 MochiKit.Base.nodeWalk(node, function(aNode) {
92 var result;
93 var name;
94
95 result = null;
96 name = aNode.name;
97 if (MochiKit.Base.isNotEmpty(name) && (typeof(values[name]) != 'undefined')) {
98 var tagName;
99
100 tagName = aNode.tagName.toUpperCase();
101 if (tagName === "INPUT" && (aNode.type == "radio" || aNode.type == "checkbox")) {
102 aNode.checked = values[name];
103 } else if (tagName === "SELECT") {
104 if (aNode.type == "select-one") {
105 Clipperz.DOM.selectOptionMatchingValue(aNode, values[name]);
106 } else { //aNode.type == "select-multiple"
107 Clipperz.logWarning("### unhandled Select.type = 'select-multiple' condition");
108 }
109 } else if (tagName === "FORM" || tagName === "P" || tagName === "SPAN" || tagName === "DIV") {
110 result = aNode.childNodes;
111 } else {
112 aNode.value = values[name]
113 }
114 } else {
115 result = aNode.childNodes;
116 }
117
118 return result;
119 });
120 },
121
122 //-------------------------------------------------------------------------
123
124 'get': MochiKit.DOM.getElement,
125
126 //-------------------------------------------------------------------------
127
128 'Helper': Clipperz.YUI.DomHelper,
129
130 //-------------------------------------------------------------------------
131 __syntaxFix__: "syntax fix"
132
133});
134
diff --git a/frontend/delta/js/Clipperz/Date.js b/frontend/delta/js/Clipperz/Date.js
new file mode 100644
index 0000000..163790e
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Date.js
@@ -0,0 +1,297 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Date) == 'undefined') { Clipperz.Date = {}; }
26
27Clipperz.Date.VERSION = "0.1";
28Clipperz.Date.NAME = "Clipperz.Date";
29
30MochiKit.Base.update(Clipperz.Date, {
31
32 //-------------------------------------------------------------------------
33
34 '__repr__': function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36 },
37
38 //-------------------------------------------------------------------------
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-------------------------------------------------------------------------
45
46 'daysInMonth': [31,28,31,30,31,30,31,31,30,31,30,31],
47
48 //-------------------------------------------------------------------------
49
50 'englishOrdinalDaySuffixForDate': function(aDate) {
51 var result;
52
53 switch (aDate.getDate()) {
54 case 1:
55 case 21:
56 case 31:
57 result = "st";
58 break;
59 case 2:
60 case 22:
61 result = "nd";
62 break;
63 case 3:
64 case 23:
65 result = "rd";
66 break;
67 default:
68 result = "th";
69 break;
70 }
71
72 return result;
73 },
74
75 //-------------------------------------------------------------------------
76
77 'isLeapYear': function(aDate) {
78 var year;
79 var result;
80
81 year = aDate.getFullYear();
82 result = ((year & 0x03) == 0 && (year % 100 || (year % 400 == 0 && year)));
83
84 return result;
85 },
86
87 //-------------------------------------------------------------------------
88
89 'getDaysInMonth': function(aDate) {
90 var result;
91
92 if (aDate.getMonth() == 1) {
93 Clipperz.Date.isLeapYear(aDate)
94 result += Clipperz.Date.isLeapYear(aDate) ? 29 : 28;
95 } else {
96 result = Clipperz.Date.daysInMonth[aDate.getMonth()];
97 }
98
99 return result;
100 },
101
102 //-------------------------------------------------------------------------
103
104 'getTimezone': function(aDate) {
105 var result;
106
107 result = aDate.toString();
108 result = result.replace(/([A-Z]{3}) [0-9]{4}/, '$1');
109 result = result.replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
110
111 return result;
112 },
113
114 'getGMTOffset': function(aDate) {
115 return (aDate.getTimezoneOffset() > 0 ? "-" : "+")+ MochiKit.Format.numberFormatter('00')(Math.floor(this.getTimezoneOffset() / 60))
116 + MochiKit.Format.numberFormatter('00')(this.getTimezoneOffset() % 60);
117 },
118
119 //-------------------------------------------------------------------------
120
121 'dayOfYear': function(aDate) {
122 var result;
123 var i,c;
124
125 result = 0;
126 c = aDate.getMonth();
127 for (i=0; i<c; i++) {
128 if (i == 1) {
129 result += Clipperz.Date.isLeapYear(aDate) ? 29 : 28;
130 } else {
131 result += Clipperz.Date.daysInMonth[i];
132 }
133 }
134 return num + this.getDate() - 1;
135 },
136
137 //-------------------------------------------------------------------------
138
139 'getPHPLikeFormatCode': function(aCharacter) {
140 var result;
141
142 switch (aCharacter) {
143 case "d":
144 result = " + MochiKit.Format.numberFormatter('00')(aDate.getDate())";
145 break;
146 case "D":
147 result = " + aLocale['shortDays'][aDate.getDay()]";
148 break;
149 case "j":
150 result = " + aDate.getDate()";
151 break;
152 case "l":
153 result = " + aLocale['days'][aDate.getDay()]";
154 break;
155 case "S":
156 result = " + Clipperz.Date.englishOrdinalDaySuffixForDate(aDate)";
157 break;
158 case "w":
159 result = " + aDate.getDay()";
160 break;
161 case "z":
162 result = " + aDate.getDayOfYear()";
163 break;
164 case "W":
165 result = " + aDate.getWeekOfYear()";
166 break;
167 case "F":
168 result = " + aLocale['months'][aDate.getMonth()]";
169 break;
170 case "m":
171 result = " + MochiKit.Format.numberFormatter('00')(aDate.getMonth() + 1)";
172 break;
173 case "M":
174 result = " + aLocale['shortMonths'][aDate.getMonth()]";
175 break;
176 case "n":
177 result = " + (aDate.getMonth() + 1)";
178 break;
179 case "t":
180 result = " + Clipperz.Date.getDaysInMonth(aDate)";
181 break;
182 case "L":
183 result = " + (Clipperz.Date.isLeapYear(aDate) ? 1 : 0)";
184 break;
185 case "Y":
186 result = " + aDate.getFullYear()";
187 break;
188 case "y":
189 result = " + ('' + aDate.getFullYear()).substring(2, 4)";
190 break;
191 case "a":
192 result = " + (aDate.getHours() < 12 ? aLocale['amDesignation'] : aLocale['pmDesignation'])";
193 break;
194 case "A":
195 result = " + (aDate.getHours() < 12 ? aLocale['amDesignation'].toUpperCase() : aLocale['pmDesignation'].toUpperCase())";
196 break;
197 case "g":
198 result = " + ((aDate.getHours() %12) ? aDate.getHours() % 12 : 12)";
199 break;
200 case "G":
201 result = " + aDate.getHours()";
202 break;
203 case "h":
204 result = " + MochiKit.Format.numberFormatter('00')((aDate.getHours() %12) ? aDate.getHours() % 12 : 12)";
205 break;
206 case "H":
207 result = " + MochiKit.Format.numberFormatter('00')(aDate.getHours())";
208 break;
209 case "i":
210 result = " + MochiKit.Format.numberFormatter('00')(aDate.getMinutes())";
211 break;
212 case "s":
213 result = " + MochiKit.Format.numberFormatter('00')(aDate.getSeconds())";
214 break;
215 case "O":
216 result = " + aDate.getGMTOffset()";
217 break;
218 case "T":
219 result = " + Clipperz.Date.getTimezone(aDate)";
220 break;
221 case "Z":
222 result = " + ( + aDate.getTimezoneOffset() * -60)";
223 break;
224 default:
225 result = " + '" + aCharacter + "'";
226 break;
227 };
228
229 return result;
230 },
231
232 //=========================================================================
233
234 'formatDateWithPHPLikeTemplateAndLocale': function(aDate, aFormat, aLocale) {
235 var result;
236 var formatterCode;
237 var formatter;
238 var i,c;
239
240 formatterCode = "Clipperz.Date.__scratchFormatter = function(aDate, aLocale){return ''";
241
242 c = aFormat.length;
243 i = 0;
244
245 while (i<c) {
246 var character;
247
248 character = aFormat.charAt(i);
249 if (character == "\\") {
250 i++;
251 character = aFormat.charAt(i);
252 formatterCode += " + '" + character + "'"
253 } else {
254 formatterCode += Clipperz.Date.getPHPLikeFormatCode(character);
255 }
256
257 i++;
258 }
259
260 formatterCode += ";}";
261 eval(formatterCode);
262
263 result = Clipperz.Date.__scratchFormatter.call(this, aDate, aLocale);
264 delete Clipperz.Date.__scratchFormatter;
265
266 return result;
267 },
268
269 //-------------------------------------------------------------------------
270
271 'parseDateWithPHPLikeTemplateAndLocale': function(aString, aFormat, aLocale) {
272 return new Date();
273 },
274
275 //=========================================================================
276
277 'formatDateWithUTCFormatAndLocale': function(aDate, aLocale) {
278 // return Clipperz.Date.formatWithJavaLikeTemplateAndLocale(aDate, "EEE, dd MMMM yyyy HH:mm:ss zzz", aLocale);
279 return aDate.toString();
280 },
281
282 'parseDateWithUTCFormatAndLocale': function(aValue, aLocale) {
283 return new Date(Date.parse(aValue));
284 },
285
286 //=========================================================================
287
288 'exception': {
289 // 'AbstractMethod': new MochiKit.Base.NamedError("Clipperz.Base.exception.AbstractMethod"),
290 // 'UnknownType': new MochiKit.Base.NamedError("Clipperz.Base.exception.UnknownType")
291 },
292
293 //-------------------------------------------------------------------------
294 __syntaxFix__: "syntax fix"
295
296});
297
diff --git a/frontend/delta/js/Clipperz/KeePassExportProcessor.js b/frontend/delta/js/Clipperz/KeePassExportProcessor.js
new file mode 100644
index 0000000..e35d729
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/KeePassExportProcessor.js
@@ -0,0 +1,191 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25
26
27Clipperz.KeePassExportProcessor = function(args) {
28 args = args || {};
29
30 return this;
31}
32
33//=============================================================================
34
35Clipperz.KeePassExportProcessor.prototype = MochiKit.Base.update(null, {
36
37 //-------------------------------------------------------------------------
38
39 'deferredParse_core': function(aContext) {
40 var deferredResult;
41
42 if (aContext.line == "") {
43 deferredResult = MochiKit.Async.succeed(aContext.result);
44 } else {
45 var record;
46
47 record = this.parseRecord(aContext);
48 if (record != null) {
49 aContext.result.push(record);
50 }
51
52 aContext.line = aContext.line.replace(/^\n*/g, "").replace(/\n$/g, "");
53
54 deferredResult = new Clipperz.Async.Deferred("KeePassExportProcessor.deferredParse_core");
55 deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
56 deferredResult.addCallback(MochiKit.Async.wait, 0.2);
57 deferredResult.addMethod(this, 'deferredParse_core');
58 deferredResult.callback(aContext);
59 }
60
61 return deferredResult;
62 },
63
64 //.........................................................................
65
66 'deferredParse': function(aValue) {
67 var deferredResult;
68 var lines;
69 var context;
70
71 lines = aValue.replace(/\r?\n/g, "\n");
72 context = {
73 line: lines,
74 size: lines.length,
75 result: []
76 }
77
78 deferredResult = new Clipperz.Async.Deferred("KeePassExportProcessor.deferredResult");
79 deferredResult.addMethod(this, 'deferredParse_core');
80 deferredResult.callback(context);
81
82 return deferredResult;
83 },
84
85 //-------------------------------------------------------------------------
86
87 'parseRecord': function(aContext) {
88 var result;
89 var recordLabelRegexp;
90 varfieldLabelRegexp;
91 var fieldValueRegexp;
92 var fullLineRegexp;
93/*
94[Record name]
95Group Tree:
96UserName:
97URL:
98Password:
99Notes: test
100UUID: 525f62430079bae48b79ed2961924b05
101Icon: 0
102Creation Time: 2007-06-26 17:56:03
103Last Access: 2007-10-25 16:23:51
104Last Modification: 2007-10-25 16:23:51
105Expires: 2999-12-28 23:59:59
106
107 [Record name] ==> Title
108 Group: General ==> Group
109 Group Tree: ==> Group Tree
110 UserName: ==> UserName
111 URL: ==>URL
112 Password: ==>Password
113 Notes: test ==>Notes
114 UUID: 525f62430079bae48b79ed2961924b05 ==>UUID
115 Icon: 0 ==>Icon
116 Creation Time: 2007-06-26 17:56:03 ==>Creation Time
117 Last Access: 2007-10-25 16:23:51 ==>Last Access
118 Last Modification: 2007-10-25 16:23:51 ==>Last Modification
119 Expires: 2999-12-28 23:59:59 ==> Expires
120 Attachment Description: ==> Attachment Description
121 Attachment: ==> Attachment
122*/
123 // recordLabelRegexp = new RegExp("(^\\[(.*)\\]\\n|^Title:\s*(.*)\\n)");
124 recordLabelRegexp = new RegExp("^\\[(.*)\\]\\n|^Title:\s*(.*)\\n");
125 fieldLabelRegexp = new RegExp("^\s?(Group|Group Tree|Username|UserName|User Name|Url|URL|Password|Notes|Comment|UUID|Icon|Creation Time|Last Access|Last Modification|Expires|Attachment Description|Attachment|Valid until): ");
126 fieldValueRegexp = new RegExp("(.*)(\\n|$)");
127 fullLineRegexp = new RegExp("^(.*\\n)");
128
129 if (recordLabelRegexp.test(aContext.line) == true) {
130 var line;
131
132 line = aContext.line;
133
134 result = {};
135 result['Title'] = line.match(recordLabelRegexp)[1];
136 line = line.replace(/^.*\n/, "");
137 while (fieldLabelRegexp.test(line) == true) {
138 var fieldName;
139 var fieldValue;
140
141 fieldName = RegExp.$1;
142 line = RegExp.rightContext;
143
144 fieldValue = line.match(fieldValueRegexp)[1];
145 line = RegExp.rightContext;
146
147 if (fieldName == 'Notes') {
148 var isMultiline;
149
150 isMultiline = false;
151
152 if ((line != "") && (fieldLabelRegexp.test(line) == false) && (recordLabelRegexp.test(line) == false)) {
153 fieldValue += '\n';
154 }
155
156 while ((line != "") && (fieldLabelRegexp.test(line) == false) && (recordLabelRegexp.test(line) == false)) {
157 var newLineValue;
158
159 newLineValue = line.match(fullLineRegexp)[1];
160 if (newLineValue != "\n") {
161 isMultiline = true;
162 }
163 fieldValue += newLineValue;
164 line = RegExp.rightContext;
165 }
166
167 if (isMultiline) {
168 fieldValue = fieldValue.replace(/\n$/g, "");
169 } else {
170 fieldValue = fieldValue.replace(/\n\n$/g, "");
171 }
172
173 line = line.replace(/^\n/, '');
174 }
175
176 result[fieldName] = fieldValue;
177 }
178 } else {
179 result = null;
180 }
181
182 aContext.line = line;
183
184 return result;
185 },
186
187 //-------------------------------------------------------------------------
188 __syntaxFix__: "syntax fix"
189});
190
191
diff --git a/frontend/delta/js/Clipperz/KeyValueObjectStore.js b/frontend/delta/js/Clipperz/KeyValueObjectStore.js
new file mode 100644
index 0000000..8bc125b
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/KeyValueObjectStore.js
@@ -0,0 +1,166 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25
26//#############################################################################
27
28Clipperz.KeyValueObjectStore = function(args) {
29 args = args || {};
30
31 //this._name = args['name'] || "unnamed KeyValueObjectStore";
32 this._values = args['values'] || {};
33 //this._referenceObjectStore = null;
34
35 return this;
36}
37
38Clipperz.KeyValueObjectStore.prototype = MochiKit.Base.update(null, {
39
40 'values': function() {
41 return this._values;
42 },
43
44 'initWithValues': function (someValues) {
45 this._values = Clipperz.Base.deepClone(someValues) || {};
46 return this;
47 },
48
49 'setValues': function (someValues) {
50 this._values = someValues;
51 return this;
52 },
53
54 //'initWithObjectStore': function (anObjectStore) {
55 // this._referenceObjectStore = anObjectStore;
56 //},
57
58 'removeAllData': function () {
59 this._values = {};
60 },
61
62 //-------------------------------------------------------------------------
63
64 'getValue': function(aKeyPath) {
65 var result;
66 var keys;
67 var i,c;
68
69 result = this.values();
70
71 keys = (aKeyPath + '').split('.');
72 c = keys.length;
73 i = 0;
74
75 while ((i<c) && (result != null)) {
76 if (typeof result[keys[i]] != 'undefined') {
77 result = result[keys[i]];
78 } else {
79 result = null;
80 }
81
82 i++;
83 }
84
85 return result;
86 },
87
88 //-------------------------------------------------------------------------
89
90 'setValue': function(aKeyPath, aValue) {
91 var targetObject;
92 var keys;
93 var i,c;
94
95 targetObject = this.values();
96 keys = (aKeyPath + '').split('.');
97 c = keys.length - 1;
98 for (i=0; i<c; i++) {
99 if (typeof targetObject[keys[i]] == 'undefined') {
100 targetObject[keys[i]] = {}
101 }
102
103 targetObject = targetObject[keys[i]];
104 }
105
106 targetObject[keys[c]] = aValue;
107
108 return aValue;
109 },
110
111 //-------------------------------------------------------------------------
112
113 'removeValue': function (aKeyPath) {
114 // this.setValue(aKeyPath, null);
115
116 var targetObject;
117 var keys;
118 var i,c;
119
120 targetObject = this.values();
121 keys = ('' + aKeyPath).split('.');
122 c = keys.length - 1;
123 for (i=0; i<c; i++) {
124 if (typeof targetObject[keys[i]] == 'undefined') {
125 targetObject[keys[i]] = {}
126 }
127
128 targetObject = targetObject[keys[i]];
129 }
130
131 delete targetObject[keys[c]];
132 },
133
134 //-------------------------------------------------------------------------
135
136 'deferredGetOrSet': function(aKeyPath, aGetterFunction) {
137 var deferredResult;
138
139 if (this.getValue(aKeyPath) != null) {
140 deferredResult = MochiKit.Async.succeed(this.getValue(aKeyPath));
141 } else {
142 deferredResult = new Clipperz.Async.Deferred("KeyValueObjectStore.deferredGetOrSet [" + aKeyPath + "]", {trace:false});
143
144 deferredResult.addCallback(aGetterFunction);
145 deferredResult.addMethod(this, 'setValue', aKeyPath);
146 deferredResult.callback();
147 }
148
149 return deferredResult;
150 },
151
152 //-------------------------------------------------------------------------
153
154 'isEmpty': function () {
155 return (MochiKit.Base.keys(this.values()).length == 0)
156 },
157
158 //-------------------------------------------------------------------------
159/*
160 'dumpData': function () {
161 return Clipperz.Base.serializeJSON(this.values());
162 },
163*/
164 //-------------------------------------------------------------------------
165 __syntaxFix__: "syntax fix"
166});
diff --git a/frontend/delta/js/Clipperz/Logging.js b/frontend/delta/js/Clipperz/Logging.js
new file mode 100644
index 0000000..b6b806a
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Logging.js
@@ -0,0 +1,32 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz');
25
26Clipperz.log = function () {
27 console.log.apply(console, arguments);
28}
29
30 Clipperz.logError= Clipperz.log;
31 Clipperz.logWarning= Clipperz.log;
32 Clipperz.logDebug= Clipperz.log; \ No newline at end of file
diff --git a/frontend/delta/js/Clipperz/PM/BookmarkletProcessor.js b/frontend/delta/js/Clipperz/PM/BookmarkletProcessor.js
new file mode 100644
index 0000000..4818b76
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/BookmarkletProcessor.js
@@ -0,0 +1,191 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/*
25if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
26if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
27
28Clipperz.PM.BookmarkletProcessor = function(aConfiguration) {
29 this._configuration = aConfiguration;
30
31 this._editableFields = null;
32 this._favicon = null;
33
34 return this;
35}
36
37Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, {
38
39 'toString': function() {
40 return "Clipperz.PM.BookmarkletProcessor";
41 },
42
43 //-------------------------------------------------------------------------
44
45 'configuration': function() {
46 return this._configuration;
47 },
48
49 //-------------------------------------------------------------------------
50
51 'pageTitle': function() {
52 return this.configuration().page.title;
53 },
54
55 //-------------------------------------------------------------------------
56
57 'fields': function() {
58 return this.configuration().form.inputs;
59 },
60
61 //-------------------------------------------------------------------------
62
63 'editableFields': function() {
64 if (this._editableFields == null) {
65 this._editableFields = MochiKit.Base.filter(function(aField) {
66 var result;
67 var type;
68
69 type = aField['type'].toLowerCase();
70 result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select'));
71
72 return result;
73 }, this.fields())
74 }
75
76 return this._editableFields;
77 },
78
79 //-------------------------------------------------------------------------
80
81 'hostname': function() {
82 if (this._hostname == null) {
83 var actionUrl;
84
85 actionUrl = this.configuration()['form']['attributes']['action'];
86 this._hostname = actionUrl.replace(/ ^ h t t p s ? : \ / \ / ( [ ^ \ / ] * ) \ / . * /, '$1');
87 }
88
89 return this._hostname;
90 },
91
92 'favicon': function() {
93 if (this._favicon == null) {
94 this._favicon = "http://" + this.hostname() + "/favicon.ico";
95 }
96
97 return this._favicon;
98 },
99
100 //-------------------------------------------------------------------------
101 __syntaxFix__: "syntax fix"
102});
103
104//#############################################################################
105/ *
106Clipperz.PM.BookmarkletProcessor.createRecordFromBookmarkletConfiguration = function(anUser, aConfiguration) {
107 var processor;
108 var record;
109 var recordVersion;
110 var directLogin;
111 var bindings;
112 var i,c;
113
114 processor = new Clipperz.PM.BookmarkletProcessor(aConfiguration);
115
116 record = new Clipperz.PM.DataModel.Record({
117 'label':processor.pageTitle(),
118 'notes':"",
119 'user': anUser
120 });
121 recordVersion = new Clipperz.PM.DataModel.Record.Version(record, {})
122 record.setCurrentVersion(recordVersion);
123
124 bindings = {};
125
126 c = processor.editableFields().length;
127 for (i=0; i<c; i++) {
128 var formField;
129 var recordField;
130
131 formField = processor.editableFields()[i];
132 recordField = new Clipperz.PM.DataModel.RecordField({
133 'label':formField['name'],
134 'value':formField['value'],
135 'type': Clipperz.PM.Strings.inputTypeToRecordFieldType[formField['type']],
136 'hidden': false,
137 'recordVersion':recordVersion
138 });
139 recordVersion.addField(recordField);
140
141 bindings[formField['name']] = recordField.key();
142 }
143
144 directLogin = new Clipperz.PM.DataModel.DirectLogin({
145 'record': record,
146 'label': processor.pageTitle(),
147 'favicon': processor.favicon(),
148 'formData': processor.configuration()['form'],
149 'bindingData':bindings,
150 'bookmarkletVersion':'0.2'
151 });
152 record.addDirectLogin(directLogin);
153
154 anUser.addRecord(record);
155
156 return record;
157};
158* /
159//-----------------------------------------------------------------------------
160
161Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration = function(aConfiguration) {
162 var result;
163
164 //throw "XSS Bookmarklet attempt";
165
166 result = aConfiguration;
167
168 return result;
169};
170
171//-----------------------------------------------------------------------------
172
173Clipperz.PM.BookmarkletProcessor.checkBookmarkletConfiguration = function(aConfiguration) {
174 var result;
175
176 try {
177 result = Clipperz.Base.evalJSON(aConfiguration);
178 result = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(result);
179
180 if (result['version'] != '0.2.3') {
181 throw "WrongBookmarkletVersion";
182 }
183 } catch (exception) {
184 throw exception;
185 }
186
187 return result;
188};
189
190//-----------------------------------------------------------------------------
191*/ \ No newline at end of file
diff --git a/frontend/delta/js/Clipperz/PM/Connection.js b/frontend/delta/js/Clipperz/PM/Connection.js
new file mode 100644
index 0000000..c02125f
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Connection.js
@@ -0,0 +1,636 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26
27//-----------------------------------------------------------------------------
28//
29 // Abstract C O N N E C T I O N class
30//
31//-----------------------------------------------------------------------------
32
33Clipperz.PM.Connection = function (args) {
34 args = args || {};
35
36 this._proxy = args.proxy || Clipperz.PM.Proxy.defaultProxy;
37 this._getCredentialsFunction = args.getCredentialsFunction;
38
39 this._clipperz_pm_crypto_version = null;
40 this._connectionId = null;
41 this._sharedSecret = null;
42 this._serverLockValue = null;
43
44 return this;
45}
46
47Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, {
48
49 'toString': function() {
50 return "Connection [" + this.version() + "]";
51 },
52
53 //=========================================================================
54
55 'version': function() {
56 throw Clipperz.Base.exception.AbstractMethod;
57 },
58
59 'clipperz_pm_crypto_version': function() {
60 if (this._clipperz_pm_crypto_version == null) {
61 var connectionVersions;
62 varversions;
63 varversion;
64 var i, c;
65
66 version = null;
67 connectionVersions = Clipperz.PM.Connection.communicationProtocol.versions;
68 versions = MochiKit.Base.keys(connectionVersions);
69 c = versions.length;
70 for (i=0; i<c; i++) {
71 if (! (versions[i] == 'current')) {
72 if (this instanceof connectionVersions[versions[i]]) {
73 version = versions[i];
74 };
75 }
76 }
77
78 this._clipperz_pm_crypto_version = version;
79 }
80
81 return this._clipperz_pm_crypto_version;
82 },
83
84 //-------------------------------------------------------------------------
85
86 'defaultErrorHandler': function(anErrorString, anException) {
87 // Clipperz.logError("### Connection.defaultErrorHandler: " + anErrorString, anException);
88 Clipperz.logError("### Connection.defaultErrorHandler: " + anErrorString + " (" + anException + ")");
89 },
90
91 //-------------------------------------------------------------------------
92
93 'getCredentialsFunction': function () {
94 return this._getCredentialsFunction;
95 },
96
97 'normalizedCredentials': function(someValues) {
98 throw Clipperz.Base.exception.AbstractMethod;
99 },
100
101 //=========================================================================
102
103 'proxy': function () {
104 return this._proxy;
105 },
106
107 //=========================================================================
108
109 'register': function () {
110 throw Clipperz.Base.exception.AbstractMethod;
111 },
112
113 'login': function() {
114 throw Clipperz.Base.exception.AbstractMethod;
115 },
116
117 //-------------------------------------------------------------------------
118
119 'message': function(someArguments, aCallback) {
120 throw Clipperz.Base.exception.AbstractMethod;
121 },
122
123 //-------------------------------------------------------------------------
124
125 'serverSideUserCredentials': function() {
126 throw Clipperz.Base.exception.AbstractMethod;
127 },
128
129 //=========================================================================
130
131 'sharedSecret': function () {
132 return this._sharedSecret;
133 },
134
135 'setSharedSecret': function (aValue) {
136 this._sharedSecret = aValue;
137 },
138
139 //-------------------------------------------------------------------------
140
141 'connectionId': function() {
142 return this._connectionId;
143 },
144
145 'setConnectionId': function(aValue) {
146 this._connectionId = aValue;
147 },
148
149 //-------------------------------------------------------------------------
150
151 'serverLockValue': function () {
152 return this._serverLockValue;
153 },
154
155 'setServerLockValue': function (aValue) {
156 this._serverLockValue = aValue;
157 },
158
159 //=========================================================================
160/*
161 //TODO: ?????
162 'oneTimePassword': function() {
163 return this._oneTimePassword;
164 },
165
166 'setOneTimePassword': function(aValue) {
167 this._oneTimePassword = aValue;
168 },
169*/
170 //=========================================================================
171
172 'reset': function() {
173 this.setSharedSecret(null);
174 this.setConnectionId(null);
175 },
176
177 //=========================================================================
178 __syntaxFix__: "syntax fix"
179
180}
181);
182
183
184if (typeof(Clipperz.PM.Connection.SRP) == 'undefined') { Clipperz.PM.Connection.SRP = {}; }
185//-----------------------------------------------------------------------------
186//
187 // S R P [ 1 . 0 ] C O N N E C T I O N class
188//
189//-----------------------------------------------------------------------------
190
191Clipperz.PM.Connection.SRP['1.0'] = function (args) {
192 Clipperz.PM.Connection.call(this, args);
193
194 return this;
195}
196
197Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection(), {
198
199 'version': function() {
200 return '1.0';
201 },
202
203 //=========================================================================
204
205 'register': function (someUserData) {
206 vardeferredResult;
207 var cryptoVersion;
208 var srpConnection;
209
210 cryptoVersion = this.clipperz_pm_crypto_version();
211
212 deferredResult = new Clipperz.Async.Deferred("Connection.registerWithVersion", {trace:false});
213 deferredResult.collectResults({
214 'credentials': [
215 this.getCredentialsFunction(),
216 MochiKit.Base.method(this, 'normalizedCredentials'),
217 MochiKit.Base.bind(function(someCredentials) {
218 var srpConnection;
219 var result;
220
221 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
222 result = srpConnection.serverSideCredentials();
223 result['version'] = Clipperz.PM.Connection.communicationProtocol.currentVersion;
224
225 return result;
226 }, this)
227 ],
228 'user': MochiKit.Base.partial(MochiKit.Async.succeed, someUserData),
229 'version':MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Connection.communicationProtocol.currentVersion),
230 'message':MochiKit.Base.partial(MochiKit.Async.succeed, 'completeRegistration')
231 });
232 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
233 deferredResult.addMethod(this.proxy(), 'registration');
234 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
235
236 deferredResult.callback();
237
238 return deferredResult;
239 },
240
241 //-------------------------------------------------------------------------
242
243 'updateCredentials': function (aUsername, aPassphrase, someUserData) {
244 vardeferredResult;
245
246 deferredResult = new Clipperz.Async.Deferred("Connection.updateCredentials", {trace:false});
247 deferredResult.collectResults({
248 'credentials': [
249 MochiKit.Base.method(this, 'normalizedCredentials', {username:aUsername, password:aPassphrase}),
250 MochiKit.Base.bind(function(someCredentials) {
251 var srpConnection;
252 var result;
253
254 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
255 result = srpConnection.serverSideCredentials();
256 result['version'] = Clipperz.PM.Connection.communicationProtocol.currentVersion;
257
258 return result;
259 }, this)
260 ],
261 'user': MochiKit.Base.partial(MochiKit.Async.succeed, someUserData)
262 });
263 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
264 deferredResult.addMethod(this, 'message', 'upgradeUserCredentials');
265 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
266 deferredResult.callback();
267
268 return deferredResult;
269
270 },
271
272 //=========================================================================
273
274 'redeemOneTimePassword': function (someParameters) {
275/*
276 //=========================================================================
277 //LOGIN WITH PASSPHRASE, extracted from the TRUNK version (LoginPanel.js)
278 deferredResult.addCallback(function(anUsername, aOneTimePassword) {
279 var args;
280
281 args = {
282 'message': 'oneTimePassword',
283 'version': Clipperz.PM.Crypto.communicationProtocol.currentVersion,
284 'parameters': {
285 'oneTimePasswordKey': Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(anUsername, aOneTimePassword),
286 'oneTimePasswordKeyChecksum': Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(anUsername, aOneTimePassword)
287 }
288 }
289
290 return args;
291 }, anUsername, oneTimePassword);
292 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_loadingOTP');
293 deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'handshake'));
294 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_extractingPassphrase');
295 deferredResult.addCallback(function(aResult) {
296 return Clipperz.PM.Crypto.deferredDecrypt(oneTimePassword, aResult['data'], aResult['version']);
297 });
298 deferredResult.addCallback(function(aResult) {
299 return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
300 });
301 deferredResult.addMethod(this, 'doLoginWithUsernameAndPassphrase', anUsername),
302*/
303 var args;
304 var normalizedOTP;
305
306 normalizedOTP = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(someParameters['password']);
307
308 args = {
309 'message': 'oneTimePassword',
310 'version': Clipperz.PM.Connection.communicationProtocol.currentVersion,
311 'parameters': {
312 'oneTimePasswordKey': Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(someParameters['username'], normalizedOTP),
313 'oneTimePasswordKeyChecksum':Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(someParameters['username'], normalizedOTP)
314 }
315 }
316
317 return Clipperz.Async.callbacks("Connction.redeemOTP", [
318 MochiKit.Base.method(this.proxy(), 'handshake', args),
319 function(aResult) {
320 return Clipperz.PM.Crypto.deferredDecrypt({
321 value:aResult['data'],
322 key:normalizedOTP,
323 version:aResult['version']
324 });
325 },
326 function(aResult) {
327 return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
328 }
329 ], {trace:false})
330 },
331
332 'login': function(isReconnecting) {
333 vardeferredResult;
334 var cryptoVersion;
335 var srpConnection;
336
337 cryptoVersion = this.clipperz_pm_crypto_version();
338 deferredResult = new Clipperz.Async.Deferred("Connection.login", {trace:false});
339 deferredResult.addCallback(this.getCredentialsFunction());
340 deferredResult.addMethod(this, 'normalizedCredentials');
341 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_sendingCredentials');
342 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
343 deferredResult.addCallback(MochiKit.Base.bind(function(someCredentials) {
344 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
345 }, this));
346 deferredResult.addCallback(function() {
347 var result;
348
349 result = {
350 message: 'connect',
351 version: cryptoVersion,
352 parameters: {
353 C: srpConnection.C(),
354 A: srpConnection.A().asString(16)
355 // reconnecting: this.connectionId()
356 }
357 };
358
359 // TODO: ?????
360 // if (isReconnecting == true) {
361 // args.parameters['reconnecting'] = aConnection.connectionId();
362 // }
363
364 return result;
365 });
366 deferredResult.addMethod(this.proxy(), 'handshake');
367 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_credentialVerification');
368 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
369 deferredResult.addCallback(function(someParameters) {
370 var result;
371
372 srpConnection.set_s(new Clipperz.Crypto.BigInt(someParameters['s'], 16));
373 srpConnection.set_B(new Clipperz.Crypto.BigInt(someParameters['B'], 16));
374
375 //TODO: ?????
376 // if (typeof(someParameters['oneTimePassword']) != 'undefined') {
377 // this.setOneTimePassword(someParameters['oneTimePassword']);
378 // }
379
380 result = {
381 message: 'credentialCheck',
382 version: cryptoVersion,
383 parameters: {
384 M1: srpConnection.M1()
385 }
386 };
387
388 return result;
389 });
390 deferredResult.addMethod(this.proxy(), 'handshake');
391 deferredResult.addCallback(function(someParameters) {
392 var result;
393
394 if (someParameters['M2'] == srpConnection.M2()) {
395 result = MochiKit.Async.succeed(someParameters);
396 } else {
397 result = MochiKit.Async.fail(Clipperz.PM.Connection.exception.WrongChecksum);
398 }
399
400 return result;
401 });
402 deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) {
403 this.setConnectionId(someParameters['connectionId']);
404 this.setSharedSecret(srpConnection.K());
405 // TODO: ?????
406 // if (this.oneTimePassword() != null) {
407 /// ?? result = this.user().oneTimePasswordManager().archiveOneTimePassword(this.oneTimePassword()));
408 // }
409
410 if ((isReconnecting == true) && (this.serverLockValue() != someParameters['lock'])) {
411 throw Clipperz.PM.Connection.exception.StaleData;
412 } else {
413 this.setServerLockValue(someParameters['lock']);
414 }
415
416 return someParameters;
417 }, this));
418 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_loggedIn');
419 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
420 // deferredResult.addCallback(MochiKit.Async.succeed, {result:"done"});
421
422 deferredResult.callback();
423
424 return deferredResult;
425 },
426
427 //=========================================================================
428
429 'logout': function() {
430 return Clipperz.Async.callbacks("Connection.logout", [
431 MochiKit.Base.method(this, 'setSharedSecret'),
432 MochiKit.Base.method(this.proxy(), 'logout', {})
433 ], {trace:false});
434 },
435
436 //=========================================================================
437
438 'ping': function () {
439 //TODO: ping the server in order to have a valid session
440 },
441
442 //=========================================================================
443
444 'message': function(aMessageName, someParameters) {
445 var args;
446 var parameters;
447
448 parameters = someParameters || {};
449 if (typeof(parameters['user']) != 'undefined') {
450 parameters['user']['lock'] = this.serverLockValue();
451 }
452
453 args = {
454 message: aMessageName,
455 srpSharedSecret: this.sharedSecret(),
456 // parameters: (someParameters || {})
457 parameters: parameters
458 }
459
460 return this.sendMessage(args);
461 },
462
463 //-------------------------------------------------------------------------
464
465 'sendMessage': function(someArguments) {
466 vardeferredResult;
467
468 deferredResult = new Clipperz.Async.Deferred("Connection.sendMessage", {trace:false});
469 deferredResult.addMethod(this.proxy(), 'message', someArguments);
470 deferredResult.addCallback(MochiKit.Base.bind(function(res) {
471 if (typeof(res['lock']) != 'undefined') {
472 this.setServerLockValue(res['lock']);
473 }
474 return res;
475 }, this));
476
477 deferredResult.addErrback(MochiKit.Base.method(this, 'messageExceptionHandler'), someArguments);
478 deferredResult.callback();
479
480 return deferredResult
481 },
482
483 //-------------------------------------------------------------------------
484
485 'messageExceptionHandler': function(anOriginalMessageArguments, anError) {
486 var result;
487
488Clipperz.log(">>> Connection.messageExceptionHandler: " + anError.message, anError);
489 if (anError instanceof MochiKit.Async.CancelledError) {
490 result = anError;
491 } else {
492 if ((anError.message == 'Trying to communicate without an active connection')||
493 (anError.message == 'No tollManager available for current session')
494 ) {
495 result = this.reestablishConnection(anOriginalMessageArguments);
496 } else if (anError.message == 'Session with stale data') {
497 MochiKit.Signal.signal(this, 'EXCEPTION');
498 } else {
499 result = anError;
500 }
501 }
502Clipperz.log("<<< Connection.messageExceptionHandler")
503
504 return result;;
505 },
506
507 //=========================================================================
508
509 'reestablishConnection': function(anOriginalMessageArguments) {
510 var deferredResult;
511
512 deferredResult = new Clipperz.Async.Deferred("Connection.reestablishConnection");
513 deferredResult.addMethod(this, 'reset');
514 deferredResult.addMethod(this, 'login', true);
515 deferredResult.addCallback(MochiKit.Base.bind(function(aMessage) {
516 aMessage['srpSharedSecret'] = this.sharedSecret();
517 return aMessage;
518 }, this), anOriginalMessageArguments);
519 deferredResult.addMethod(this, 'sendMessage');
520 deferredResult.addErrback(MochiKit.Signal.signal, this, 'EXCEPTION', null);
521 deferredResult.callback();
522
523 return deferredResult;
524 },
525
526 //=========================================================================
527
528 'serverSideUserCredentials': function(aUsername, aPassword) {
529 varresult;
530 varnewSrpConnection;
531 var normalizedAttributes;
532
533 normalizedAttributes = this.normalizedCredentials({username:aUsername, password:aPassword});
534 newSrpConnection = new Clipperz.Crypto.SRP.Connection({ C:normalizedAttributes['username'], P:normalizedAttributes['password'], hash:this.hash() });
535 result = newSrpConnection.serverSideCredentials();
536 result['version'] = this.clipperz_pm_crypto_version();
537
538 return result;
539 },
540
541 //=========================================================================
542
543 'normalizedCredentials': function(someValues) {
544 var result;
545
546 result = {}
547 result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'])).toHexString().substring(2);
548 result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2);
549
550 return result;
551 },
552
553 //-----------------------------------------------------------------------------
554
555 'hash': function() {
556 return Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].hash;
557 },
558
559 //-----------------------------------------------------------------------------
560 __syntaxFix__: "syntax fix"
561
562});
563
564
565
566//-----------------------------------------------------------------------------
567//
568 // S R P [ 1 . 1 ] C O N N E C T I O N class
569//
570//-----------------------------------------------------------------------------
571
572Clipperz.PM.Connection.SRP['1.1'] = function (args) {
573 Clipperz.PM.Connection.SRP['1.0'].call(this, args);
574
575 return this;
576}
577
578Clipperz.PM.Connection.SRP['1.1'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection.SRP['1.0'](), {
579
580 'version': function() {
581 return '1.1';
582 },
583
584 //-----------------------------------------------------------------------------
585
586 'normalizedCredentials': function(someValues) {
587 var result;
588
589 result = {}
590 result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'] + someValues['password'])).toHexString().substring(2);
591 result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2);
592
593 return result;
594 },
595
596 //-----------------------------------------------------------------------------
597
598 'hash': function() {
599 return Clipperz.PM.Crypto.encryptingFunctions.versions['0.2'].hash;
600 },
601
602 //-----------------------------------------------------------------------------
603 __syntaxFix__: "syntax fix"
604
605});
606
607Clipperz.PM.Connection.exception = {
608 WrongChecksum: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue"),
609 StaleData: new MochiKit.Base.NamedError("Stale data"),
610 UnexpectedRequest:new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.UnexpectedRequest")
611};
612
613
614Clipperz.PM.Connection.communicationProtocol = {
615 'currentVersion': '0.2',
616 'versions': {
617 '0.1': Clipperz.PM.Connection.SRP['1.0'],//Clipperz.Crypto.SRP.versions['1.0'].Connection,
618 '0.2': Clipperz.PM.Connection.SRP['1.1']//Clipperz.Crypto.SRP.versions['1.1'].Connection
619 },
620 'fallbackVersions': {
621 // 'current':'0.1',
622 '0.2': '0.1',
623 '0.1': null
624 }
625};
626
627MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.versions, {
628 'current': Clipperz.PM.Connection.communicationProtocol.versions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
629});
630
631MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.fallbackVersions, {
632 'current': Clipperz.PM.Connection.communicationProtocol.fallbackVersions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
633});
634
635
636
diff --git a/frontend/delta/js/Clipperz/PM/Crypto.js b/frontend/delta/js/Clipperz/PM/Crypto.js
new file mode 100644
index 0000000..7edf17f
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Crypto.js
@@ -0,0 +1,546 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.Crypto) == 'undefined') { Clipperz.PM.Crypto = {}; }
27
28Clipperz.PM.Crypto.VERSION = "0.2";
29Clipperz.PM.Crypto.NAME = "Clipperz.PM.Crypto";
30
31Clipperz.PM.Crypto.encryptingFunctions = {};
32
33MochiKit.Base.update(Clipperz.PM.Crypto, {
34
35 '__repr__': function () {
36 return "[" + this.NAME + " " + this.VERSION + "]";
37 },
38
39 //-------------------------------------------------------------------------
40
41 'toString': function () {
42 return this.__repr__();
43 },
44
45 //-------------------------------------------------------------------------
46/*
47 'communicationProtocol': {
48 'currentVersion': '0.2',
49 'versions': {
50 '0.1': Clipperz.PM.Connection.SRP['1.0'],//Clipperz.Crypto.SRP.versions['1.0'].Connection,
51 '0.2': Clipperz.PM.Connection.SRP['1.1']//Clipperz.Crypto.SRP.versions['1.1'].Connection
52 },
53 'fallbackVersions': {
54 'current':'0.1',
55 '0.2': '0.1',
56 '0.1': null
57 }
58 },
59*/
60 //-------------------------------------------------------------------------
61
62 'encryptingFunctions': {
63 'currentVersion': '0.4',
64 'versions': {
65
66 //#####################################################################
67
68 '0.1': {
69 'encrypt': function(aKey, aValue) {
70 return Clipperz.Crypto.Base.encryptUsingSecretKey(aKey, Clipperz.Base.serializeJSON(aValue));
71 },
72
73 'deferredEncrypt': function(aKey, aValue) {
74 var deferredResult;
75
76 deferredResult = new Clipperz.Async.Deferred("Crypto[0.1].deferredEncrypt");
77 deferredResult.addCallback(Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].encrypt, aKey, aValue);
78 deferredResult.callback();
79
80 return deferredResult;
81 },
82
83 'decrypt': function(aKey, aValue) {
84 var result;
85
86 if (aValue != null) {
87 result = Clipperz.Base.evalJSON(Clipperz.Crypto.Base.decryptUsingSecretKey(aKey, aValue));
88 } else {
89 result = null;
90 }
91
92 return result;
93 },
94
95 'deferredDecrypt': function(aKey, aValue) {
96 var deferredResult;
97
98 deferredResult = new Clipperz.Async.Deferred("Crypto.[0.1].deferredDecrypt");
99 deferredResult.addCallback(Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].decrypt, aKey, aValue);
100 deferredResult.callback();
101
102 return deferredResult;
103 },
104
105 'hash': function(aValue) {
106 var result;
107 var strngResult;
108
109 stringResult = Clipperz.Crypto.Base.computeHashValue(aValue.asString()); //!!!!!!!
110 result = new Clipperz.ByteArray("0x" + stringResult);
111
112 return result;
113 },
114
115 'deriveKey': function(aStringValue) {
116 return Clipperz.Crypto.Base.computeHashValue(aStringValue);
117 }
118 },
119
120 //#####################################################################
121
122 '0.2': {
123 'encrypt': function(aKey, aValue, aNonce) {
124 var result;
125 varkey, value;
126 var dataToEncrypt;
127 var encryptedData;
128
129 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
130 value = new Clipperz.ByteArray(Clipperz.Base.serializeJSON(aValue));
131 dataToEncrypt = Clipperz.Crypto.SHA.sha_d256(value).appendBlock(value);
132 encryptedData = Clipperz.Crypto.AES.encrypt(key, dataToEncrypt, aNonce);
133 result = encryptedData.toBase64String();
134
135 return result;
136 },
137
138 'deferredEncrypt': function(aKey, aValue, aNonce) {
139 var deferredResult;
140 varkey, value;
141 var dataToEncrypt;
142 // var encryptedData;
143
144 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
145 value = new Clipperz.ByteArray(Clipperz.Base.serializeJSON(aValue));
146 dataToEncrypt = Clipperz.Crypto.SHA.sha_d256(value).appendBlock(value);
147
148 deferredResult = new Clipperz.Async.Deferred("Crypto[0.2].deferredEncrypt")
149 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncrypt, key, dataToEncrypt, aNonce);
150 deferredResult.addCallback(function(aResult) {
151 return aResult.toBase64String();
152 })
153 deferredResult.callback();
154
155 return deferredResult;
156 },
157
158 'decrypt': function(aKey, aValue) {
159 var result;
160
161 if (aValue != null) {
162 var key, value;
163 var decryptedData;
164 var decryptedValue;
165
166 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
167 value = new Clipperz.ByteArray().appendBase64String(aValue);
168
169 decryptedData = Clipperz.Crypto.AES.decrypt(key, value);
170 decryptedValue = decryptedData.split((256/8));
171
172 try {
173 result = Clipperz.Base.evalJSON(decryptedValue.asString());
174 } catch (exception) {
175 Clipperz.logError("Error while decrypting data [1]");
176 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
177 }
178 } else {
179 result = null;
180 }
181
182 return result;
183 },
184
185 'deferredDecrypt': function(aKey, aValue) {
186 var result;
187
188 if (aValue != null) {
189 var deferredResult;
190 var key, value;
191 // var decryptedData;
192
193 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
194 value = new Clipperz.ByteArray().appendBase64String(aValue);
195
196 deferredResult = new Clipperz.Async.Deferred("Crypto.[0.2].deferredDecrypt");
197 deferredResult.addCallback(Clipperz.Crypto.AES.deferredDecrypt, key, value);
198 deferredResult.addCallback(function(aResult) {
199 var result;
200 var decryptedData;
201
202 decryptedData = aResult.split((256/8));
203
204 try {
205 result = Clipperz.Base.evalJSON(decryptedData.asString());
206 } catch (exception) {
207 Clipperz.logError("Error while decrypting data [2]");
208 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
209 }
210
211 return result;
212 })
213 deferredResult.callback();
214
215 result = deferredResult;
216 } else {
217 result = MochiKit.Async.succeed(null);
218 }
219
220 return result;
221 },
222
223 'hash': Clipperz.Crypto.SHA.sha_d256,
224
225 'deriveKey': function(aStringValue) {
226 varbyteData;
227 var result;
228
229 byteData = new Clipperz.ByteArray(aStringValue);
230 result = Clipperz.Crypto.SHA.sha_d256(byteData);
231
232 return result;
233 }
234 },
235
236 //#####################################################################
237
238 '0.3': {
239 'encrypt': function(aKey, aValue, aNonce) {
240 var result;
241 varkey, value;
242 var data;
243 var dataToEncrypt;
244 var encryptedData;
245
246 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
247 value = Clipperz.Base.serializeJSON(aValue);
248 data = new Clipperz.ByteArray(value);
249 encryptedData = Clipperz.Crypto.AES.encrypt(key, data, aNonce);
250 result = encryptedData.toBase64String();
251
252 return result;
253 },
254
255 'deferredEncrypt': function(aKey, aValue, aNonce) {
256 var deferredResult;
257 varkey, value;
258 var data;
259 var dataToEncrypt;
260 var encryptedData;
261
262 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
263 value = Clipperz.Base.serializeJSON(aValue);
264 data = new Clipperz.ByteArray(value);
265
266 deferredResult = new Clipperz.Async.Deferred("Crypto[0.3].deferredEncrypt")
267 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncrypt, key, data, aNonce);
268 deferredResult.addCallback(function(aResult) {
269 return aResult.toBase64String();
270 })
271 deferredResult.callback();
272
273 return deferredResult;
274 },
275
276 'decrypt': function(aKey, aValue) {
277 var result;
278
279 if (aValue != null) {
280 var key, value;
281 var decryptedData;
282
283 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
284 value = new Clipperz.ByteArray().appendBase64String(aValue);
285
286 decryptedData = Clipperz.Crypto.AES.decrypt(key, value);
287
288 value = decryptedData.asString();
289 try {
290 result = Clipperz.Base.evalJSON(value);
291 } catch (exception) {
292 Clipperz.logError("Error while decrypting data [3]");
293 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
294 }
295 } else {
296 result = null;
297 }
298
299 return result;
300 },
301
302 'deferredDecrypt': function(aKey, aValue) {
303 var deferredResult;
304
305 deferredResult = new Clipperz.Async.Deferred("Crypto[0.3].deferredDecrypt", {trace: false});
306 // now = new Date;
307
308 if (aValue != null) {
309 var key, value;
310 // var decryptedData;
311
312 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
313 value = new Clipperz.ByteArray().appendBase64String(aValue);
314
315 deferredResult.addCallback(Clipperz.Crypto.AES.deferredDecrypt, key, value);
316 deferredResult.addCallback(MochiKit.Async.wait, 0.1);
317 deferredResult.addCallback(function(aResult) {
318 return aResult.asString();
319 });
320 deferredResult.addCallback(MochiKit.Async.wait, 0.1);
321 deferredResult.addCallback(Clipperz.Base.evalJSON);
322 deferredResult.addErrback(function(anError) {
323console.log("PIPPO_1", anError)
324 Clipperz.logError("Error while decrypting data [4]");
325 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
326 })
327 } else {
328 deferredResult.addCallback(function() {
329 return null;
330 });
331 }
332 deferredResult.callback();
333
334 return deferredResult;
335 },
336
337 'hash': Clipperz.Crypto.SHA.sha_d256,
338
339 'deriveKey': function(aStringValue) {
340 varbyteData;
341 var result;
342
343 byteData = new Clipperz.ByteArray(aStringValue);
344 result = Clipperz.Crypto.SHA.sha_d256(byteData);
345
346 return result;
347 }
348 },
349
350 //#####################################################################
351
352 '0.4': {
353 'encrypt': function(aKey, aValue, aNonce) {
354 var result;
355 varkey, value;
356 var data;
357 var dataToEncrypt;
358 var encryptedData;
359
360 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
361 value = Clipperz.Base.serializeJSON(aValue);
362 data = new Clipperz.ByteArray(value);
363 encryptedData = Clipperz.Crypto.AES_2.encrypt(key, data, aNonce);
364 result = encryptedData.toBase64String();
365
366 return result;
367 },
368
369 'deferredEncrypt': function(aKey, aValue, aNonce) {
370 var deferredResult;
371 varkey, value;
372 var data;
373 var dataToEncrypt;
374 var encryptedData;
375
376 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
377 value = Clipperz.Base.serializeJSON(aValue);
378 data = new Clipperz.ByteArray(value);
379
380 deferredResult = new Clipperz.Async.Deferred("Crypto[0.4].deferredEncrypt")
381 deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredEncrypt, key, data, aNonce);
382 deferredResult.addCallback(function(aResult) {
383 return aResult.toBase64String();
384 })
385 deferredResult.callback();
386
387 return deferredResult;
388 },
389
390 'decrypt': function(aKey, aValue) {
391 var result;
392
393 if (aValue != null) {
394 var key, value;
395 var decryptedData;
396
397 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
398 value = new Clipperz.ByteArray().appendBase64String(aValue);
399
400 decryptedData = Clipperz.Crypto.AES_2.decrypt(key, value);
401
402 value = decryptedData.asString();
403 try {
404 result = Clipperz.Base.evalJSON(value);
405 } catch (exception) {
406 console.log("PIPPO_2", anError)
407 Clipperz.logError("Error while decrypting data [4]");
408 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
409 }
410 } else {
411 result = null;
412 }
413
414 return result;
415 },
416
417 'deferredDecrypt': function(aKey, aValue) {
418 var deferredResult;
419
420 deferredResult = new Clipperz.Async.Deferred("Crypto[0.4].deferredDecrypt", {trace: false});
421
422 if (aValue != null) {
423 var key, value;
424
425 key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
426 value = new Clipperz.ByteArray().appendBase64String(aValue);
427
428 deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredDecrypt, key, value);
429 deferredResult.addCallback(MochiKit.Async.wait, 0.1);
430 deferredResult.addCallback(function(aResult) {
431 return aResult.asString();
432 });
433 deferredResult.addCallback(MochiKit.Async.wait, 0.1);
434 deferredResult.addCallback(Clipperz.Base.evalJSON);
435 deferredResult.addErrback(function(anError) {
436 Clipperz.logError("Error while decrypting data [4]");
437 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
438 })
439 } else {
440 deferredResult.addCallback(function() {
441 return null;
442 });
443 }
444 deferredResult.callback();
445
446 return deferredResult;
447 },
448
449 'hash': Clipperz.Crypto.SHA.sha_d256,
450
451 'deriveKey': function(aStringValue) {
452 varbyteData;
453 var result;
454
455 byteData = new Clipperz.ByteArray(aStringValue);
456 result = Clipperz.Crypto.SHA.sha_d256(byteData);
457
458 return result;
459 }
460 },
461
462 //#####################################################################
463 __syntaxFix__: "syntax fix"
464 }
465 },
466
467 //-------------------------------------------------------------------------
468
469 'encrypt': function(aKey, aValue, aVersion) {
470 return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].encrypt(aKey, aValue);
471 },
472
473 'deferredEncrypt': function(someParameters) {
474 return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters['version']].deferredEncrypt(someParameters['key'], someParameters['value']);
475 },
476
477 //.........................................................................
478
479 'decrypt': function(aKey, aValue, aVersion) {
480 return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].decrypt(aKey, aValue);
481 },
482
483 'deferredDecrypt': function(someParameters) {
484 return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters['version']].deferredDecrypt(someParameters['key'], someParameters['value']);
485 },
486
487 //-------------------------------------------------------------------------
488
489 'hash': function(aValue) {
490 return Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion]['hash'](aValue);
491 },
492
493 //-------------------------------------------------------------------------
494
495 'randomKey': function() {
496 return Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
497 },
498
499 //-------------------------------------------------------------------------
500
501 'deriveKey': function(aValue) {
502 return Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion].deriveKey(aValue);
503 },
504
505 //-------------------------------------------------------------------------
506
507 'passwordEntropy': function(aValue) {
508 var result;
509 varbitPerChar;
510
511 bitPerChar = 4;
512 if (/[a-z]/.test(aValue)) {
513 bitPerChar ++;
514 }
515 if (/[A-Z]/.test(aValue)) {
516 bitPerChar ++;
517 }
518 if (/[^a-zA-Z0-9]/.test(aValue)) {
519 bitPerChar ++;
520 }
521
522 result = aValue.length * bitPerChar;
523
524 return result;
525 },
526
527 //-------------------------------------------------------------------------
528
529 'nullValue': '####',
530
531 //-------------------------------------------------------------------------
532 __syntaxFix__: "syntax fix"
533
534});
535
536//*****************************************************************************
537
538//MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.versions, {
539 //'current': Clipperz.PM.Connection.communicationProtocol.versions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
540//});
541
542MochiKit.Base.update(Clipperz.PM.Crypto.encryptingFunctions.versions, {
543 'current': Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion]
544});
545
546//*****************************************************************************
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js
new file mode 100644
index 0000000..8db90de
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js
@@ -0,0 +1,1086 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.DataModel');
25
26Clipperz.PM.DataModel.DirectLogin = function(args) {
27 args = args || {};
28
29 Clipperz.PM.DataModel.DirectLogin.superclass.constructor.apply(this, arguments);
30
31 this._reference =args.reference
32 ||Clipperz.PM.Crypto.randomKey();
33 this._record =args.record
34 ||Clipperz.Base.exception.raise('MandatoryParameter');
35
36 this._retrieveIndexDataFunction = args.retrieveIndexDataFunction
37 ||this.record().retrieveDirectLoginIndexDataFunction()
38 ||Clipperz.Base.exception.raise('MandatoryParameter');
39 this._setIndexDataFunction = args.setIndexDataFunction
40 ||this.record().setDirectLoginIndexDataFunction()
41 ||Clipperz.Base.exception.raise('MandatoryParameter');
42 this._removeIndexDataFunction =args.removeIndexDataFunction
43 ||this.record().removeDirectLoginIndexDataFunction()
44 ||Clipperz.Base.exception.raise('MandatoryParameter');
45
46 this._inputs = null;
47 this._bindings = null;
48 this._formValues = null;
49
50 // this._inputsDeferredLock = new MochiKit.Async.DeferredLock();
51 // this._bindingsDeferredLock = new MochiKit.Async.DeferredLock();
52 // this._formValuesDeferredLock = new MochiKit.Async.DeferredLock();
53
54 this._transientState = null;
55
56 this._isBrandNew = MochiKit.Base.isUndefinedOrNull(args.reference);
57
58 this.record().addDirectLogin(this);
59
60 return this;
61}
62
63Clipperz.Base.extend(Clipperz.PM.DataModel.DirectLogin, Object, {
64
65 'toString': function() {
66 return "DirectLogin (" + this.reference() + ")";
67 },
68
69 //=========================================================================
70
71 'reference': function () {
72 return this._reference;
73 },
74
75 //-------------------------------------------------------------------------
76
77 'record': function () {
78 return this._record;
79 },
80
81 //=========================================================================
82
83 'isBrandNew': function () {
84 return this._isBrandNew;
85 },
86
87 //=========================================================================
88
89 'removeIndexDataFunction': function () {
90 return this._removeIndexDataFunction;
91 },
92
93 'remove': function () {
94 return Clipperz.Async.callbacks("DirectLogin.remove", [
95 MochiKit.Base.partial(this.removeIndexDataFunction(), this.reference()),
96 MochiKit.Base.method(this.record(), 'removeDirectLogin', this)
97 ], {trace:false});
98 },
99
100 //=========================================================================
101 /*
102 'inputsDeferredLock': function () {
103 return this._inputsDeferredLock;
104 },
105
106 'bindingsDeferredLock': function () {
107 return this._bindingsDeferredLock;
108 },
109
110 'formValuesDeferredLock': function () {
111 return this._formValuesDeferredLock;
112 },
113*/
114 //=========================================================================
115
116 'label': function () {
117 return this.getIndexDataForKey('label');
118 },
119
120 'setLabelKeepingBackwardCompatibilityWithBeta': function (aValue) {
121 return Clipperz.Async.callbacks("DirectLogin.setLabelKeepingBackwardCompatibilityWithBeta", [
122 MochiKit.Base.method(this, 'setIndexDataForKey', 'label', aValue),
123 MochiKit.Base.method(this, 'setValue', 'label', aValue)
124 ], {trace:false});
125 },
126
127 'setLabel': function (aValue) {
128 return this.setLabelKeepingBackwardCompatibilityWithBeta(aValue);
129 // return this.setIndexDataForKey('label', aValue);
130 },
131
132 //=========================================================================
133
134 'favicon': function () {
135 return this.getIndexDataForKey('favicon');
136 },
137
138 'setFavicon': function (aValue) {
139 return this.setIndexDataForKey('favicon', aValue);
140 },
141
142 'faviconUrlWithBookmarkletConfiguration': function (aBookmarkletConfiguration) {
143 varresult;
144
145 if (! MochiKit.Base.isUndefinedOrNull(aBookmarkletConfiguration['page']['favicon'])) {
146 result = aBookmarkletConfiguration['page']['favicon'];
147 } else if (! MochiKit.Base.isUndefinedOrNull(aBookmarkletConfiguration['form']['attributes']['action'])) {
148 var actionUrl;
149 var hostname;
150
151 actionUrl = aBookmarkletConfiguration['form']['attributes']['action'];
152 hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
153 result = "http://" + hostname + "/favicon.ico";
154 } else {
155 result = null;
156 }
157
158
159 return result;
160 },
161
162 //-------------------------------------------------------------------------
163/*
164 'faviconData': function () {
165 var regexp = new RegExp('^data\:\/\/.*', 'i');
166
167 return Clipperz.Async.callbacks("DirectLogin.favicon", [
168 MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon'),
169 MochiKit.Base.method(regexp, 'test'),
170 Clipperz.Async.deferredIf("is data URL", [
171 MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon')
172 ], [
173 MochiKit.Base.method(this, 'transientState'),
174 MochiKit.Base.itemgetter('faviconData'),
175 Clipperz.Async.deferredIf('has a chaced value for the favicon data', [
176 MochiKit.Base.operator.identity
177 ], [
178 MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon'),
179 MochiKit.Base.method(this, 'loadFaviconDataFromURL')
180 ])
181
182 ])
183 ], {trace:false});
184 },
185
186 //-------------------------------------------------------------------------
187
188 'loadFaviconDataFromURL': function (anURL) {
189 var deferredResult;
190 var image;
191
192 deferredResult = new Clipperz.Async.Deferred("DirectLogin.loadFaviconDataFromURL", {trace:false});
193 deferredResult.addCallback(function (anEvent) {
194 var image = anEvent.src();
195 var canvas = document.createElement("canvas");
196 var result;
197
198 canvas.width = image.width;
199 canvas.height = image.height;
200
201 var ctx = canvas.getContext("2d");
202 ctx.drawImage(image, 0, 0);
203
204 result = canvas.toDataURL(/*"image/png"* /);
205
206 return result;
207 });
208 deferredResult.addErrback(MochiKit.Async.succeed, Clipperz.PM.Strings.getValue('defaultFaviconUrl'));
209 deferredResult.addBoth(MochiKit.Base.bind(function (aDataUrl) {
210 this.transientState()['faviconData'] = aDataUrl;
211
212 return aDataUrl;
213 }, this));
214
215 image = new Image();
216 MochiKit.Signal.connect(image, 'onload', MochiKit.Base.method(deferredResult, 'callback'));
217 MochiKit.Signal.connect(image, 'onerror', MochiKit.Base.method(deferredResult, 'errback'));
218 MochiKit.Signal.connect(image, 'onabort', MochiKit.Base.method(deferredResult, 'errback'));
219
220 image.src = anURL;
221
222 return deferredResult;
223 },
224*/
225
226 //=========================================================================
227
228 'type': function () {
229 return this.getValue('formData.attributes.type')
230 },
231
232 //=========================================================================
233
234 'serializedData': function () {
235 return Clipperz.Async.collectResults("DirectLogin.serializedData", {
236 'bookmarkletVersion': MochiKit.Base.method(this, 'getValue', 'bookmarkletVersion'),
237 'formData': MochiKit.Base.method(this, 'getValue', 'formData'),
238 'formValues': MochiKit.Base.method(this, 'getValue', 'formValues'),
239 'bindingData': [
240 MochiKit.Base.method(this, 'bindings'),
241 function (someBindings) {
242 var result;
243 var bindingKey;
244
245 result = {}
246 for (bindingKey in someBindings) {
247 result[bindingKey] = someBindings[bindingKey].serializedData();
248 }
249
250 return result;
251 }
252 ]
253 }, {trace:false})()
254 },
255
256 //=========================================================================
257/*
258 'fixFormDataFromBookmarkletVersion_0_1': function(aValue) {
259//{"type":"radio", "name":"action", "value":"new-user", "checked":false }, { "type":"radio", "name":"action", "value":"sign-in", "checked":true }
260 // ||
261 // \ /
262 // \/
263//{"name":"dominio", "type":"radio", "options":[{"value":"@alice.it", "checked":true}, {"value":"@tin.it", "checked":false}, {"value":"@virgilio.it", "checked":false}, {"value":"@tim.it", "checked":false}]}
264 var result;
265 var inputs;
266 var updatedInputs;
267 var radios;
268
269 result = aValue;
270 inputs = aValue['inputs'];
271
272 updatedInputs = MochiKit.Base.filter(function(anInput) {
273 varresult;
274 var type;
275
276 type = anInput['type'] || 'text';
277 result = type.toLowerCase() != 'radio';
278
279 return result;
280 }, inputs);
281 radios = MochiKit.Base.filter(function(anInput) {
282 varresult;
283 var type;
284
285 type = anInput['type'] || 'text';
286 result = type.toLowerCase() == 'radio';
287
288 return result;
289 }, inputs);
290
291 if (radios.length > 0) {
292 var updatedRadios;
293
294 updatedRadios = {};
295 MochiKit.Iter.forEach(radios, MochiKit.Base.bind(function(aRadio) {
296 varradioConfiguration;
297
298 radioConfiguration = updatedRadios[aRadio['name']];
299 if (radioConfiguration == null) {
300 radioConfiguration = {type:'radio', name:aRadio['name'], options:[]};
301 updatedRadios[aRadio['name']] = radioConfiguration;
302 }
303
304 //TODO: remove the value: field and replace it with element.dom.value = <some value>
305 radioConfiguration.options.push({value:aRadio['value'], checked:aRadio['checked']});
306
307 //TODO: shoud remove the 'formValues' call, as it is now deferred
308 // if ((aRadio['checked'] == true) && (this.formValues()[aRadio['name']] == null)) {
309 // this.formValues()[aRadio['name']] = aRadio['value'];
310 // }
311 }, this))
312
313 updatedInputs = MochiKit.Base.concat(updatedInputs, MochiKit.Base.values(updatedRadios));
314 }
315
316 delete result.inputs;
317 result.inputs = updatedInputs;
318
319 return result;
320 },
321
322 '_fixConfiguration': function (aConfiguration) {
323 var fixedConfiguration;
324 // var inputs;
325 // var bindings;
326 // var i,c;
327
328 fixedConfiguration = Clipperz.Base.deepClone(aConfiguration);
329
330//Clipperz.log("PROCESS CONFIGURATION", aConfiguration);
331 switch (aConfiguration['bookmarkletVersion']) {
332 case '0.1':
333 fixedConfiguration['formData'] = this.fixFormDataFromBookmarkletVersion_0_1(aConfiguration['formData']);
334 break;
335 case '0.2':
336 fixedConfiguration['formData'] = aConfiguration['formData'];
337 break;
338 }
339
340 / *
341 aConfiguration['_inputs'] = [];
342 c = formData['inputs'].length;
343 for (i=0; i<c; i++) {
344 aConfiguration['_inputs'].push(new Clipperz.PM.DataModel.DirectLoginInput(formData['inputs'][i]));
345 }
346* /
347/ *
348 aConfiguration['_bindings'] = {};
349 if (aConfiguration['legacyBindingData'] == null) {
350 if (aConfiguration['bindingData'] != null) {
351 var bindingKey;
352
353 for (bindingKey in aConfiguration['bindingData']) {
354 var newBinding;
355
356 newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(bindingKey, {fieldKey:aConfiguration['bindingData'][bindingKey]});
357 aConfiguration['_bindings'][newBinding.key()] = newBinding;
358 }
359 } else {
360 var editableFields;
361
362 editableFields = MochiKit.Base.filter(function(aField) {
363 var result;
364 var type;
365
366 type = aField['type'].toLowerCase();
367 result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select'));
368
369 return result;
370 }, aConfiguration['_inputs']);
371
372 MochiKit.Iter.forEach(editableFields, MochiKit.Base.bind(function(anEditableField) {
373 var newBinding;
374
375 newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(anEditableField['name']);
376 aConfiguration['_bindings'][newBinding.key()] = newBinding;
377 }, this));
378 }
379
380 } else {
381 var bindingKey;
382
383 for (bindingKey in aConfiguration['legacyBindingData']) {
384 var newBinding;
385
386 newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(bindingKey, {fieldName:aConfiguration['legacyBindingData'][bindingKey]});
387 aConfiguration['_bindings'][newBinding.key()] = newBinding;
388 }
389 }
390* /
391
392 return fixedConfiguration;
393 },
394
395 //-------------------------------------------------------------------------
396
397 'getObjectDataStore': function () {
398 var deferredResult;
399
400 deferredResult = new Clipperz.Async.Deferred("DirectLogin.getObjectDataStore", {trace:false});
401 deferredResult.acquireLock(this.objectDataStoreDeferredLock());
402 deferredResult.addCallback(MochiKit.Base.bind(function () {
403 var innerDeferredResult;
404
405 if (this._objectDataStore == null) {
406 this._objectDataStore = new Clipperz.KeyValueObjectStore();
407
408 innerDeferredResult = new Clipperz.Async.Deferred("DirectLogin.getObjectDataStore <inner deferred>", {trace:false});
409 // innerDeferredResult.addMethod(this.record(), 'getValue', 'directLogins' + '.' + this.reference());
410 innerDeferredResult.addMethod(this, 'getValue', ''),
411 innerDeferredResult.addMethod(this, 'setOriginalState');
412 innerDeferredResult.addMethod(this, '_fixConfiguration');
413 innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues');
414 // innerDeferredResult.addMethod(this._objectDataStore, 'setValues');
415 innerDeferredResult.callback();
416 } else {
417 innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore);
418 }
419
420 return innerDeferredResult;
421 }, this));
422 deferredResult.releaseLock(this.objectDataStoreDeferredLock());
423 deferredResult.callback();
424
425 return deferredResult;
426 },
427
428 //-------------------------------------------------------------------------
429
430 'hasInitiatedObjectDataStore': function () {
431 return (this._objectDataStore != null);
432 },
433
434 //-------------------------------------------------------------------------
435
436 'resetObjectDataStore': function () {
437 this._objectDataStore.removeAllData();
438 this._objectDataStore = null;
439 },
440*/
441 //=========================================================================
442
443 'bookmarkletConfiguration': function () {
444 return Clipperz.Async.callbacks("DirectLogin.bookmarkletConfiguration", [
445 Clipperz.Async.collectResults("DirectLogin.bookmarkletConfiguration <inner results>", {
446 'label': MochiKit.Base.method(this, 'label'),
447 'configuration': MochiKit.Base.method(this, 'getValue', '')
448 }, {trace:false}),
449 function (someValues) {
450 var result;
451
452 if (someValues['configuration'] != null) {
453 varconfiguration;
454
455 configuration = {
456 'page': {
457 'title': someValues['label']
458 //'favicon'
459 // 'url'
460 },
461 'form': someValues['configuration']['formData'],
462 'version':someValues['configuration']['bookmarkletVersion']
463 }
464
465 result = Clipperz.Base.formatJSON(configuration);
466 } else {
467 result = '';
468 }
469
470 return result;
471 }
472 ], {trace:false});
473
474 },
475
476 //-------------------------------------------------------------------------
477
478 'setBookmarkletConfiguration': function (aValue) {
479 var bookmarkletConfiguration;
480
481 bookmarkletConfiguration = Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration(aValue);
482
483 return Clipperz.Async.callbacks("DirectLogin.setBookmarkletConfiguration", [
484 MochiKit.Base.method(this, 'setValue', 'formData', bookmarkletConfiguration['form']),
485 MochiKit.Base.method(this, 'setValue', 'bookmarkletVersion', bookmarkletConfiguration['version']),
486
487 MochiKit.Base.method(this, 'favicon'),
488 Clipperz.Async.deferredIf("the favicon is not set", [
489 ], [
490 MochiKit.Base.method(this, 'faviconUrlWithBookmarkletConfiguration', bookmarkletConfiguration),
491 MochiKit.Base.method(this, 'setFavicon')
492 ]),
493
494 MochiKit.Base.method(this, 'updateInputsAfterChangingBookmarkletConfiguration'),
495 MochiKit.Base.method(this, 'updateFormValuesAfterChangingBookmarkletConfiguration'),
496 MochiKit.Base.method(this, 'updateBindingsAfterChangingBookmarkletConfiguration'),
497
498 MochiKit.Base.noop
499 ], {trace:false});
500 },
501
502 //=========================================================================
503
504 'formAttributes': function () {
505 return this.getValue('formData.attributes');
506 },
507
508 //=========================================================================
509
510 'inputs': function () {
511 return Clipperz.Async.callbacks("DirectLogin.inputs", [
512 Clipperz.Async.deferredIf("this._inputs is defined", [
513 ], [
514 MochiKit.Base.method(this, 'updateInputsAfterChangingBookmarkletConfiguration')
515 ])
516 ], {trace:false}, this._inputs);
517 },
518
519 'setInputWithFormDataConfiguration': function (aFormDataConfiguration) {
520 this._inputs = {};
521
522 if (aFormDataConfiguration != null) {
523 MochiKit.Iter.forEach(aFormDataConfiguration['inputs'], MochiKit.Base.bind(function (anInputData) {
524 var newInput;
525
526 newInput = new Clipperz.PM.DataModel.DirectLoginInput(anInputData);
527 this._inputs[newInput.name()] = newInput;
528 }, this));
529 }
530
531 return this._inputs;
532 },
533
534 'updateInputsAfterChangingBookmarkletConfiguration': function () {
535 return Clipperz.Async.callbacks("DirectLogin.updateInputsAfterChangingBookmarkletConfiguration", [
536 MochiKit.Base.method(this, 'getValue', 'formData'),
537 MochiKit.Base.method(this, 'setInputWithFormDataConfiguration')
538 ], {trace:false});
539 },
540
541 //=========================================================================
542
543 'inputValues': function () {
544 return Clipperz.Async.callbacks("DirectLogin.inputValues", [
545 MochiKit.Base.method(this, 'inputs'),
546 MochiKit.Base.values,
547 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.partial(MochiKit.Base.method(this, 'inputValue'))),
548 Clipperz.Async.collectAll,
549 Clipperz.Base.mergeItems
550 ], {trace:false});
551 },
552
553 'inputValue': function (anInput) {
554 vardeferredResult;
555
556 deferredResult = new Clipperz.Async.Deferred("DirectLogin.inputValue", {trace:false});
557
558 if (anInput.needsFormValue()) {
559 deferredResult.addMethod(this, 'formValues');
560 deferredResult.addCallback(MochiKit.Base.itemgetter(anInput.name()));
561 deferredResult.addMethodcaller('value');
562 } else if (anInput.needsBinding()) {
563 deferredResult.addMethod(this, 'bindings');
564 deferredResult.addCallback(MochiKit.Base.itemgetter(anInput.name()));
565 deferredResult.addMethodcaller('field');
566 deferredResult.addMethodcaller('value');
567 } else {
568 deferredResult.addCallback(MochiKit.Async.succeed, anInput.value());
569 }
570 deferredResult.addCallback(function (anActualValue) {
571 return [anInput.name(), anActualValue];
572 });
573
574 deferredResult.callback();
575
576 return deferredResult;
577 },
578
579 //=========================================================================
580
581 'bindings': function () {
582 return Clipperz.Async.callbacks("DirectLogin.bindings", [
583 Clipperz.Async.deferredIf("this._bindings is defined", [
584 ], [
585 MochiKit.Base.method(this, 'updateBindingsAfterChangingBookmarkletConfiguration'),
586 MochiKit.Base.bind(function () { return this._bindings;}, this)
587 ])
588 ], {trace:false}, this._bindings);
589 },
590
591 'bindFormFieldWithLabelToRecordFieldWithLabel': function (aFormFieldLabel, aRecordFieldLabel) {
592 return Clipperz.Async.callbacks("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel", [
593 Clipperz.Async.collectResults("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel - collect results", {
594 'binding': [
595 MochiKit.Base.method(this, 'bindings'),
596 MochiKit.Base.itemgetter(aFormFieldLabel)
597 ],
598 'field': [
599 MochiKit.Base.method(this.record(), 'fieldWithLabel', aRecordFieldLabel)
600 ]
601 }),
602 function (someValues) {
603 someValues['binding'].setField(someValues['field'])
604 }
605 ], {trace:false});
606 },
607
608 //-------------------------------------------------------------------------
609/*
610 'bindingValues': function () {
611 return Clipperz.Async.callbacks("DirectLogin.bindingValues", [
612 Clipperz.Async.collectResults("DirectLogin.bindingValues [collectResults]", {
613 'fieldValues': [
614 MochiKit.Base.method(this, 'record'),
615 MochiKit.Base.methodcaller('getFieldsValues')
616 ],
617 'bindings': MochiKit.Base.method(this, 'bindings')
618 }, {trace:false}),
619 function (someData) {
620 var result;
621 varbindingKey;
622
623 result = {};
624 for (bindingKey in someData['bindings']) {
625 result[bindingKey] = someData['fieldValues'][someData['bindings'][bindingKey].fieldKey()]['value'];
626 }
627
628 return result;
629 }
630 ], {trace:false});
631 },
632*/
633 //-------------------------------------------------------------------------
634
635 'updateBindingsAfterChangingBookmarkletConfiguration': function () {
636 return Clipperz.Async.callbacks("DirectLogin.updateBindingsAfterChangingBookmarkletConfiguration", [
637 Clipperz.Async.collectResults("DirectLogin.updateBindingsAfterChangingBookmarkletConfiguration<collect results>", {
638 'currentValues':MochiKit.Base.method(this, 'getValue', ''),
639 'originalValues':MochiKit.Base.method(this, 'originalConfiguration'),
640 'inputs': MochiKit.Base.method(this, 'inputs')
641 }, {trace:false}),
642 MochiKit.Base.bind(function (someValues) {
643 var availableBindingValues;
644 var inputRequiringBindingValues;
645 var newBindingValues;
646
647 if (MochiKit.Base.isUndefinedOrNull(someValues['originalValues']) || MochiKit.Base.isUndefinedOrNull(someValues['originalValues']['bindingData'])) {
648 availableBindingValues = {};
649 } else {
650 availableBindingValues = Clipperz.Base.deepClone(someValues['originalValues']['bindingData'])
651 }
652
653 if (someValues['currentValues'] != null) {
654 MochiKit.Base.update(availableBindingValues, someValues['currentValues']['bindingData']);
655 }
656
657 this._bindings = {};
658 newBindingValues = {}
659 MochiKit.Iter.forEach(MochiKit.Base.filter(MochiKit.Base.methodcaller('needsBinding'), MochiKit.Base.values(someValues['inputs'])), MochiKit.Base.bind(function (anInput) {
660 varnewBinding;
661
662 newBindingValues[anInput.name()] = availableBindingValues[anInput.name()];
663 newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, {
664 'key': anInput.name(),
665 'field':availableBindingValues[anInput.name()]
666 });
667
668 this._bindings[anInput.name()] = newBinding;
669 }, this))
670
671 return newBindingValues;
672
673/*
674 this._bindings = {};
675
676 if (someValues['currentValues'] != null) {
677 if (someValues['currentValues']['bindingData'] != null) {
678 var bindingKey;
679
680 for (bindingKey in someValues['currentValues']['bindingData']) {
681 var newBinding;
682
683 newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, {
684 'key': bindingKey,
685 'field':someValues['currentValues']['bindingData'][bindingKey]
686 });
687 this._bindings[newBinding.key()] = newBinding;
688 }
689 } else if (someValues['currentValues']['legacyBindingData'] == null) {
690 var bindingKey;
691
692 for (bindingKey in someValues['currentValues']['legacyBindingData']) {
693 var newBinding;
694
695 newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, {
696 'key': bindingKey,
697 'field':someValues['currentValues']['legacyBindingData'][bindingKey]
698 });
699 this._bindings[newBinding.key()] = newBinding;
700 }
701 } else {
702 WTF = TODO;
703 }
704 }
705
706 return this._bindings;
707*/
708 }, this),
709 MochiKit.Base.method(this, 'setValue', 'bindingData')
710 ], {trace:false});
711 },
712
713 //=========================================================================
714
715 'formValues': function () {
716 return Clipperz.Async.callbacks("DirectLogin.formValues", [
717 Clipperz.Async.deferredIf("this._formValues is defined", [
718 ], [
719 MochiKit.Base.method(this, 'updateFormValuesAfterChangingBookmarkletConfiguration'),
720 MochiKit.Base.bind(function () { return this._formValues;}, this)
721 ])
722 ], {trace:false}, this._formValues);
723 },
724
725 //-------------------------------------------------------------------------
726
727 'updateFormValuesAfterChangingBookmarkletConfiguration': function () {
728 return Clipperz.Async.callbacks("DirectLogin.updateFormValuesAfterChangingBookmarkletConfiguration", [
729 Clipperz.Async.collectResults("DirectLogin.updateFormValuesAfterChangingBookmarkletConfiguration <collect results>", {
730 'currentValues':MochiKit.Base.method(this, 'getValue', ''),
731 'originalValues':MochiKit.Base.method(this, 'originalConfiguration'),
732 'inputs': MochiKit.Base.method(this, 'inputs')
733 }, {trace:false}),
734 MochiKit.Base.bind(function (someValues) {
735 var availableFormValues;
736 var inputRequiringFormValues;
737 var newFormValues;
738
739 if (MochiKit.Base.isUndefinedOrNull(someValues['originalValues']) || MochiKit.Base.isUndefinedOrNull(someValues['originalValues']['formValues'])) {
740 availableFormValues = {};
741 } else {
742 availableFormValues = Clipperz.Base.deepClone(someValues['originalValues']['formValues'])
743 }
744
745 MochiKit.Base.update(availableFormValues, someValues['currentValues']['formValues']);
746
747 this._formValues = {};
748 newFormValues = {};
749 MochiKit.Iter.forEach(MochiKit.Base.filter(MochiKit.Base.methodcaller('needsFormValue'), MochiKit.Base.values(someValues['inputs'])), MochiKit.Base.bind(function (anInput) {
750 varnewFormValue;
751 var fieldOptions;
752
753 fieldOptions = {
754 'type': anInput.type(),
755 'options':anInput.options()
756 };
757
758 newFormValues[anInput.name()] = availableFormValues[anInput.name()]
759 newFormValue = new Clipperz.PM.DataModel.DirectLoginFormValue(this, {
760 'key': anInput.name(),
761 'fieldOptions':fieldOptions,
762 'value': availableFormValues[anInput.name()]
763 });
764
765 this._formValues[anInput.name()] = newFormValue;
766 }, this))
767
768 return newFormValues;
769 }, this),
770 MochiKit.Base.method(this, 'setValue', 'formValues')
771 ], {trace:false});
772 },
773
774 //=========================================================================
775
776 'retrieveIndexDataFunction': function () {
777 return this._retrieveIndexDataFunction;
778 },
779
780 'getIndexDataForKey': function (aKey) {
781 return Clipperz.Async.callbacks("DirectLogin.getIndexDataForKey", [
782 MochiKit.Base.partial(this.retrieveIndexDataFunction(), this.reference()),
783 Clipperz.Async.deferredIf("DirectLogin.getIndexDataForKey - index data not null", [
784 MochiKit.Base.itemgetter(aKey)
785 ],[
786 MochiKit.Async.succeed
787 ])
788 ], {trace:false});
789 },
790
791 //-------------------------------------------------------------------------
792
793 'setIndexDataForKey': function (aKey, aValue) {
794 return Clipperz.Async.callbacks("DirectLogin.setValueForKey", [
795 MochiKit.Base.method(this, 'getIndexDataForKey', aKey),
796 MochiKit.Base.bind(function (anActualValue) {
797 var transientStateKey;
798
799 transientStateKey = 'original_' + aKey;
800 if (MochiKit.Base.isUndefinedOrNull(this.transientState()[transientStateKey])) {
801 if (anActualValue != aValue) {
802 this.transientState()[transientStateKey] = anActualValue;
803 }
804 } else if (this.transientState()[transientStateKey] == aValue) {
805 this.transientState()[transientStateKey] = null;
806 }
807 }, this),
808 MochiKit.Base.partial(this._setIndexDataFunction, this.reference(), aKey, aValue)
809 ], {trace:false})
810 },
811
812 //-------------------------------------------------------------------------
813/*
814 'setValueForKey': function (aKey, aValue) {
815 return Clipperz.Async.callbacks("DirectLogin.setValueForKey", [
816 MochiKit.Base.method(this, 'getIndexDataForKey', aKey),
817 MochiKit.Base.bind(function (anActualValue) {
818 var transientStateKey;
819
820 transientStateKey = 'original_' + aKey;
821 if (MochiKit.Base.isUndefinedOrNull(this.transientState()[transientStateKey])) {
822 if (anActualValue != aValue) {
823 this.transientState()[transientStateKey] = anActualValue;
824 }
825 } else if (this.transientState()[transientStateKey] == aValue) {
826 this.transientState()[transientStateKey] = null;
827 }
828 }, this),
829 MochiKit.Base.method(this, 'setIndexDataForKey', aKey, aValue)
830 ], {trace:false})
831 },
832*/
833 //=========================================================================
834/*
835 'storedConfiguration': function () {
836 return this.record().getValue('directLogins' + '.' + this.reference());
837 },
838
839 //'setStoredConfiguration': function (aValue) {
840 // return this.record().setValue('directLogins' + '.' + this.reference(), aValue);
841 //},
842*/
843 //=========================================================================
844
845 'hasPendingChanges': function () {
846 varresult;
847 var deferredResult;
848
849 result = false;
850 result = result || this.isBrandNew();
851 result = result || (! MochiKit.Base.isUndefinedOrNull(this.transientState()['original_label']));
852 result = result || (! MochiKit.Base.isUndefinedOrNull(this.transientState()['original_favicon']));
853
854 if ((result == false) && (this.originalConfiguration() != null)) {
855 deferredResult = Clipperz.Async.callbacks("DirectLogin.hasPendingChanges", [
856 MochiKit.Base.method(this, 'serializedData'),
857 MochiKit.Base.bind(function (aCurrentConfiguration) {
858 varoriginalConfiguration;
859 var currentConfiguration;
860 var result;
861
862 originalConfiguration = this.originalConfiguration();
863 currentConfiguration = aCurrentConfiguration;
864
865 result = false;
866 result = result || (MochiKit.Base.compare(originalConfiguration['bookmarkletVersion'], currentConfiguration['bookmarkletVersion'])!= 0);
867 result = result || (MochiKit.Base.compare(originalConfiguration['formData'], currentConfiguration['formData']) != 0);
868 result = result || (MochiKit.Base.compare(originalConfiguration['formValues'], currentConfiguration['formValues']) != 0);
869 result = result || (MochiKit.Base.compare(originalConfiguration['bindingData'], currentConfiguration['bindingData']) != 0);
870
871 return result;
872 }, this)
873 ], {trace:false});
874 } else {
875 deferredResult = MochiKit.Async.succeed(result);
876 }
877
878 return deferredResult;
879 },
880
881 //-------------------------------------------------------------------------
882
883 'revertChanges': function () {
884 var deferredResult;
885
886 if (this.transientState()['original_label'] != null) {
887 this.setLabel(this.transientState()['original_label']);
888 }
889
890 if (this.transientState()['original_favicon'] != null) {
891 this.setFavicon(this.transientState()['original_favicon']);
892 }
893
894 if (this.originalConfiguration() != null) {
895 deferredResult = this.setValue('', this.originalConfiguration());
896 } else {
897 deferredResult = MochiKit.Async.succeed();
898 }
899
900 this._inputs = null;
901 this._bindings = null;
902 this._formValues= null;
903
904 this.resetTransientState(false);
905
906/*
907 if (this.hasInitiatedObjectDataStore()) {
908 deferredResult = Clipperz.Async.callbacks("DirectLogin.revertChanges", [
909 // MochiKit.Base.method(this.record(), 'setValue', 'directLogins' + '.' + this.reference(), this.originalState()),
910 MochiKit.Base.method(this, 'setValue', '', this.originalState()),
911 MochiKit.Base.method(this, 'resetObjectDataStore')
912 ], {trace:false})
913 } else {
914 deferredResult = MochiKit.Async.succeed();
915 }
916*/
917 return deferredResult;
918 },
919
920
921 //=========================================================================
922
923 'transientState': function () {
924 if (this._transientState == null) {
925 this._transientState = {}
926 }
927
928 return this._transientState;
929 },
930
931 'resetTransientState': function (isCommitting) {
932 this._transientState = null;
933 },
934
935 'commitTransientState': function (isCommitting) {
936 this._transientState = null;
937 this._isBrandNew = false;
938 },
939
940 //-------------------------------------------------------------------------
941
942 'originalConfiguration': function () {
943 return this.transientState()['original_configuration'];
944 },
945
946 'setOriginalConfiguration': function (aConfiguration) {
947 this.transientState()['original_configuration'] = Clipperz.Base.deepClone(aConfiguration);
948 },
949
950 //=========================================================================
951
952 'actualKey': function (aValueKey) {
953 var actualKey;
954
955 actualKey = 'directLogins' + '.' + this.reference();
956 if (aValueKey != '') {
957 actualKey = actualKey + '.' + aValueKey;
958 }
959
960 return actualKey;
961 },
962
963 //-------------------------------------------------------------------------
964
965 'getValue': function (aValueKey) {
966 return this.record().getValue(this.actualKey(aValueKey));
967 },
968
969 'setValue': function (aValueKey, aValue) {
970 // return this.record().setValue(this.actualKey(aValueKey), aValue);
971
972 return Clipperz.Async.callbacks("DirectLogin.setValue", [
973 MochiKit.Base.method(this, 'getValue', ''),
974 MochiKit.Base.bind(function (aValue) {
975 if (this.originalConfiguration() == null) {
976 this.setOriginalConfiguration(aValue);
977 }
978 }, this),
979 // MochiKit.Base.method(this, 'originalConfiguration'),
980 // Clipperz.Async.deferredIf("originalConfiguration has been set", [
981 // ], [
982 // MochiKit.Base.method(this, 'getValue', ''),
983 // MochiKit.Base.method(this, 'setOriginalConfiguration')
984 // ]),
985 MochiKit.Base.method(this.record(), 'setValue', this.actualKey(aValueKey), aValue)
986 ], {trace:false});
987 },
988
989 'removeValue': function (aValueKey) {
990 // return this.record().removeValue(this.actualKey(aValueKey));
991
992 return Clipperz.Async.callbacks("DirectLogin.setValue", [
993 MochiKit.Base.method(this, 'originalConfiguration'),
994 Clipperz.Async.deferredIf("originalConfiguration has been set", [
995 ], [
996 MochiKit.Base.method(this, 'getValue', ''),
997 MochiKit.Base.method(this, 'setOriginalConfiguration')
998 ]),
999 MochiKit.Base.method(this.record(), 'removeValue', this.actualKey(aValueKey))
1000 ], {trace:false});
1001 },
1002
1003 //=========================================================================
1004
1005 'content': function () {
1006 // return this.serializedData();
1007 // return MochiKit.Async.succeed(this);
1008
1009 var deferredResult;
1010 varfieldValues;
1011
1012 fieldValues = {};
1013 deferredResult = new Clipperz.Async.Deferred("DirectLogin.content", {trace:false});
1014 deferredResult.addMethod(this, 'reference');
1015 deferredResult.addCallback(function (aValue) { fieldValues['reference'] = aValue; });
1016 deferredResult.addMethod(this, 'label');
1017 deferredResult.addCallback(function (aValue) { fieldValues['label'] = aValue; });
1018 deferredResult.addMethod(this, 'favicon');
1019 deferredResult.addCallback(function (aValue) { fieldValues['favicon'] = aValue; });
1020 deferredResult.addCallback(function () { return fieldValues; });
1021 deferredResult.callback();
1022
1023 return deferredResult;
1024 },
1025
1026 //=========================================================================
1027
1028 'deleteAllCleanTextData': function () {
1029 this._inputs = null;
1030 this._bindings = null;
1031 this._formValues = null;
1032
1033 this.resetTransientState();
1034 },
1035
1036 //-------------------------------------------------------------------------
1037
1038 'hasAnyCleanTextData': function () {
1039 var result;
1040
1041 result = false;
1042
1043 result = result || (this._inputs != null);
1044 result = result || (this._bindings != null);
1045 result = result || (this._formValues != null);
1046 result = result || (MochiKit.Base.keys(this.transientState()).length != 0);
1047
1048 return MochiKit.Async.succeed(result);
1049 },
1050
1051 //=========================================================================
1052 __syntaxFix__: "syntax fix"
1053});
1054
1055//#############################################################################
1056
1057Clipperz.PM.DataModel.DirectLogin.exception = {
1058 'WrongBookmarkletConfiguration': new MochiKit.Base.NamedError("Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration")
1059};
1060
1061Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration = function(aConfiguration) {
1062 var configuration;
1063
1064 try {
1065 configuration = Clipperz.Base.evalJSON(aConfiguration);
1066 // configuration = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(configuration);
1067
1068 if (MochiKit.Base.isUndefinedOrNull(configuration['page']['title'])
1069 ||MochiKit.Base.isUndefinedOrNull(configuration['form']['attributes']['action'])
1070 // ||MochiKit.Base.isUndefinedOrNull(configuration['form']['attributes']['method'])
1071 ||MochiKit.Base.isUndefinedOrNull(configuration['form']['inputs'])
1072 ||MochiKit.Base.isUndefinedOrNull(configuration['version'])
1073 ) {
1074 throw Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration;
1075 }
1076
1077 // if (MochiKit.Base.isUndefinedOrNull(configuration['favicon'])) {
1078 // throw Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration;
1079 // }
1080
1081 } catch (exception) {
1082 throw exception;
1083 }
1084
1085 return configuration;
1086};
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js
new file mode 100644
index 0000000..a8ebb97
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js
@@ -0,0 +1,120 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28
29//#############################################################################
30
31Clipperz.PM.DataModel.DirectLoginBinding = function(aDirectLogin, args) {
32 args = args || {};
33
34 this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter');
35
36 this._key = args.key|| Clipperz.Base.exception.raise('MandatoryParameter');
37 this._fieldKey = args.field || /* this.directLogin().fieldWithName(args.fieldName).reference() || */null;
38
39 return this;
40}
41
42Clipperz.PM.DataModel.DirectLoginBinding.prototype = MochiKit.Base.update(null, {
43
44 'toString': function() {
45 return "DirectLoginBinding (" + this.key() + ", " + this.fieldKey() + ")";
46 },
47
48 //-------------------------------------------------------------------------
49
50 'directLogin': function () {
51 return this._directLogin;
52 },
53
54 //-------------------------------------------------------------------------
55
56 'key': function() {
57 return this._key;
58 },
59
60 //-------------------------------------------------------------------------
61
62 'fieldKey': function() {
63 return this._fieldKey;
64 },
65
66 'setFieldKey': function(aValue) {
67 this._fieldKey = aValue;
68
69 return this.directLogin().setValue('bindingData' + '.' + this.key(), aValue);
70 },
71
72 //'fieldName': function() {
73 // return this._fieldName;
74 //},
75
76 //-------------------------------------------------------------------------
77
78 'field': function() {
79 var deferredResult;
80
81 if (this.fieldKey() != null) {
82 deferredResult = Clipperz.Async.callbacks("DirectLoginBinding.field [1]", [
83 MochiKit.Base.method(this.directLogin().record(), 'fields'),
84 MochiKit.Base.itemgetter(this.fieldKey())
85 ], {trace:false});
86 // } else if (this.fieldName() != null) {
87 // WTF = TODO;
88 // result = this.directLogin().record().fieldWithName(this.fieldName());
89 //
90 // this.setFieldKey(result.key());
91 } else {
92 deferredResult = MochiKit.Async.succeed(null);
93 }
94
95 return deferredResult;
96 },
97
98 'setField': function (aField) {
99 this.setFieldKey(aField.reference());
100 },
101
102 //-------------------------------------------------------------------------
103/*
104 'fieldValue': function () {
105 return Clipperz.Async.callbacks("DirectLoginBinding.fieldValue", [
106 MochiKit.Base.method('field'),
107 MochiKit.Base.methodcaller('value')
108 ], {trace:false});
109 },
110*/
111 //-------------------------------------------------------------------------
112
113 'serializedData': function() {
114 return this.fieldKey();
115 },
116
117 //-------------------------------------------------------------------------
118 __syntaxFix__: "syntax fix"
119});
120
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js
new file mode 100644
index 0000000..2429f88
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js
@@ -0,0 +1,101 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28
29//#############################################################################
30
31Clipperz.PM.DataModel.DirectLoginFormValue = function(aDirectLogin, args) {
32 args = args || {};
33
34 this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter');
35
36 this._key = args.key || Clipperz.Base.exception.raise('MandatoryParameter');
37 this._fieldOptions = args.fieldOptions|| Clipperz.Base.exception.raise('MandatoryParameter');
38 this._value = args.value || null;
39
40 return this;
41}
42
43Clipperz.PM.DataModel.DirectLoginFormValue.prototype = MochiKit.Base.update(null, {
44
45 'toString': function() {
46 return "DirectLoginFormValue (" + this.key() + ", " + this.value() + ")";
47 },
48
49 //-------------------------------------------------------------------------
50
51 'directLogin': function () {
52 return this._directLogin;
53 },
54
55 //-------------------------------------------------------------------------
56
57 'key': function() {
58 return this._key;
59 },
60
61 //-------------------------------------------------------------------------
62
63 'fieldOptions': function() {
64 return this._fieldOptions;
65 },
66
67 //-------------------------------------------------------------------------
68
69 'type': function () {
70 return this.fieldOptions()['type'];
71 },
72
73 //-------------------------------------------------------------------------
74
75 'value': function() {
76 varresult;
77
78 result = this._value;
79
80 // if ((result == null) && (this.type() == 'checkbox')) {
81 // result = false;
82 // };
83
84 return result;
85 },
86
87 'setValue': function (aValue) {
88 this._value = aValue;
89 return this.directLogin().setValue('formValues' + '.' + this.key(), aValue);
90 },
91
92 //-------------------------------------------------------------------------
93/*
94 'serializedData': function() {
95 return this.value();
96 },
97*/
98 //-------------------------------------------------------------------------
99 __syntaxFix__: "syntax fix"
100});
101
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js
new file mode 100644
index 0000000..d9995fc
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js
@@ -0,0 +1,192 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28//#############################################################################
29
30Clipperz.PM.DataModel.DirectLoginInput = function(args) {
31 this._args = args;
32
33 return this;
34}
35
36Clipperz.PM.DataModel.DirectLoginInput.prototype = MochiKit.Base.update(null, {
37
38 'args': function() {
39 return this._args;
40 },
41
42 //-------------------------------------------------------------------------
43
44 'name': function() {
45 return this.args()['name'];
46 },
47
48 //-------------------------------------------------------------------------
49
50 'type': function() {
51 var result;
52
53 result = this.args()['type'];
54
55 if (result != null) {
56 result = result.toLowerCase();
57 }
58 return result;
59 },
60
61 //-------------------------------------------------------------------------
62
63 'options': function() {
64 return this.args()['options'];
65 },
66
67 //-------------------------------------------------------------------------
68
69 'value': function() {
70 return this.args()['value'];
71 },
72
73 //-------------------------------------------------------------------------
74 /*
75 'formConfiguration': function(someFormValues, someBindings, someFields) {
76 var result;
77
78 if (this.shouldSetValue()) {
79 switch (this.type()) {
80 case 'select':
81 var currentValue;
82 var options;
83
84 // currentValue = this.directLogin()._configuration['formValues'][this.name()];
85 currentValue = someFormValues[this.name()];
86 options = this.args()['options'];
87
88 result = MochiKit.DOM.SELECT({name:this.name()},
89 MochiKit.Base.map(function(anOption) {
90 var options;
91
92 options = {value:anOption['value']};
93 if (currentValue == anOption['value']) {
94 options.selected = true;
95 }
96
97 return MochiKit.DOM.OPTION(options, anOption['label'])
98 }, options)
99 )
100 break;
101 case 'checkbox':
102 var options;
103
104 options = {type:'checkbox', name: this.name()};
105 // if (this.directLogin()._configuration['formValues'][this.name()] == true) {
106 if (someFormValues[this.name()] == true) {
107 options['checked'] = true;
108 };
109
110 result = MochiKit.DOM.INPUT(options, null);
111 break;
112 case 'radio':
113 var currentName;
114 var currentValue;
115 var options;
116
117 currentName = this.name();
118 // currentValue = this.directLogin()._configuration['formValues'][this.name()];
119 currentValue = someFormValues[this.name()];
120 options = this.args()['options'];
121
122 result = MochiKit.DOM.DIV(null,
123 MochiKit.Base.map(function(anOption) {
124 var options;
125 var isChecked;
126 var inputNode;
127 var divNode;
128
129 options = {type:'radio', name:currentName, value:anOption['value']}
130 isChecked = (currentValue == anOption['value']);
131 if (isChecked) {
132 options.checked = true;
133 }
134
135 if (Clipperz_IEisBroken == true) {
136 var checkedValue;
137
138 checkedValue = (isChecked ? " CHECKED" : "");
139 inputNode = MochiKit.DOM.currentDocument().createElement("<INPUT TYPE='RADIO' NAME='" + currentName + "' VALUE='" + anOption['value'] + "'" + checkedValue + ">");
140 } else {
141 inputNode = MochiKit.DOM.INPUT(options, anOption['value']);
142 }
143 divNode = MochiKit.DOM.DIV(null, inputNode);
144
145 return divNode;
146 }, options)
147 );
148 break;
149 }
150 } else {
151 var binding;
152 // binding = this.directLogin().bindings()[this.name()];
153 binding = someBindings[this.name()];
154
155 result = MochiKit.DOM.INPUT({
156 type:((this.type() != 'password') ? this.type() : 'text'),
157 name:this.name(),
158 // value:((binding != null)? binding.field().value() : this.value())
159 value:((binding != null)? someFields[binding.fieldKey()]['value'] : this.value())
160 // value:((binding != null)? someFields[binding.fieldKey()].value() : this.value())
161 }, null);
162 }
163
164 return result;
165 },
166 */
167 //-------------------------------------------------------------------------
168
169 'needsFormValue': function() {
170 var type;
171 var result;
172
173 type = this.type();
174 result = ((type == 'checkbox') || (type == 'radio') || (type == 'select'));
175
176 return result;
177 },
178
179 'needsBinding': function() {
180 var type;
181 var result;
182
183 type = this.type();
184 result = ((type == 'text') || (type == 'password'));
185
186 return result;
187 },
188
189 //-------------------------------------------------------------------------
190 __syntaxFix__: "syntax fix"
191});
192
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js b/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js
new file mode 100644
index 0000000..1aa7a52
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js
@@ -0,0 +1,542 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.EncryptedRemoteObject depends on Clipperz.KeyValueObjectStore!";
26}
27
28if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
29if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
30
31Clipperz.PM.DataModel.EncryptedRemoteObject = function(args) {
32 args = args || {};
33
34 this._name = args.name || null;
35 this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
36 this._isBrandNew = ((args.reference == null) && (args.remoteData == null));
37
38 if ((this._isBrandNew == false) && (args['retrieveKeyFunction'] == null)) {
39 Clipperz.Base.exception.raise('MandatoryParameter');
40 } else {
41 this._retrieveKeyFunction = args['retrieveKeyFunction'];
42 }
43
44 this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction|| null;
45 this._remoteData = args.remoteData || null;
46 // this._remoteData = args.remoteData ? Clipperz.Base.deepClone(args.remoteData) : null;
47 if ((!this._isBrandNew) && ((this._retrieveRemoteDataFunction == null) && (this._remoteData == null))) {
48 Clipperz.Base.exception.raise('MandatoryParameter');
49 }
50
51
52 this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter');
53 this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version';//Clipperz.Base.exception.raise('MandatoryParameter');
54
55
56 this._transientState = null;
57 this._deferredLocks = {};
58
59 if (this._isBrandNew == true) {
60 this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [1]'}*/);
61 } else {
62 this._objectDataStore = null;
63 }
64
65 return this;
66}
67
68//
69 // Basic data workflow
70 //=======================
71//
72 //getRemoteData
73 // unpackRemoteData
74 // getDecryptData [encryptedDataKeypath, encryptedVersionKeypath]
75 // unpackData
76 //
77 //
78 // ?? packData
79 // ?? encryptDataWithKey
80 // ??packRemoteData [encryptedDataKeypath (?), encryptedVersionKeypath (?)]
81//
82
83Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(null, {
84
85 'toString': function () {
86 return "Clipperz.PM.DataModel.EncryptedRemoteObject" + (this.name() != null ? " - " + this.name() : "");
87 },
88
89 //-------------------------------------------------------------------------
90
91 'name': function () {
92 return this._name;
93 },
94
95 //-------------------------------------------------------------------------
96
97 'reference': function () {
98 return this._reference;
99 },
100
101 'setReference': function (aValue) {
102 this._reference = aValue;
103
104 return this._reference;
105 },
106
107 //-------------------------------------------------------------------------
108
109 'transientState': function () {
110 if (this._transientState == null) {
111 this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.transientState [2]'}*/);
112 }
113
114 return this._transientState;
115 },
116
117 'resetTransientState': function (isCommitting) {
118 if (this._transientState != null) {
119 this._transientState.removeAllData();
120 }
121
122 this._transientState = null;
123 },
124
125 //-------------------------------------------------------------------------
126
127 'isBrandNew': function () {
128 return this._isBrandNew;
129 },
130
131 //-------------------------------------------------------------------------
132
133 'getKey': function () {
134 var deferredResult;
135 var deferredLock;
136
137 deferredLock = this.getDeferredLockForKey('key');
138
139 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getKey", {trace:false});
140 deferredResult.acquireLock(deferredLock);
141 deferredResult.addMethod(
142 this.decryptedDataStore(),
143 'deferredGetOrSet',
144 'decryptionKey',
145 MochiKit.Base.partial(this.retrieveKeyFunction(), this.reference())
146 );
147 deferredResult.releaseLock(deferredLock);
148 deferredResult.callback();
149
150 return deferredResult;
151 },
152
153 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
154
155 'retrieveKeyFunction': function () {
156 return this._retrieveKeyFunction;
157 },
158
159 'setRetrieveKeyFunction': function (aFunction) {
160 this._retrieveKeyFunction = aFunction;
161 },
162
163 //-------------------------------------------------------------------------
164
165 'hasLoadedRemoteData': function () {
166 return (this._remoteData != null);
167 },
168
169 'getRemoteData': function () {
170 var deferredResult;
171 vardeferredLock;
172
173 deferredLock = this.getDeferredLockForKey('remoteData');
174
175 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObjects.getRemoteData", {trace:false});
176 deferredResult.acquireLock(deferredLock);
177 deferredResult.addCallback(MochiKit.Base.bind(function () {
178 var innerDeferredResult;
179
180 if (this._remoteData != null) {
181 innerDeferredResult = MochiKit.Async.succeed(this._remoteData);
182 } else {
183 innerDeferredResult = Clipperz.Async.callbacks("EncryptedRemoteObjects.getRemoteData <inner deferred>", [
184 MochiKit.Base.partial(this.retrieveRemoteDataFunction(), this.reference()),
185 MochiKit.Base.method(this, 'unpackRemoteData'),
186 MochiKit.Base.bind(function (someData) {
187 this._remoteData = someData;
188 return this._remoteData;
189 }, this)
190 ], {trace:false});
191 }
192
193 return innerDeferredResult;
194 }, this))
195 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
196 deferredResult.releaseLock(deferredLock);
197
198 deferredResult.callback();
199
200 return deferredResult;
201 },
202
203 //-------------------------------------------------------------------------
204
205 'unpackRemoteData': function (someData) {
206 return MochiKit.Async.succeed(someData);
207 },
208
209 //.........................................................................
210
211 'packRemoteData': function (someData) {
212 var result;
213
214 result = {
215 'reference':this.reference(),
216 'data': someData,
217 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion
218 };
219
220 return MochiKit.Async.succeed(result);
221 },
222
223 //-------------------------------------------------------------------------
224
225 'retrieveRemoteDataFunction': function () {
226 return this._retrieveRemoteDataFunction;
227 },
228
229 'setRetrieveRemoteDataFunction': function (aFunction) {
230 this._retrieveRemoteDataFunction = aFunction;
231 },
232
233 //-------------------------------------------------------------------------
234
235 'decryptedDataStore': function () {
236 if (this._decryptedDataStore == null) {
237 this._decryptedDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.decryptedDataStore [3]'}*/);
238 };
239
240 return this._decryptedDataStore;
241 },
242
243 //.........................................................................
244
245 'getDecryptedData': function () {
246 var deferredResult;
247 var deferredLock;
248
249 deferredLock = this.getDeferredLockForKey('decryptedData');
250
251 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData", {trace:false});
252 deferredResult.acquireLock(deferredLock);
253 deferredResult.addMethod(this, 'decryptedDataStore');
254 deferredResult.addCallback(MochiKit.Base.methodcaller('deferredGetOrSet', 'decryptedData', MochiKit.Base.bind(function () {
255 varinnerDeferredResult;
256
257 innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData <inner deferred>", {trace:false});
258
259 innerDeferredResult.addMethod(this, 'getRemoteData');
260 innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
261 innerDeferredResult.collectResults({
262 'key': MochiKit.Base.method(this, 'getKey'),
263 'value':MochiKit.Base.itemgetter(this._encryptedDataKeypath),
264 'version':MochiKit.Base.itemgetter(this._encryptedVersionKeypath)
265 });
266
267 innerDeferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt);
268 innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
269 innerDeferredResult.addMethod(this, 'unpackData');
270 innerDeferredResult.callback();
271
272 return innerDeferredResult;
273 }, this)));
274 deferredResult.releaseLock(deferredLock);
275 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
276 deferredResult.callback();
277
278 return deferredResult;
279 },
280
281 //-------------------------------------------------------------------------
282
283 'setValue': function(aKey, aValue) {
284 var deferredResult;
285
286 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.setValue", {trace:false});
287 deferredResult.addMethod(this, '_getObjectDataStore');
288 deferredResult.addCallback(MochiKit.Base.methodcaller('setValue', aKey, aValue));
289 deferredResult.callback();
290
291 return deferredResult;
292 },
293
294 //.........................................................................
295
296 'getValue': function (aKey) {
297 return Clipperz.Async.callbacks("EncryptedRemoteObject.getValue", [
298 MochiKit.Base.method(this, '_getObjectDataStore'),
299 MochiKit.Base.methodcaller('getValue', aKey)
300 ], {trace:false});
301 },
302
303 //.........................................................................
304
305 'removeValue': function (aKey) {
306 return Clipperz.Async.callbacks("EncryptedRemoteObject.removeValue", [
307 MochiKit.Base.method(this, '_getObjectDataStore'),
308 MochiKit.Base.methodcaller('removeValue', aKey)
309 ], {trace:false});
310 },
311
312 //.........................................................................
313
314 'values': function () {
315 return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [
316 MochiKit.Base.method(this, '_getObjectDataStore'),
317 MochiKit.Base.methodcaller('values')
318 ], {trace:false});
319 },
320
321 'setValues': function (someValues) {
322 return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [
323 MochiKit.Base.method(this, '_getObjectDataStore'),
324 MochiKit.Base.methodcaller('setValues', someValues)
325 ], {trace:false});
326 },
327
328 //.........................................................................
329
330 '_getObjectDataStore': function () {
331 var deferredResult;
332 var deferredLock;
333
334 deferredLock = this.getDeferredLockForKey('objectDataStore');
335
336 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore", {trace:false});
337 deferredResult.acquireLock(deferredLock);
338 deferredResult.addCallback(MochiKit.Base.bind(function () {
339 var innerDeferredResult;
340
341 if (this._objectDataStore == null) {
342 this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [4]'}*/);
343
344 innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore <inner deferred>", {trace:false});
345 innerDeferredResult.addMethod(this, 'getDecryptedData');
346 innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues');
347 innerDeferredResult.callback();
348 } else {
349 innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore);
350 }
351
352 return innerDeferredResult;
353 }, this));
354 deferredResult.releaseLock(deferredLock);
355 deferredResult.callback();
356
357 return deferredResult;
358 },
359
360 'hasInitiatedObjectDataStore': function () {
361 return (this._objectDataStore != null);
362 },
363
364 //-------------------------------------------------------------------------
365
366 'getDeferredLockForKey': function (aKey) {
367 var result;
368
369 result = this._deferredLocks[aKey];
370
371 if (typeof(result) == 'undefined') {
372 result = new MochiKit.Async.DeferredLock();
373 this._deferredLocks[aKey] = result;
374 }
375
376 return result;
377 },
378
379 //-------------------------------------------------------------------------
380
381 'unpackData': function (someData) { //++
382 return someData;
383 },
384
385 'packData': function (someData) { //++
386 return someData;
387 },
388
389 //-------------------------------------------------------------------------
390
391 'hasPendingChanges': function () {
392 var deferredResult;
393 var tempObj = this;
394
395 if (this.isBrandNew()) {
396 // deferredResult = MochiKit.Async.succeed(true);
397 deferredResult = this.hasPendingChangesWhenBrandNew();
398 } else if (this.hasInitiatedObjectDataStore()) {
399 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.hasPendingChanges", {trace:false});
400 deferredResult.collectResults({
401 'decryptedData': [
402 MochiKit.Base.method(this, 'getDecryptedData'),
403 Clipperz.Base.serializeJSON
404 ],
405 'objectData': [
406 MochiKit.Base.method(this, '_getObjectDataStore'),
407 MochiKit.Base.methodcaller('values'),
408 Clipperz.Base.serializeJSON
409 ]
410 });
411 deferredResult.addCallback(function (someValues) {
412 return (someValues['decryptedData'] != someValues['objectData']);
413 });
414 deferredResult.callback();
415 } else {
416 deferredResult = MochiKit.Async.succeed(false);
417 }
418
419 return deferredResult;
420 },
421
422 'hasPendingChangesWhenBrandNew': function () {
423 return MochiKit.Async.succeed(true);
424 },
425
426 //-------------------------------------------------------------------------
427
428 'commitTransientState': function () {
429 var deferredResult;
430
431 // if (this.transientState().getValue('__prepareRemoteData') == true) {
432 if (this.transientState().getValue('packedRemoteData') != null) {
433 deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [
434 MochiKit.Base.bind(function (someData) {
435 this._remoteData = this.transientState().getValue('packedRemoteData');
436 }, this),
437
438 MochiKit.Base.method(this, '_getObjectDataStore'),
439 MochiKit.Base.methodcaller('values'),
440 Clipperz.Base.deepClone,
441 MochiKit.Base.method(this.decryptedDataStore(), 'setValue', 'decryptedData'),
442
443 MochiKit.Base.method(this, 'resetTransientState', true)
444 ], {trace:false});
445
446 } else {
447 deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - NO prepareRemoteData", [
448 MochiKit.Base.method(this, 'resetTransientState', true)
449 ], {trace:false});
450 }
451
452 this._isBrandNew = false;
453
454 return deferredResult;
455 },
456
457 //-------------------------------------------------------------------------
458
459 'revertChanges': function () {
460 if (this.hasInitiatedObjectDataStore()) {
461 this._objectDataStore.removeAllData();
462 this._objectDataStore = null;
463 }
464 this.resetTransientState(false);
465
466 return MochiKit.Async.succeed();
467 },
468
469 //-------------------------------------------------------------------------
470
471 'deleteAllCleanTextData': function () {
472 var deferredResult;
473
474 deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.deleteAllCleanTextData", {trace:false});
475
476 deferredResult.addMethod(this, 'resetTransientState', false);
477
478 deferredResult.acquireLock(this.getDeferredLockForKey('decryptedData'));
479 deferredResult.addCallback(MochiKit.Base.bind(function () {
480 if (this._decryptedDataStore != null) {
481 this._decryptedDataStore.removeAllData();
482 }
483 }, this));
484 deferredResult.releaseLock(this.getDeferredLockForKey('decryptedData'));
485
486 deferredResult.acquireLock(this.getDeferredLockForKey('objectDataStore'));
487 deferredResult.addCallback(MochiKit.Base.bind(function () {
488 if (this._objectDataStore != null) {
489 this._objectDataStore.removeAllData();
490 this._objectDataStore = null;
491 }
492 }, this));
493 deferredResult.releaseLock(this.getDeferredLockForKey('objectDataStore'));
494
495 deferredResult.callback();
496
497 return deferredResult;
498 },
499
500 //.........................................................................
501
502 'hasAnyCleanTextData': function () {
503 var result;
504
505 result = false;
506
507 result = result || (! this.decryptedDataStore().isEmpty());
508 result = result || (! this.transientState().isEmpty());
509 if (this.hasInitiatedObjectDataStore()) {
510 result = result || (! this._objectDataStore.isEmpty());
511 }
512
513 return MochiKit.Async.succeed(result);
514 },
515
516 //-------------------------------------------------------------------------
517
518 'prepareRemoteDataWithKey': function (aKey) {
519 return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [
520 // MochiKit.Base.method(this.transientState(), 'setValue', '__prepareRemoteData', true),
521 MochiKit.Base.method(this, '_getObjectDataStore'),
522 MochiKit.Base.methodcaller('values'),
523 MochiKit.Base.method(this, 'packData'),
524 function (someData) {
525 return Clipperz.PM.Crypto.deferredEncrypt({
526 'key': aKey,
527 'value':someData,
528 'version':Clipperz.PM.Crypto.encryptingFunctions.currentVersion
529 })
530 },
531 MochiKit.Base.method(this, 'packRemoteData'),
532 MochiKit.Base.method(this.transientState(), 'setValue', 'packedRemoteData'),
533 function (someData) {
534 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'advanceProgress');
535 return someData;
536 }
537 ], {trace:false});
538 },
539
540 //-------------------------------------------------------------------------
541 __syntaxFix__: "syntax fix"
542});
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js b/frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js
new file mode 100644
index 0000000..fbca1ff
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js
@@ -0,0 +1,350 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28
29//#############################################################################
30
31Clipperz.PM.DataModel.OneTimePassword = function(args) {
32 args = args || {};
33
34 //this._user = args['user'];
35 this._reference = args['reference']|| Clipperz.PM.Crypto.randomKey();
36 this._password = args['password'];
37 this._passwordValue = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(args['password']);
38 this._creationDate = args['created'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['created']) : new Date();
39 this._usageDate = args['used'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['used']) : null;
40
41 this._status = args['status'] || 'ACTIVE'; //'REQUESTED', 'USED', 'DISABLED'
42 this._connectionInfo= null;
43
44 this._key = null;
45 this._keyChecksum= null;
46
47 return this;
48}
49
50Clipperz.PM.DataModel.OneTimePassword.prototype = MochiKit.Base.update(null, {
51
52 'toString': function() {
53 return "Clipperz.PM.DataModel.OneTimePassword";
54 },
55/*
56 //-------------------------------------------------------------------------
57
58 'user': function() {
59 return this._user;
60 },
61
62 //-------------------------------------------------------------------------
63
64 'password': function() {
65 return this._password;
66 },
67
68 //-------------------------------------------------------------------------
69
70 'passwordValue': function() {
71 return this._passwordValue;
72 },
73
74 //-------------------------------------------------------------------------
75
76 'creationDate': function() {
77 return this._creationDate;
78 },
79
80 //-------------------------------------------------------------------------
81
82 'reference': function() {
83 return this._reference;
84 },
85
86 //-------------------------------------------------------------------------
87
88 'key': function() {
89 if (this._key == null) {
90 this._key = Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(this.user().username(), this.passwordValue());
91 }
92
93 return this._key;
94 },
95
96 //-------------------------------------------------------------------------
97
98 'keyChecksum': function() {
99 if (this._keyChecksum == null) {
100 this._keyChecksum = Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(this.user().username(), this.passwordValue());
101 }
102
103 return this._keyChecksum;
104 },
105*/
106 //-------------------------------------------------------------------------
107
108 'status': function() {
109 return this._status;
110 },
111
112 'setStatus': function(aValue) {
113 this._status = aValue;
114 },
115
116 //-------------------------------------------------------------------------
117/*
118 'serializedData': function() {
119 var result;
120
121 result = {
122 'password': this.password(),
123 'created': this.creationDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.creationDate()) : null,
124 'used': this.usageDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.usageDate()) : null,
125 'status': this.status()
126 };
127
128 return result;
129 },
130
131 //-------------------------------------------------------------------------
132
133 'packedPassphrase': function() {
134 var result;
135 var packedPassphrase;
136 var encodedPassphrase;
137 varprefixPadding;
138 var suffixPadding;
139 var getRandomBytes;
140
141 getRandomBytes = MochiKit.Base.method(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'getRandomBytes');
142
143 encodedPassphrase = new Clipperz.ByteArray(this.user().passphrase()).toBase64String();
144//Clipperz.logDebug("--- encodedPassphrase.length: " + encodedPassphrase.length);
145 prefixPadding = getRandomBytes(getRandomBytes(1).byteAtIndex(0)).toBase64String();
146//Clipperz.logDebug("--- prefixPadding.length: " + prefixPadding.length);
147 suffixPadding = getRandomBytes((500 - prefixPadding.length - encodedPassphrase.length) * 6 / 8).toBase64String();
148//Clipperz.logDebug("--- suffixPadding.length: " + suffixPadding.length);
149//Clipperz.logDebug("--- total.length: " + (prefixPadding.length + encodedPassphrase.length + suffixPadding.length));
150
151 packedPassphrase = {
152 'prefix': prefixPadding,
153 'passphrase': encodedPassphrase,
154 'suffix': suffixPadding
155 };
156
157 // result = Clipperz.Base.serializeJSON(packedPassphrase);
158 result = packedPassphrase;
159//Clipperz.logDebug("===== OTP packedPassprase: [" + result.length + "]" + result);
160//Clipperz.logDebug("<<< OneTimePassword.packedPassphrase");
161
162 return result;
163 },
164
165 //-------------------------------------------------------------------------
166
167 'encryptedPackedPassphrase': function() {
168 return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(this.passwordValue(), this.packedPassphrase())
169 },
170
171 //-------------------------------------------------------------------------
172
173 'encryptedData': function() {
174 var deferredResult;
175 varresult;
176
177//Clipperz.logDebug(">>> OneTimePassword.encryptedData");
178//Clipperz.logDebug("--- OneTimePassword.encryptedData - id: " + this.reference());
179 result = {
180 'reference': this.reference(),
181 'key': this.key(),
182 'keyChecksum': this.keyChecksum(),
183 'data': "",
184 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion
185 }
186//Clipperz.logDebug("--- OneTimePassword.encryptedData - 2: " + Clipperz.Base.serializeJSON(result));
187 deferredResult = new MochiKit.Async.Deferred();
188//Clipperz.logDebug("--- OneTimePassword.encryptedData - 3");
189//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 1: " + res); return res;});
190 //# deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.passwordValue(), this.packedPassphrase());
191 deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedPackedPassphrase'));
192//Clipperz.logDebug("--- OneTimePassword.encryptedData - 4");
193//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 2: [" + res.length + "]" + res); return res;});
194 deferredResult.addCallback(function(aResult, res) {
195 aResult['data'] = res;
196 return aResult;
197 }, result);
198//Clipperz.logDebug("--- OneTimePassword.encryptedData - 5");
199//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 3: " + Clipperz.Base.serializeJSON(res)); return res;});
200 deferredResult.callback();
201//Clipperz.logDebug("--- OneTimePassword.encryptedData - 6");
202
203 return deferredResult;
204 },
205
206 //-------------------------------------------------------------------------
207
208 'saveChanges': function() {
209 var deferredResult;
210 varresult;
211
212//Clipperz.logDebug(">>> OneTimePassword.saveChanges");
213 result = {};
214 deferredResult = new MochiKit.Async.Deferred();
215
216 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptUserData');
217 deferredResult.addCallback(MochiKit.Base.method(this.user(), 'encryptedData'));
218 deferredResult.addCallback(function(aResult, res) {
219 aResult['user'] = res;
220 return aResult;
221 }, result);
222
223 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptOTPData');
224 deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData'));
225 deferredResult.addCallback(function(aResult, res) {
226 aResult['oneTimePassword'] = res;
227 return aResult;
228 }, result);
229
230 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_sendingData');
231//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 1: " + Clipperz.Base.serializeJSON(res)); return res;});
232 deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'addNewOneTimePassword');
233
234 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_updatingInterface');
235//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;});
236 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'OTPUpdated');
237 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'oneTimePassword_saveChanges_done', null);
238//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;});
239 deferredResult.callback();
240//Clipperz.logDebug("<<< OneTimePassword.saveChanges");
241
242 return deferredResult;
243 },
244
245 //-------------------------------------------------------------------------
246
247 'usageDate': function() {
248 return this._usageDate;
249 },
250
251 'setUsageDate': function(aValue) {
252 this._usageDate = aValue;
253 },
254
255 //-------------------------------------------------------------------------
256
257 'connectionInfo': function() {
258 return this._connectionInfo;
259 },
260
261 'setConnectionInfo': function(aValue) {
262 this._connectionInfo = aValue;
263 },
264
265 //-------------------------------------------------------------------------
266
267 'isExpired': function() {
268 return (this.usageDate() != null);
269 },
270
271 //-------------------------------------------------------------------------
272
273 'updateStatusWithValues': function(someValues) {
274 var result;
275
276 result = false;
277
278 if (someValues['status'] != this.status()) {
279 result = true;
280 }
281
282 this.setStatus(someValues['status']);
283 this.setUsageDate(Clipperz.PM.Date.parseDateWithUTCFormat(someValues['requestDate']));
284 this.setConnectionInfo(someValues['connection']);
285
286 return result;
287 },
288 */
289 //-------------------------------------------------------------------------
290 __syntaxFix__: "syntax fix"
291});
292
293//#############################################################################
294
295Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword = function(anUsername, aPassword) {
296 return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aPassword)).toHexString().substring(2);
297}
298
299Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword = function(anUsername, aPassword) {
300 return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(anUsername + aPassword)).toHexString().substring(2);
301}
302
303//=============================================================================
304
305Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue = function(aPassword) {
306 var result;
307
308 //"yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg"
309 if (aPassword.replace(/[\s\-]/g, '').length == 32) {
310 try {
311 var passwordByteArray;
312
313 passwordByteArray = new Clipperz.ByteArray();
314 passwordByteArray.appendBase32String(aPassword);
315
316 result = true;
317 } catch(exception) {
318 result = false;
319 }
320 } else {
321 result = false;
322 }
323
324 return result;
325}
326
327//=============================================================================
328
329Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword = function(aPassword) {
330 varresult;
331
332 if (aPassword.replace(/[\s\-]/g, '').length == 32) {
333 try {
334 var passwordByteArray;
335
336 passwordByteArray = new Clipperz.ByteArray();
337 passwordByteArray.appendBase32String(aPassword);
338
339 result = passwordByteArray.toBase64String();
340 } catch(exception) {
341 result = aPassword;
342 }
343 } else {
344 result = aPassword;
345 }
346
347 return result;
348}
349
350//#############################################################################
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js
new file mode 100644
index 0000000..01e7196
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js
@@ -0,0 +1,186 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.Record.Version) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.Record.Version.Field depends on Clipperz.PM.DataModel.Record.Version!";
26}
27
28Clipperz.PM.DataModel.Record.Version.Field = function(args) {
29 Clipperz.PM.DataModel.Record.Version.Field.superclass.constructor.apply(this, arguments);
30
31 this._recordVersion = args.recordVersion|| Clipperz.Base.exception.raise('MandatoryParameter');
32 this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
33
34 return this;
35}
36
37
38Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version.Field, Object, {
39
40 'toString': function() {
41 return "Record.Version.Field (" + this.reference() + ")";
42 },
43
44 //-------------------------------------------------------------------------
45
46 'recordVersion': function () {
47 return this._recordVersion;
48 },
49
50 //-------------------------------------------------------------------------
51
52 'reference': function () {
53 return this._reference;
54 },
55
56 //-------------------------------------------------------------------------
57
58 'getItem': function (aKey) {
59 return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [
60 MochiKit.Base.method(this, 'recordVersion'),
61 MochiKit.Base.methodcaller('getValue', 'fields' + '.' + this.reference() + '.' + aKey)
62 ], {trace:false});
63 },
64
65 'setItem': function (aKey, aValue) {
66 return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [
67 MochiKit.Base.method(this, 'recordVersion'),
68 MochiKit.Base.methodcaller('setValue', 'fields' + '.' + this.reference() + '.' + aKey, aValue)
69 ], {trace:false});
70 },
71
72 //-------------------------------------------------------------------------
73
74 'label': function () {
75 return this.getItem('label');
76 },
77
78 'setLabel': function (aValue) {
79 return this.setItem('label', aValue);
80 },
81
82 //-------------------------------------------------------------------------
83
84 'value': function () {
85 return this.getItem('value');
86 },
87
88 'setValue': function (aValue) {
89 return this.setItem('value', aValue);
90 },
91
92 //-------------------------------------------------------------------------
93
94 'actionType': function () {
95 return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.actionType", [
96 Clipperz.Async.collectResults("Clipperz.PM.DataModel.Record.Version.Field.actionType [collect results]", {
97 'isHidden':MochiKit.Base.method(this, 'isHidden'),
98 'value':MochiKit.Base.method(this, 'value')
99 }, {trace:false}),
100 function (someValues) {
101 var result; //'NONE', 'URL', 'EMAIL', 'PASSWORD'
102
103 result = 'NONE';
104
105 if (someValues['isHidden']) {
106 result = 'PASSWORD';
107 } else if (Clipperz.Base.isUrl(someValues['value'])) {
108 result = 'URL'
109 } else if (Clipperz.Base.isEmail(someValues['value'])) {
110 result = 'EMAIL'
111 };
112
113 return result;
114 }
115 ], {trace:false});
116 },
117
118 //-------------------------------------------------------------------------
119
120 'isHidden': function () {
121 return this.getItem('hidden');
122 },
123
124 'setIsHidden': function (aValue) {
125 return this.setItem('hidden', aValue);
126 },
127
128 //-------------------------------------------------------------------------
129
130 'isEmpty': function () {
131 var deferredResult;
132
133 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.Field.isEmpty", {trace:false});
134
135 deferredResult.collectResults({
136 'label': [
137 MochiKit.Base.method(this, 'label'),
138 MochiKit.Base.partial(MochiKit.Base.operator.eq, '')
139 ],
140 'value': [
141 MochiKit.Base.method(this, 'value'),
142 MochiKit.Base.partial(MochiKit.Base.operator.eq, '')
143 ],
144 'isHidden': [
145 MochiKit.Base.method(this, 'isHidden'),
146 MochiKit.Base.partial(MochiKit.Base.operator.eq, false)
147 ]
148 });
149 deferredResult.addCallback(MochiKit.Base.values);
150 deferredResult.addCallback(function(someValues) {
151 return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity);
152 });
153 deferredResult.callback();
154
155 return deferredResult;
156 },
157
158 //-------------------------------------------------------------------------
159
160 'content': function () {
161 var deferredResult;
162 varfieldValues;
163
164 fieldValues = {};
165 deferredResult = new Clipperz.Async.Deferred("Record.Version.Field.content", {trace:false});
166 deferredResult.addMethod(this, 'reference');
167 deferredResult.addCallback(function (aValue) { fieldValues['reference'] = aValue; });
168 deferredResult.addMethod(this, 'label');
169 deferredResult.addCallback(function (aValue) { fieldValues['label'] = aValue; });
170 deferredResult.addMethod(this, 'value');
171 deferredResult.addCallback(function (aValue) { fieldValues['value'] = aValue; });
172 deferredResult.addMethod(this, 'actionType');
173 deferredResult.addCallback(function (aValue) { fieldValues['actionType'] = aValue; });
174 deferredResult.addMethod(this, 'isHidden');
175 deferredResult.addCallback(function (aValue) { fieldValues['isHidden'] = aValue; });
176 deferredResult.addCallback(function () { return fieldValues; });
177 deferredResult.callback();
178
179 return deferredResult;
180 },
181
182 //-------------------------------------------------------------------------
183 __syntaxFix__: "syntax fix"
184});
185
186
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js
new file mode 100644
index 0000000..87b319c
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js
@@ -0,0 +1,328 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.Record) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.Record.Version depends on Clipperz.PM.DataModel.Record!";
26}
27
28Clipperz.PM.DataModel.Record.Version = function(args) {
29 Clipperz.PM.DataModel.Record.Version.superclass.constructor.apply(this, arguments);
30
31 this._getVersionFunction = args.getVersion|| Clipperz.Base.exception.raise('MandatoryParameter');
32 this._fields = null;
33
34 return this;
35}
36
37
38Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version, Clipperz.PM.DataModel.EncryptedRemoteObject, {
39
40 'toString': function() {
41 return "Record.Version (" + this.reference() + ")";
42 },
43
44 //-------------------------------------------------------------------------
45
46 'reference': function () {
47 return this._reference;
48 },
49
50 //-------------------------------------------------------------------------
51/*
52 'hasPendingChanges': function () {
53 var deferredResult;
54
55 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChanges", {trace:false});
56 deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.hasPendingChanges, this));
57 deferredResult.callback();
58
59 return deferredResult;
60 },
61*/
62 //-------------------------------------------------------------------------
63
64
65 'hasPendingChangesWhenBrandNew': function () {
66 var deferredResult;
67
68 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChangesWhenBrandNew", {trace:false});
69 deferredResult.addMethod(this, 'fields');
70 deferredResult.addCallback(MochiKit.Base.values);
71 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('isEmpty'))
72 deferredResult.addCallback(Clipperz.Async.collectAll);
73 deferredResult.addCallback(function(someValues) {
74 return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity);
75 });
76 deferredResult.addCallback(MochiKit.Base.operator.lognot)
77 deferredResult.callback();
78
79 return deferredResult;
80 },
81
82 //=========================================================================
83
84 'commitTransientState': function () {
85 var deferredResult;
86
87 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.commitTransientState", {trace:false});
88 deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.commitTransientState, this));
89 deferredResult.callback();
90
91 return deferredResult;
92 },
93
94 //=========================================================================
95
96 'unpackData': function (someData) { //++
97 varresult;
98
99 result = someData;
100 if ((someData['fields'] != null) && (someData['fields'] instanceof Array)) {
101 varfields;
102 var i,c;
103
104 fields = someData['fields'];
105 delete someData['fields'];
106
107 someData['fields'] = {};
108 c = fields.length;
109 for (i=0; i<c; i++) {
110 someData['fields'][i] = fields[i];
111 }
112 }
113
114
115
116 return result;
117 },
118
119 //=========================================================================
120
121 'fields': function () {
122 vardeferredResult;
123 var deferredLock;
124
125 deferredLock = this.getDeferredLockForKey('fields');
126
127 deferredResult = new Clipperz.Async.Deferred("Record.Version.fields", {trace:false});
128 deferredResult.acquireLock(deferredLock);
129 deferredResult.addCallback(MochiKit.Base.bind(function () {
130 var innerDeferredResult;
131
132 if (this._fields == null) {
133 innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false});
134 innerDeferredResult.addMethod(this, 'getValue', 'fields');
135 innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) {
136 var reference;
137
138 this._fields = {};
139
140 for (reference in someObjectData) {
141 varrecordVersionField;
142
143 recordVersionField = new Clipperz.PM.DataModel.Record.Version.Field({
144 'recordVersion':this,
145 'reference': reference
146 });
147
148 this._fields[reference] = recordVersionField;
149 }
150
151 return this._fields;
152 }, this));
153 innerDeferredResult.callback();
154 } else {
155 innerDeferredResult = MochiKit.Async.succeed(this._fields);
156 }
157
158 return innerDeferredResult;
159 }, this));
160 deferredResult.releaseLock(deferredLock);
161 deferredResult.callback();
162
163 return deferredResult;
164 },
165
166 //-------------------------------------------------------------------------
167
168 'getFieldsValues': function () {
169 return this.getValue('fields');
170 },
171
172 //-------------------------------------------------------------------------
173
174 'addField': function (someParameters) {
175 varnewField;
176
177 newField = new Clipperz.PM.DataModel.Record.Version.Field({recordVersion:this});
178
179 return Clipperz.Async.callbacks("Record.Version.addField", [
180 MochiKit.Base.method(this, 'fields'),
181
182 MochiKit.Base.method(this, '_getObjectDataStore'),
183 MochiKit.Base.methodcaller('values'),
184 Clipperz.Base.serializeJSON,
185
186 MochiKit.Base.bind(function () { this._fields[newField.reference()] = newField; }, this),
187 MochiKit.Base.method(newField, 'setLabel', someParameters['label']),
188 MochiKit.Base.method(newField, 'setValue', someParameters['value']),
189 MochiKit.Base.method(newField, 'setIsHidden',someParameters['isHidden']),
190
191 MochiKit.Base.method(this, '_getObjectDataStore'),
192 MochiKit.Base.methodcaller('values'),
193 Clipperz.Base.serializeJSON,
194
195 MochiKit.Base.partial(MochiKit.Async.succeed, newField)
196 ], {trace:false});
197 },
198
199 //-------------------------------------------------------------------------
200
201 'removeField': function (aField) {
202 return Clipperz.Async.callbacks("Record.Version.removeField", [
203 MochiKit.Base.method(this, 'fields'),
204 MochiKit.Base.bind(function () { delete this._fields[aField.reference()]; }, this),
205 MochiKit.Base.method(this, 'removeValue', 'fields' + '.' + aField.reference())
206 ], {trace:false});
207 },
208
209 //-------------------------------------------------------------------------
210/*
211 'sortFieldReference': function (someSortedFieldReferences) {
212
213
214
215 },
216*/
217 //=========================================================================
218/*
219 'directLogins': function () {
220 return MochiKit.Base.values(this._directLogins);
221 },
222
223 'addDirectLogin': function (aDirectLogin) {
224 this._directLogins[aDirectLogin.reference()] = aDirectLogin;
225 },
226*/
227
228 //=========================================================================
229/*
230 'updateValues': function (anotherVersion) {
231 return Clipperz.Async.callbacks("Record.Version.updateValue", [
232 MochiKit.Base.partial(MochiKit.Async.succeed, this)
233 ], {trace:false});
234 },
235*/
236 //=========================================================================
237
238 'setRemoteData': function (aValue) {
239 this._remoteData = aValue;
240
241 return aValue;
242 },
243
244 //=========================================================================
245
246 'getVersionFunction': function () {
247 return this._getVersionFunction;
248 },
249
250 'previousVersion': function () {
251 return Clipperz.Async.callbacks("Record.Versions.previousVersion", [
252 MochiKit.Base.method(this, 'previousVersionReference'),
253 this.getVersionFunction()
254 ], {trace:false});
255 },
256
257 'previousVersionReference': function () {
258 return this.getValue('previousVersionReference');
259 },
260
261 'previousVersionKey': function () {
262 //TODO: this value i encrypted on its own. So it can not be saved in the main objectStore!!!
263 return this.getValue('previousVersionKey');
264 },
265
266 //-------------------------------------------------------------------------
267
268 'setPreviousVersionReferenceAndKey': function (aVersionObjectAndKey) {
269 // this._previousVersion = anotherVersion;
270 return Clipperz.Async.callbacks("Record.Version.setPreviousVersion", [
271 MochiKit.Base.method(this, 'setValue', 'previousVersionReference',aVersionObjectAndKey['reference']),
272 MochiKit.Base.method(this, 'setValue', 'previousVersionKey', aVersionObjectAndKey['key'])
273 ], {trace:false});
274 },
275
276 //=========================================================================
277
278 'revertChanges': function () {
279 this.setReference(this.transientState()['originalReference']);
280 Clipperz.PM.DataModel.Record.Version.superclass.revertChanges.apply(this, arguments);
281 },
282
283 //-------------------------------------------------------------------------
284
285 'prepareRemoteDataWithKey': function (aKey) {
286 var deferredResult;
287 var result;
288
289 result = {};
290
291 deferredResult = new Clipperz.Async.Deferred("Record.Version.prepareRemoteDataWithKey", {trace:false});
292 if (this.isBrandNew() == false) {
293 this.transientState()['originalReference'] = this.reference();
294
295 deferredResult.collectResults({
296 'key':MochiKit.Base.partial(MochiKit.Async.succeed, aKey),
297 'value': MochiKit.Base.method(this, 'getKey'),
298 'version': MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Crypto.encryptingFunctions.currentVersion)
299 });
300 deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncrypt);
301 deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey');
302 } else {
303 deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey', Clipperz.PM.Crypto.nullValue);
304 }
305 deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey));
306 deferredResult.addCallback(MochiKit.Base.update, result);
307 deferredResult.addMethod(this, 'setRemoteData');
308
309 deferredResult.callback();
310
311 return deferredResult;
312 },
313
314 //=========================================================================
315/*
316 'deleteAllCleanTextData': function () {
317 return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments);
318 },
319
320 'hasAnyCleanTextData': function () {
321 return Clipperz.PM.DataModel.Record.Version.superclass.hasAnyCleanTextData.apply(this, arguments);
322 },
323*/
324 //=========================================================================
325 __syntaxFix__: "syntax fix"
326});
327
328
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.js
new file mode 100644
index 0000000..379872a
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.js
@@ -0,0 +1,891 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28
29Clipperz.PM.DataModel.Record = function(args) {
30 Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments);
31
32 this._updateDate = (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter'));
33
34 this._retrieveIndexDataFunction = args.retrieveIndexDataFunction|| Clipperz.Base.exception.raise('MandatoryParameter');
35 this._updateIndexDataFunction = args.updateIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter');
36
37 this._retrieveDirectLoginIndexDataFunction = args.retrieveDirectLoginIndexDataFunction|| null;
38 this._setDirectLoginIndexDataFunction = args.setDirectLoginIndexDataFunction || null;
39 this._removeDirectLoginIndexDataFunction = args.removeDirectLoginIndexDataFunction|| null;
40
41 this._createNewDirectLoginFunction = args.createNewDirectLoginFunction || null;
42
43 this._directLogins = {};
44
45 this._versions = {};
46
47 this._currentRecordVersion = null;
48 if (this.isBrandNew()) {
49 var newVersion;
50
51 this.setNotes('');
52 newVersion = new Clipperz.PM.DataModel.Record.Version({
53 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'),
54 'getVersion': MochiKit.Base.method(this, 'getVersion')
55
56 });
57 this._versions[newVersion.reference()] = newVersion;
58 this._currentVersionReference = newVersion.reference();
59 // this.setLabel('');
60 }
61
62 return this;
63}
64
65
66Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.EncryptedRemoteObject, {
67
68 'toString': function() {
69 return "Record (" + this.reference() + ")";
70 },
71
72 //-------------------------------------------------------------------------
73
74 'reference': function () {
75 return this._reference;
76 },
77
78 //=========================================================================
79
80 'getIndexData': function () {
81 return this._retrieveIndexDataFunction(this.reference());
82 },
83
84 //.........................................................................
85
86 'getIndexDataForKey': function (aKey) {
87 return Clipperz.Async.callbacks("Record.getIndexDataForKey", [
88 MochiKit.Base.method(this, 'getIndexData'),
89 MochiKit.Base.itemgetter(aKey)
90 ], {trace:false});
91 },
92
93 //-------------------------------------------------------------------------
94
95 'setIndexDataForKey': function (aKey, aValue) {
96 // return this._updateIndexDataFunction(this.reference(), aKey, aValue);
97
98 var deferredResult;
99
100 deferredResult = new Clipperz.Async.Deferred("Record.setIndexDataForKey", {trace:false});
101 deferredResult.addMethod(this, 'getIndexDataForKey', aKey);
102 deferredResult.addCallback(MochiKit.Base.bind(function (aCurrentValue) {
103 var result;
104 var originalValue;
105
106 originalValue = this.transientState().getValue('originalValues.indexData.' + aKey);
107 if (originalValue == null) {
108 originalValue = this.transientState().setValue('originalValues.indexData.' + aKey, aCurrentValue);
109 }
110
111 if (aCurrentValue != aValue) {
112 if (originalValue != aValue) {
113 this.transientState().setValue('hasPendingChanges.indexData.' + aKey, true);
114 } else {
115 this.transientState().setValue('hasPendingChanges.indexData.' + aKey, false);
116 }
117
118 result = this._updateIndexDataFunction(this.reference(), aKey, aValue);
119 } else {
120 result = MochiKit.Async.succeed(aValue);
121 }
122
123 return result;
124 }, this));
125
126 deferredResult.callback();
127
128 return deferredResult;
129 },
130
131 //=========================================================================
132/*
133 'key': function () {
134 return this.getIndexDataForKey('key');
135 },
136*/
137 //=========================================================================
138
139 'label': function () {
140 return this.getIndexDataForKey('label');
141 },
142
143 //.........................................................................
144
145 'setLabel': function (aValue) {
146 return this.setIndexDataForKey('label', aValue);
147 },
148
149 //=========================================================================
150
151 'headerNotes': function () {
152 return this.getIndexDataForKey('notes');
153 },
154
155 //-------------------------------------------------------------------------
156
157 'notes': function () {
158 return Clipperz.Async.callbacks("Record.notes", [
159 MochiKit.Base.method(this, 'headerNotes'),
160 MochiKit.Base.bind(function (someHeaderNotes) {
161 var result;
162
163 if ((someHeaderNotes == null) || (typeof(someHeaderNotes) == 'undefined')) {
164 result = this.getValue('notes');
165 } else {
166 result = MochiKit.Async.succeed(someHeaderNotes);
167 }
168
169 return result;
170 }, this)
171 ], {trace:false});
172 },
173
174 //.........................................................................
175
176 'setNotes': function (aValue) {
177 return this.setValue('notes', aValue);
178 },
179
180 //=========================================================================
181
182 'updateDate': function () {
183 return MochiKit.Async.succeed(this._updateDate);
184 },
185
186 //=========================================================================
187
188 'favicon': function () {
189 var result;
190 var directLogins;
191
192 directLogins = MochiKit.Base.values(this.directLogins());
193 if (directLogins.length > 0) {
194 result = directLogins[0].favicon();
195 // } else if (/* is there an URL to use for searching a favicon */){
196 } else {
197 result = null; //MochiKit.Async.succeed(Clipperz.PM.Strings['defaultFaviconUrl']);
198 }
199
200 return result;
201 },
202
203 //-------------------------------------------------------------------------
204
205 'searchableContent': function () {
206 var deferredResult;
207
208 deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false});
209
210 deferredResult.collectResults({
211 'recordLabel': MochiKit.Base.method(this, 'label'),
212 'directLoginLabels': [
213 MochiKit.Base.method(this, 'directLoginReferences'),
214 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label'))
215 ]
216 })
217 deferredResult.addCallback(function (someValues) {
218 return someValues['recordLabel'] + ' ' + someValues['directLoginLabels'].join(' ');
219 });
220 deferredResult.callback();
221
222 return deferredResult;
223 },
224
225 //-------------------------------------------------------------------------
226
227 'isMatching': function (aRegExp) {
228 return Clipperz.Async.callbacks("deferredFilterFunction", [
229 MochiKit.Base.method(this, 'searchableContent'),
230 MochiKit.Base.method(aRegExp, 'test'),
231 function (doesItMatch) {
232 var result;
233
234 if (doesItMatch) {
235 result = MochiKit.Async.succeed('match');
236 } else {
237 result = MochiKit.Async.fail('miss');
238 }
239
240 return result;
241 }
242 ], {trace:false});
243 },
244
245 //=========================================================================
246
247 'content': function () {
248 var deferredResult;
249 varresult;
250
251 result = {
252 'fields': [],
253 'directLogins': []
254 };
255
256 deferredResult = new Clipperz.Async.Deferred("Record.content", {trace:false});
257 deferredResult.addMethod(this, 'reference');
258 deferredResult.addCallback(function (aValue) { result['reference'] = aValue; });
259 deferredResult.addMethod(this, 'label');
260 deferredResult.addCallback(function (aValue) { result['title'] = aValue; });
261 deferredResult.addMethod(this, 'notes');
262 deferredResult.addCallback(function (aValue) { result['notes'] = aValue; });
263
264 deferredResult.addMethod(this, 'fields');
265 deferredResult.addCallback(MochiKit.Base.values);
266 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content'));
267 deferredResult.addCallback(Clipperz.Async.collectAll);
268 deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['fields'].push(aValue); });
269
270 deferredResult.addMethod(this, 'directLogins');
271 deferredResult.addCallback(MochiKit.Base.values);
272 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content'));
273 deferredResult.addCallback(Clipperz.Async.collectAll);
274 deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['directLogins'].push(aValue); });
275 deferredResult.addCallback(function () { return result; });
276
277 deferredResult.callback();
278
279 return deferredResult;
280 },
281
282 //=========================================================================
283
284 'directLogins': function () {
285 return this._directLogins;
286 },
287
288 'addDirectLogin': function (aDirectLogin) {
289 this._directLogins[aDirectLogin.reference()] = aDirectLogin;
290 },
291
292 'directLoginWithReference': function (aDirectLoginReference) {
293 return this._directLogins[aDirectLoginReference];
294 },
295
296 'createNewDirectLoginFunction': function () {
297 return this._createNewDirectLoginFunction;
298 },
299
300 'saveOriginalDirectLoginStatusToTransientState': function () {
301 if (this.transientState().getValue('directLogins') == null) {
302 // this.transientState().setValue('directLogins', this._directLogins)
303 MochiKit.Iter.forEach(MochiKit.Base.keys(this._directLogins), MochiKit.Base.bind(function(aKey) {
304 this.transientState().setValue('directLogins' + '.' + aKey, this._directLogins[aKey])
305 }, this))
306 }
307 },
308
309 'createNewDirectLogin': function () {
310 this.saveOriginalDirectLoginStatusToTransientState();
311
312 return this.createNewDirectLoginFunction()(this);
313 },
314
315 'removeDirectLogin': function(aDirectLogin) {
316 this.saveOriginalDirectLoginStatusToTransientState();
317
318 return Clipperz.Async.callbacks("Record.removeDirectLogin", [
319 MochiKit.Base.method(this, 'removeValue', 'directLogins' + '.' + aDirectLogin.reference()),
320 MochiKit.Base.bind(function () {
321 delete this._directLogins[aDirectLogin.reference()]
322 }, this)
323 ], {trace:false});
324
325 },
326
327 'directLoginReferences': function () {
328 var result;
329
330 result = Clipperz.Async.callbacks("Record.directLoginReferences", [
331 MochiKit.Base.method(this, 'directLogins'),
332 MochiKit.Base.values,
333 function (someDirectLogins) {
334 var result;
335 var i,c;
336
337 result = [];
338 c = someDirectLogins.length;
339 for (i=0; i<c; i++) {
340 result.push(Clipperz.Async.collectResults("Record.directLoginReferences - collectResults", {
341 '_rowObject': MochiKit.Async.succeed,
342 '_reference': MochiKit.Base.methodcaller('reference'),
343 'label': MochiKit.Base.methodcaller('label'),
344 'favicon': MochiKit.Base.methodcaller('favicon')
345 }, {trace:false})(someDirectLogins[i]));
346 };
347
348 return result;
349 },
350 Clipperz.Async.collectAll
351 ], {trace:false});
352
353 return result;
354 },
355
356 //=========================================================================
357
358 'unpackRemoteData': function (someData) {
359 var result;
360
361/*
362 this._currentRecordVersion = new Clipperz.PM.DataModel.Record.Version({
363 'reference': someData['currentVersion']['reference'],
364 'retrieveKeyFunction': MochiKit.Base.method(this, 'getCurrentRecordVersionKey'),
365 'remoteData': someData['currentVersion'],
366 });
367*/
368 var versionKey;
369
370 for (versionKey in someData['versions']) {
371 this._versions[versionKey] = new Clipperz.PM.DataModel.Record.Version({
372 'reference': versionKey,
373 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'),
374 'remoteData': someData['versions'][versionKey],
375 'getVersion': MochiKit.Base.method(this, 'getVersion')
376 })
377 }
378
379 // this._currentVersionReference = someData['currentVersion']['reference'];
380 this._currentVersionReference = someData['currentVersion'];
381
382 result = Clipperz.PM.DataModel.Record.superclass.unpackRemoteData.apply(this, arguments);
383
384 return result;
385 },
386
387 //-------------------------------------------------------------------------
388
389 'unpackData': function (someData) {
390 var result;
391
392 result = Clipperz.PM.DataModel.Record.superclass.unpackData.apply(this, arguments);
393
394 if (MochiKit.Base.isUndefinedOrNull(result['notes'])) {
395 result['notes'] = ''
396 }
397
398 return result;
399 },
400
401 //-------------------------------------------------------------------------
402
403 'prepareRemoteDataWithKey': function (aKey) {
404 var deferredResult;
405 varnewVersionKey;
406 var result;
407
408 newVersionKey = Clipperz.PM.Crypto.randomKey();
409 result = {};
410
411 deferredResult = new Clipperz.Async.Deferred("Record.prepareRemoteDataWithKey", {trace:false});
412 deferredResult.addCallbackList([
413 Clipperz.Async.collectResults("Record.prepareRemoteDataWithKey - collect results", {
414 'isBrandNew': MochiKit.Base.method(this, 'isBrandNew'),
415 'versionHasPendingChanges':[
416 // MochiKit.Base.method(this, 'getCurrentRecordVersion'),
417 // MochiKit.Base.methodcaller('hasPendingChanges')
418 MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges')
419 ]
420 }),
421 Clipperz.Async.or,
422
423 Clipperz.Async.deferredIf("Current Version has pending changes", [
424 MochiKit.Base.method(this, 'createNewRecordVersion'),
425 MochiKit.Base.methodcaller('prepareRemoteDataWithKey', newVersionKey),
426 MochiKit.Base.partial(Clipperz.Async.setItem, result, 'currentRecordVersion'),
427 MochiKit.Base.method(this, 'setCurrentRecordVersionKey', newVersionKey)
428 ], []),
429
430 MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey),
431 MochiKit.Base.partial(Clipperz.Async.setItem, result, 'record'),
432
433 MochiKit.Base.partial(MochiKit.Async.succeed, result)
434 ]);
435
436 deferredResult.callback();
437
438 return deferredResult;
439 },
440
441 //=========================================================================
442
443 'fields': function () {
444 return this.invokeCurrentRecordVersionMethod('fields');
445 },
446
447 'addField': function (someParameters) {
448 return this.invokeCurrentRecordVersionMethod('addField', someParameters);
449 },
450
451 'removeField': function (someParameters) {
452 return this.invokeCurrentRecordVersionMethod('removeField', someParameters);
453 },
454
455 //'sortFieldReference': function (someSortedFieldReferences) {
456 // return this.invokeCurrentRecordVersionMethod('sortFieldReference', someSortedFieldReferences);
457 //},
458
459 'getFieldsValues': function () {
460 return this.invokeCurrentRecordVersionMethod('getFieldsValues');
461 },
462
463 'fieldWithLabel': function (aLabel) {
464 return Clipperz.Async.callbacks("Record.fieldWithLabel", [
465 MochiKit.Base.method(this, 'fields'),
466 MochiKit.Base.values,
467 MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aField) {
468 return Clipperz.Async.callbacks("Record.fieldWithLabel - check field label", [
469 MochiKit.Base.methodcaller('label'),
470 MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel)
471 ], {trace:false}, aField);
472 }),
473 function (someFilteredResults) {
474 var result;
475
476 switch (someFilteredResults.length) {
477 case 0:
478 result = null;
479 break;
480 case 1:
481 result = someFilteredResults[0];
482 break;
483 default:
484 WTF = TODO;
485 break;
486 }
487
488 return result;
489 }
490 ], {trace:false});
491 },
492
493 //=========================================================================
494
495 'getVersion': function (aVersionReference) {
496 return Clipperz.Async.callbacks("Record.getVersion", [
497 MochiKit.Base.method(this, 'getVersions'),
498 MochiKit.Base.itemgetter(aVersionReference)
499 ], {trace:false});
500 },
501
502 //-------------------------------------------------------------------------
503
504 'getVersionKey': function (aVersionReference) {
505 vardeferredResult;
506 var transientStateKey;
507
508 transientStateKey = 'versionKeys' + '.' + aVersionReference;
509 if (this.transientState().getValue(transientStateKey) != null) {
510 deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey));
511 } else {
512 deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [
513 MochiKit.Base.method(this, 'getVersions'),
514 MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()),
515 Clipperz.Async.deferredIf("getVersionKey for current version", [
516 MochiKit.Base.method(this, 'getCurrentRecordVersionKey'),
517 MochiKit.Base.method(this.transientState(), 'setValue', transientStateKey)
518 ],[
519 MochiKit.Async.fail
520 ])
521 ], {trace:false});
522 }
523
524 return deferredResult;
525 },
526
527 //-------------------------------------------------------------------------
528
529 'versions': function () {
530 return this._versions;
531 },
532
533 'getVersions': function () {
534 return Clipperz.Async.callbacks("Record.versions", [
535 MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'),
536 MochiKit.Base.bind(function () { return this._versions; }, this)
537 ], {trace:false});
538 },
539
540 //-------------------------------------------------------------------------
541
542 'getCurrentRecordVersion': function () {
543 return Clipperz.Async.callbacks("Record.getCurrentRecordVersion", [
544 // MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'),
545 // MochiKit.Base.bind(function () { return this._currentRecordVersion; }, this)
546
547 MochiKit.Base.method(this, 'versions'),
548 MochiKit.Base.itemgetter(this.currentVersionReference()),
549 Clipperz.Async.deferredIf("The current version is available", [
550 MochiKit.Async.succeed
551 ], [
552 MochiKit.Base.method(this, 'getVersions'),
553 MochiKit.Base.bind(function (someVersions) { return someVersions[this.currentVersionReference()]}, this)
554 ])
555 ], {trace:false});
556 },
557
558 'setCurrentRecordVersion': function (aRecordVersion) {
559 this._currentVersionReference = aRecordVersion.reference();
560 },
561
562 //.........................................................................
563
564 'currentVersionReference': function () {
565 return this._currentVersionReference;
566 },
567
568 //-------------------------------------------------------------------------
569
570 'createNewRecordVersion': function () {
571 var deferredResult;
572
573 if (this.isBrandNew()) {
574 deferredResult = this.getCurrentRecordVersion();
575 } else {
576 var newVersion;
577
578 newVersion = new Clipperz.PM.DataModel.Record.Version({
579 // 'reference': versionKey,
580 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'),
581 // 'remoteData': {},
582 'getVersion': MochiKit.Base.method(this, 'getVersion')
583 })
584 this._versions[newVersion.reference()] = newVersion;
585
586 deferredResult = Clipperz.Async.callbacks("Record.createNewRecordVersion", [
587 // MochiKit.Base.method(this, 'getCurrentRecordVersion'),
588 // MochiKit.Base.methodcaller('values'),
589 MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'values'),
590 MochiKit.Base.method(newVersion, 'setValues'),
591
592 Clipperz.Async.collectResults("Record.createNewRecordVersion [collect results]", {
593 'reference':MochiKit.Base.method(this, 'currentVersionReference'),
594 'key': MochiKit.Base.method(this, 'getCurrentRecordVersionKey')
595 }, {trace:false}),
596 MochiKit.Base.method(newVersion, 'setPreviousVersionReferenceAndKey'),
597
598 // MochiKit.Base.method(this, 'getCurrentRecordVersion'),
599 // MochiKit.Base.method(this, 'revertChanges'),
600 MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
601
602 MochiKit.Base.method(this, 'setCurrentRecordVersion', newVersion),
603 MochiKit.Base.partial(MochiKit.Async.succeed, newVersion)
604 ], {trace:false});
605 }
606
607 return deferredResult;
608 },
609
610 //-------------------------------------------------------------------------
611
612 'getCurrentRecordVersionKey': function () {
613 return Clipperz.Async.callbacks("Record.getCurrentRecordVersionKey", [
614 MochiKit.Base.method(this, 'getValue', 'currentVersionKey'),
615 Clipperz.Async.deferredIf("currentVersionKey is NOT null", [
616 MochiKit.Async.succeed
617 ], [
618 MochiKit.Base.method(this, 'getKey')
619 ])
620 ], {trace:false});
621 },
622
623 'setCurrentRecordVersionKey': function (aValue) {
624 //TODO: triple check this method!
625 return Clipperz.Async.callbacks("Record.setCurrentRecordVersionKey", [
626 MochiKit.Base.method(this, 'setValue', 'currentVersionKey', aValue)
627 ], {trace:false});
628 },
629
630 //-------------------------------------------------------------------------
631
632 'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) {
633 return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [
634 MochiKit.Base.method(this, 'getCurrentRecordVersion'),
635 MochiKit.Base.methodcaller(aMethodName, someValues)
636 ], {trace:false});
637 },
638
639
640 'lazilyinvokeCurrentRecordVersionMethod': function (aMethodName, someValues, defaultResult) {
641 return Clipperz.Async.callbacks("Record.lazilyinvokeCurrentRecordVersionMethod", [
642 MochiKit.Base.method(this, 'currentVersionReference'),
643 Clipperz.Async.deferredIf("versions has been loaded", [
644 MochiKit.Base.method(this, 'getCurrentRecordVersion'),
645 MochiKit.Base.methodcaller(aMethodName, someValues),
646 ], [
647 MochiKit.Base.partial(MochiKit.Async.succeed, defaultResult),
648 ])
649 ], {trace:false});
650 },
651
652 //=========================================================================
653
654 'hasPendingChanges': function () {
655 var deferredResult;
656
657 if (this.hasInitiatedObjectDataStore()) {
658 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false});
659 deferredResult.collectResults({
660 'super': MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this),
661 'currentVersion': [
662 // MochiKit.Base.method(this, 'getCurrentRecordVersion'),
663 // MochiKit.Base.methodcaller('hasPendingChanges')
664 MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges')
665 ],
666 'directLogins': [
667 MochiKit.Base.method(this, 'directLogins'),
668 MochiKit.Base.values,
669 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')),
670 Clipperz.Async.collectAll,
671 Clipperz.Async.or
672 // function(someValues) {
673 // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
674 // }
675 ]
676 });
677 deferredResult.addCallback(MochiKit.Base.values);
678 deferredResult.addCallback(MochiKit.Base.bind(function(someValues) {
679 var result;
680 result = MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
681
682 if ((result == false) && (this.isBrandNew() == false)) {
683 result = MochiKit.Iter.some(MochiKit.Base.values(this.transientState().getValue('hasPendingChanges.indexData')), MochiKit.Base.operator.identity);
684 }
685
686 return result;
687 }, this));
688
689 deferredResult.callback();
690 } else {
691 deferredResult = Clipperz.Async.callbacks("Recrod.hasPendingChanges [hasInitiatedObjectDataStore == false]", [
692 MochiKit.Base.method(this, 'directLogins'),
693 MochiKit.Base.values,
694 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')),
695 Clipperz.Async.collectAll,
696 Clipperz.Async.or
697 // function(someValues) {
698 // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
699 // }
700 ], {trace:false})
701 }
702
703 return deferredResult;
704 },
705
706 //-------------------------------------------------------------------------
707
708 'hasPendingChangesWhenBrandNew': function () {
709 var deferredResult;
710
711 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChangesWhenBrandNew", {trace:false});
712 deferredResult.collectResults({
713 'label': [
714 MochiKit.Base.method(this, 'label'),
715 MochiKit.Base.partial(MochiKit.Base.operator.ne, '')
716 ],
717 'notes': [
718 MochiKit.Base.method(this, 'notes'),
719 MochiKit.Base.partial(MochiKit.Base.operator.ne, '')
720 ]
721 });
722 // deferredResult.addCallback(MochiKit.Base.values);
723 // deferredResult.addCallback(function(someValues) {
724 // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
725 // });
726 deferredResult.addCallback(Clipperz.Async.or);
727
728 deferredResult.callback();
729
730 return deferredResult;
731 },
732
733 //-------------------------------------------------------------------------
734
735 'isBrandNewWithNoPendingChanges': function () {
736 vardeferredResult;
737
738 if (this.isBrandNew() == false) {
739 deferredResult = MochiKit.Async.succeed(false);
740 } else {
741 deferredResult = Clipperz.Async.callbacks("Record.isBrandNewWithNoPendingChanges", [
742 MochiKit.Base.method(this, 'hasPendingChanges'),
743 MochiKit.Base.operator.lognot
744 ], {trace:false});
745 }
746
747 return deferredResult;
748 },
749
750 //=========================================================================
751
752 'revertChanges': function () {
753 var deferredResult;
754
755 if (this.isBrandNew() == false) {
756 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false});
757 deferredResult.addMethod(this, 'hasPendingChanges');
758 deferredResult.addIf([
759 // MochiKit.Base.method(this, 'getCurrentRecordVersion'),
760 // MochiKit.Base.methodcaller('revertChanges'),
761 MochiKit.Base.method(this,'invokeCurrentRecordVersionMethod', 'revertChanges'),
762
763 MochiKit.Base.method(this, 'directLogins'),
764 MochiKit.Base.values,
765 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')),
766
767 MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this)
768 ], [
769 MochiKit.Async.succeed
770 ]);
771 deferredResult.callback();
772 } else {
773 // this.deleteAllCleanTextData();
774 deferredResult = MochiKit.Async.succeed();
775 }
776
777 return deferredResult;
778 },
779
780 //-------------------------------------------------------------------------
781
782 'resetTransientState': function (isCommitting) {
783 // if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) {
784 // this._directLogins = this.transientState().getValue('directLogins');
785 // }
786
787 return Clipperz.Async.callbacks("Record.resetTransientState", [
788 //- MochiKit.Base.method(this, 'getCurrentRecordVersion'),
789 //- MochiKit.Base.methodcaller('resetTransientState'),
790 // MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'resetTransientState'),
791 MochiKit.Base.method(this, 'lazilyinvokeCurrentRecordVersionMethod', 'resetTransientState'),
792
793 MochiKit.Base.method(this, 'directLogins'),
794 MochiKit.Base.values,
795 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('resetTransientState')),
796
797 MochiKit.Base.bind(function () {
798 if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) {
799 this._directLogins = this.transientState().getValue('directLogins');
800 }
801 }, this),
802
803 MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.resetTransientState, this, isCommitting)
804 ], {trace:false})
805 },
806
807 //-------------------------------------------------------------------------
808
809 'commitTransientState': function () {
810 var deferredResult;
811
812 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.commitTransientState", {trace:false});
813 deferredResult.addMethod(this, 'hasPendingChanges');
814 deferredResult.addIf([
815 MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.commitTransientState, this),
816 // MochiKit.Base.method(this, 'getCurrentRecordVersion'),
817 // MochiKit.Base.methodcaller('commitTransientState'),
818 MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'commitTransientState'),
819 MochiKit.Base.method(this, 'directLogins'),
820 MochiKit.Base.values,
821 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('commitTransientState'))
822 ], [
823 MochiKit.Async.succeed
824 ]);
825 deferredResult.callback();
826
827 return deferredResult;
828 },
829
830 //=========================================================================
831
832 'retrieveDirectLoginIndexDataFunction': function () {
833 return this._retrieveDirectLoginIndexDataFunction;
834 },
835
836 'setDirectLoginIndexDataFunction': function () {
837 return this._setDirectLoginIndexDataFunction;
838 },
839
840 'removeDirectLoginIndexDataFunction': function () {
841 return this._removeDirectLoginIndexDataFunction;
842 },
843
844 //=========================================================================
845
846 'deleteAllCleanTextData': function () {
847 // return Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData.apply(this, arguments);
848
849 return Clipperz.Async.callbacks("Record.deleteAllCleanTextData", [
850 MochiKit.Base.method(this, 'versions'),
851 MochiKit.Base.values,
852 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
853
854 MochiKit.Base.method(this, 'directLogins'),
855 MochiKit.Base.values,
856 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
857
858 MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData, this)
859 ], {trace:false});
860 },
861
862 'hasAnyCleanTextData': function () {
863 // return Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData.apply(this, arguments);
864
865 return Clipperz.Async.callbacks("Record.hasAnyCleanTextData", [
866 Clipperz.Async.collectResults("Record.hasAnyCleanTextData [collect results]", {
867 'versions':[
868 MochiKit.Base.method(this, 'versions'),
869 MochiKit.Base.values,
870 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
871 Clipperz.Async.collectAll
872 ],
873 'directLogins': [
874 MochiKit.Base.method(this, 'directLogins'),
875 MochiKit.Base.values,
876 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
877 Clipperz.Async.collectAll
878 ],
879 'super': [
880 MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData, this)
881 ]
882 }, {trace:false}),
883 Clipperz.Async.or
884 ])
885 },
886
887 //=========================================================================
888 __syntaxFix__: "syntax fix"
889});
890
891
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js
new file mode 100644
index 0000000..cda5a41
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js
@@ -0,0 +1,182 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.User.Header.Legacy depends on Clipperz.PM.DataModel.User!";
26}
27
28if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
29
30Clipperz.PM.DataModel.User.Header.Legacy = function(args) {
31 //args = args || {};
32 Clipperz.PM.DataModel.User.Header.Legacy.superclass.constructor.apply(this, arguments);
33
34 this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction|| Clipperz.Base.exception.raise('MandatoryParameter');
35 this._records = null;
36 //this._directLogins = null;
37
38 return this;
39}
40
41
42Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Legacy, Clipperz.PM.DataModel.EncryptedRemoteObject, {
43
44 'toString': function() {
45 return "Clipperz.PM.DataModel.User.Header.Legacy";
46 },
47
48 //-------------------------------------------------------------------------
49
50 'retrieveRecordDetailFunction': function () {
51 return this._retrieveRecordDetailFunction;
52 },
53
54 //-------------------------------------------------------------------------
55
56 'getRecordKey': function (aRecordReference) {
57 var deferredResult;
58
59 deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.getRecordKey", {trace:false});
60 deferredResult.addMethod(this, 'getRecordIndexData');
61 deferredResult.addCallback(MochiKit.Base.itemgetter('key'))
62 deferredResult.callback();
63
64 return deferredResult;
65 },
66
67 //=========================================================================
68
69 'getRecordIndexData': function (aRecordReference) {
70 return this.getValue('records.' + aRecordReference);
71 },
72
73 'updateRecordIndexData': function (aRecordReference, aKey, aValue) {
74 return this.setValue('records.' + aRecordReference + "." + aKey, aValue);
75 },
76
77 //-------------------------------------------------------------------------
78
79 'getDirectLoginIndexData': function (aDirectLoginReference) {
80 return this.getValue('directLogins.' + aDirectLoginReference);
81 },
82
83 'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) {
84 return this.setValue('directLogins.' + aDirectLoginReference + '.' + aKey, aValue);
85 },
86
87 'removeDirectLoginIndexData': function (aDirectLoginReference) {
88 return this.removeValue('directLogins.' + aDirectLoginReference);
89 },
90
91 //=========================================================================
92
93 'records': function () {
94 vardeferredResult;
95 var deferredLock;
96
97 deferredLock = this.getDeferredLockForKey('records');
98
99 deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records", {trace:false});
100 deferredResult.acquireLock(deferredLock);
101 deferredResult.addCallback(MochiKit.Base.bind(function () {
102 var innerDeferredResult;
103
104 if (this._records == null) {
105 innerDeferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records <inner deferred>", {trace:false});
106 innerDeferredResult.collectResults({
107 'header': [
108 // MochiKit.Base.method(this, 'getObjectDataStore'),
109 // MochiKit.Base.methodcaller('values')
110 MochiKit.Base.method(this, 'values')
111 ],
112 'recordsStats': [
113 MochiKit.Base.method(this, 'getRemoteData'),
114 MochiKit.Base.itemgetter('recordsStats')
115 ]
116 });
117 innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) {
118 var reference;
119
120 this._records = {};
121 // this._directLogins = {};
122
123 for (reference in someObjectData['header']['records']) {
124 varrecord;
125
126 record = new Clipperz.PM.DataModel.Record({
127 'reference': reference,
128 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'),
129 'retrieveRemoteDataFunction':this.retrieveRecordDetailFunction(),
130 // 'encryptedDataKeypath': 'data',
131 // 'encryptedVersionKeypath': 'version',
132
133 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getRecordIndexData'),
134 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
135 'updateDate': someObjectData['recordsStats'][reference]['updateDate'],
136
137 'retrieveDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'),
138 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
139 'removeDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'removeDirectLoginIndexData')
140 });
141
142 this._records[reference] = record;
143 }
144
145 for (reference in someObjectData['header']['directLogins']) {
146 vardirectLogin;
147 var record;
148
149 record = this._records[someObjectData['header']['directLogins'][reference]['record']];
150 if (record != null) {
151 directLogin = new Clipperz.PM.DataModel.DirectLogin({
152 'reference': reference,
153 'record': record//,
154 // 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'),
155 // 'setIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
156 // 'removeIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData')
157 });
158 } else {
159Clipperz.log("WARNING: DIRECT LOGIN without a matching RECORD!!");
160 }
161 }
162
163 return this._records;
164 }, this));
165 innerDeferredResult.callback();
166 } else {
167 innerDeferredResult = MochiKit.Async.succeed(this._records);
168 }
169
170 return innerDeferredResult;
171 }, this));
172 deferredResult.releaseLock(deferredLock);
173 deferredResult.callback();
174
175 return deferredResult;
176 },
177
178 //=========================================================================
179 __syntaxFix__: "syntax fix"
180});
181
182
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js
new file mode 100644
index 0000000..e82da47
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js
@@ -0,0 +1,117 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.User.Header.OneTimePasswords depends on Clipperz.PM.DataModel.User!";
26}
27if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
28
29//-----------------------------------------------------------------------------
30
31Clipperz.PM.DataModel.User.Header.OneTimePasswords = function(args) {
32 Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.constructor.apply(this, arguments);
33
34 this._oneTimePasswords = null;
35
36 return this;
37}
38
39//-----------------------------------------------------------------------------
40
41Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.OneTimePasswords, Clipperz.PM.DataModel.EncryptedRemoteObject, {
42
43 'toString': function() {
44 return "Clipperz.PM.DataModel.User.Header.OneTimePasswords";
45 },
46
47 //-------------------------------------------------------------------------
48/*
49 'packData': function (someData) { //++
50 var result;
51
52 result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packData.apply(this, arguments);
53
54 return result;
55 },
56*/
57 //-------------------------------------------------------------------------
58/*
59 'packRemoteData': function (someData) {
60 var result;
61
62 result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packRemoteData.apply(this, arguments);
63
64 return result;
65 },
66*/
67 //-------------------------------------------------------------------------
68/*
69 'prepareRemoteDataWithKey': function (aKey) {
70 var result;
71
72 result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.prepareRemoteDataWithKey.apply(this, arguments);
73
74 return result;
75 },
76*/
77 //=========================================================================
78
79 'oneTimePasswords': function () {
80 vardeferredResult;
81
82 deferredResult = new Clipperz.Async.Deferred("User.Header.OneTimePasswords.oneTimePasswords", {trace:false});
83 if (this._oneTimePasswords == null) {
84 deferredResult.addMethod(this, 'values')
85 deferredResult.addCallback(MochiKit.Base.bind(function (someData) {
86 varotpKey;
87
88 this._oneTimePasswords = {};
89
90 for (otpKey in someData) {
91 var otp;
92 var otpParameters;
93
94 otpParameters = Clipperz.Base.deepClone(someData[otpKey]);
95 otpParameters['reference'] = otpKey;
96
97 otp = new Clipperz.PM.DataModel.OneTimePassword(otpParameters);
98 this._oneTimePasswords[otpKey] = otp;
99 }
100
101 return this._oneTimePasswords;
102
103 }, this));
104 deferredResult.callback();
105 } else {
106 deferredResult = MochiKit.Async.succeed(this._oneTimePasswords);
107 }
108
109 return deferredResult;
110 },
111
112 //=========================================================================
113 __syntaxFix__: "syntax fix"
114});
115
116//-----------------------------------------------------------------------------
117
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js
new file mode 100644
index 0000000..f1f95e8
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js
@@ -0,0 +1,48 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.User.Header.Preferences depends on Clipperz.PM.DataModel.User!";
26}
27
28if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
29
30Clipperz.PM.DataModel.User.Header.Preferences = function(args) {
31 Clipperz.PM.DataModel.User.Header.Preferences.superclass.constructor.apply(this, arguments);
32
33 return this;
34}
35
36
37Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Preferences, Clipperz.PM.DataModel.EncryptedRemoteObject, {
38
39 'toString': function() {
40 return "Clipperz.PM.DataModel.User.Header.Preferences";
41 },
42
43 //-------------------------------------------------------------------------
44 //=========================================================================
45 __syntaxFix__: "syntax fix"
46});
47
48
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js
new file mode 100644
index 0000000..5681f70
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js
@@ -0,0 +1,685 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.User.Header.RecordIndex depends on Clipperz.PM.DataModel.User!";
26}
27
28if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
29
30Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) {
31 Clipperz.PM.DataModel.User.Header.RecordIndex.superclass.constructor.apply(this, arguments);
32
33 this._recordsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({
34 'name':'recordsData',
35 'retrieveKeyFunction': args.retrieveKeyFunction,
36 'remoteData': {
37 'data': args.recordsData['data'],
38 'version': args.encryptedDataVersion,
39 'recordsStats': args.recordsStats
40 }//,
41 // 'encryptedDataKeypath': 'data',
42 // 'encryptedVersionKeypath': 'version'
43 });
44
45 this._directLoginsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({
46 'name':'directLoginsData',
47 'retrieveKeyFunction': args.retrieveKeyFunction,
48 'remoteData': {
49 'data': args.directLoginsData['data'],
50 'version': args.encryptedDataVersion
51 }//,
52 // 'encryptedDataKeypath': 'data',
53 // 'encryptedVersionKeypath': 'version'
54 });
55
56 this._lock = new MochiKit.Async.DeferredLock();
57 this._transientState = null;
58
59 this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction|| Clipperz.Base.exception.raise('MandatoryParameter');
60 this._recordsIndex = args.recordsData['index'] || Clipperz.Base.exception.raise('MandatoryParameter');
61 this._directLoginsIndex = args.directLoginsData['index']|| Clipperz.Base.exception.raise('MandatoryParameter');
62
63 this._records = null;
64
65 return this;
66}
67
68
69Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
70
71 'toString': function() {
72 return "Clipperz.PM.DataModel.User.Header.RecordIndex";
73 },
74
75 //-------------------------------------------------------------------------
76
77 'retrieveRecordDetailFunction': function () {
78 return this._retrieveRecordDetailFunction;
79 },
80
81 //-------------------------------------------------------------------------
82
83 'recordsIndex': function () {
84 return this._recordsIndex;
85 },
86
87 'recordsData': function () {
88 return this._recordsData;
89 },
90
91 //-------------------------------------------------------------------------
92
93 'directLoginsIndex': function () {
94 return this._directLoginsIndex;
95 },
96
97 'directLoginsData': function () {
98 return this._directLoginsData;
99 },
100
101 //-------------------------------------------------------------------------
102
103 'lock': function () {
104 return this._lock;
105 },
106
107 //-------------------------------------------------------------------------
108
109 'transientState': function () {
110 if (this._transientState == null) {
111 this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'User.Header.RecordIndex.transientState [1]'}*/);
112 }
113
114 return this._transientState;
115 },
116
117 'resetTransientState': function (isCommitting) {
118 if (this._transientState != null) {
119 this._transientState.removeAllData();
120 }
121
122 this._transientState = null;
123 },
124
125 //-------------------------------------------------------------------------
126
127 'getRecordKey': function (aRecordReference) {
128 return Clipperz.Async.callbacks("User.Header.RecordIndex.getRecordKey", [
129 MochiKit.Base.method(this, 'getRecordIndexData', aRecordReference),
130 MochiKit.Base.itemgetter('key')
131 ], {trace:false});
132 },
133
134 'setRecordKey': function (aRecordReference, aValue) {
135 return this.updateRecordIndexData(aRecordReference, 'key', aValue);
136 },
137
138 //-------------------------------------------------------------------------
139
140 'getRecordIndexData': function (aRecordReference) {
141 return this.recordsData().getValue(this.recordsIndex()[aRecordReference]);
142 },
143
144 //.........................................................................
145
146 'updateRecordIndexData': function (aRecordReference, aKey, aValue) {
147 return this.recordsData().setValue(this.recordsIndex()[aRecordReference]+'.'+aKey, aValue);
148 },
149
150 //-------------------------------------------------------------------------
151
152 'getDirectLoginIndexData': function (aDirectLoginReference) {
153 return this.directLoginsData().getValue(this.directLoginsIndex()[aDirectLoginReference]);
154 },
155
156 'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) {
157//if (MochiKit.Base.isUndefinedOrNull(this.directLoginsIndex()[aDirectLoginReference])) {
158 //throw "PIPPO";
159//}
160 return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference] + '.' + aKey, aValue);
161 },
162
163 'addDirectLoginIndexData': function (aDirectLoginReference) {
164 return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference], {});
165 },
166
167 'removeDirectLoginIndexData': function (aDirectLoginReference) {
168 return this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLoginReference])
169 },
170
171 //-------------------------------------------------------------------------
172
173 'records': function () {
174 vardeferredResult;
175
176 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records", {trace:false});
177 deferredResult.acquireLock(this.lock());
178 deferredResult.addCallback(MochiKit.Base.bind(function () {
179 var innerDeferredResult;
180
181 if (this._records == null) {
182 innerDeferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records <inner deferred>", {trace:false});
183 innerDeferredResult.collectResults({
184 'records': [
185 // MochiKit.Base.method(this.recordsData(), 'getObjectDataStore'),
186 // MochiKit.Base.methodcaller('values')
187 MochiKit.Base.method(this.recordsData(), 'values')
188 ],
189 'recordsStats': [
190 MochiKit.Base.method(this.recordsData(), 'getRemoteData'),
191 MochiKit.Base.itemgetter('recordsStats')
192 ],
193 'directLogins': [
194 // MochiKit.Base.method(this.directLoginsData(), 'getObjectDataStore'),
195 // MochiKit.Base.methodcaller('values')
196 MochiKit.Base.method(this.directLoginsData(), 'values')
197 ]
198 })
199 innerDeferredResult.addCallback(MochiKit.Base.bind(function (someData) {
200 var indexReference;
201 var recordsInvertedIndex;
202 var directLoginsInvertedIndex;
203
204 recordsInvertedIndex = Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.recordsIndex());
205 directLoginsInvertedIndex= Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.directLoginsIndex());
206
207 this._records = {};
208
209 for (indexReference in someData['records']) {
210 varrecord;
211 var reference;
212 var updateDate;
213
214 reference = recordsInvertedIndex[indexReference];
215
216 if (typeof(someData['recordsStats'][reference]) != 'undefined') {
217 updateDate = someData['recordsStats'][reference]['updateDate'];
218
219 record = new Clipperz.PM.DataModel.Record({
220 'reference': reference,
221 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'),
222 'retrieveRemoteDataFunction':this.retrieveRecordDetailFunction(),
223
224 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getRecordIndexData'),
225 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
226 'updateDate': updateDate,
227
228 'retrieveDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'),
229 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
230 'removeDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'removeDirectLoginIndexData'),
231
232 'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin')
233 });
234
235 this._records[reference] = record;
236 } else {
237Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference]));
238 //# skip the record, as it seems it is not present in the DB
239 //updateDate = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
240 }
241 }
242
243 for (indexReference in someData['directLogins']) {
244 // vardirectLogin;
245 var reference;
246 var record;
247
248 reference = directLoginsInvertedIndex[indexReference];
249 record = this._records[recordsInvertedIndex[someData['directLogins'][indexReference]['record']]];
250
251 if (record != null) {
252 // directLogin = new Clipperz.PM.DataModel.DirectLogin({
253 new Clipperz.PM.DataModel.DirectLogin({
254 'reference': reference,
255 'record': record
256 });
257 } else {
258 Clipperz.logWarning("WARNING: DIRECT LOGIN without a matching RECORD!!");
259 }
260 }
261
262 return this._records;
263 }, this));
264 innerDeferredResult.callback();
265 } else {
266 innerDeferredResult = MochiKit.Async.succeed(this._records);
267 }
268
269 return innerDeferredResult;
270 }, this));
271 deferredResult.releaseLock(this.lock());
272 deferredResult.callback();
273
274 return deferredResult;
275 },
276
277 //-------------------------------------------------------------------------
278
279 'updateRecordIndexForNewRecord': function (aNewRecord) {
280 var newRecordIndex;
281 var recordReference;
282
283 recordReference = aNewRecord.reference();
284 newRecordIndex = (MochiKit.Base.listMax(MochiKit.Base.map(MochiKit.Base.partial(MochiKit.Base.operator.mul, 1), MochiKit.Base.values(this.recordsIndex()))) + 1) + '';
285 this.recordsIndex()[recordReference] = newRecordIndex;
286
287 this.transientState().setValue('newlyCreatedRecordsIndex' + '.' + recordReference, newRecordIndex);
288 this.transientState().setValue('newlyCreatedRecordsReferences'+ '.' + recordReference, aNewRecord);
289 },
290
291 //.........................................................................
292
293 'createNewRecord': function () {
294 var deferredResult;
295 var newRecord;
296
297 newRecord = new Clipperz.PM.DataModel.Record({
298 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'),
299 'retrieveRemoteDataFunction':this.retrieveRecordDetailFunction(),
300
301 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getRecordIndexData'),
302 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
303 'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
304
305 'retrieveDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'),
306 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
307 'removeDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'removeDirectLoginIndexData'),
308
309 'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin')
310 });
311
312 this.transientState().setValue('newRecordsReferences' + '.' + newRecord.reference(), newRecord);
313 this.updateRecordIndexForNewRecord(newRecord);
314
315 deferredResult = Clipperz.Async.callbacks("User.Header.RecordIndex.createNewRecord", [
316 MochiKit.Base.method(this, 'records'),
317 MochiKit.Base.partial(Clipperz.Async.setItemOnObject, newRecord.reference(), newRecord),
318 MochiKit.Base.method(this, 'setRecordKey', newRecord.reference(), Clipperz.PM.Crypto.randomKey()),
319 MochiKit.Base.method(newRecord, 'setLabel', ''),
320 MochiKit.Base.partial(MochiKit.Async.succeed, newRecord)
321 ], {trace:false});
322
323
324 return deferredResult;
325 },
326
327 //-------------------------------------------------------------------------
328
329 'deleteRecord': function (aRecord) {
330 var deferredResult;
331 var recordReference;
332
333 recordReference = aRecord.reference();
334
335 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.deleteRecord", {trace:false});
336
337 deferredResult.addMethod(aRecord, 'directLogins');
338 deferredResult.addCallback(MochiKit.Base.values);
339 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeDirectLogin'));
340
341 deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]);
342 deferredResult.addCallback(MochiKit.Base.bind(function () {
343 this.transientState().setValue('deleteRecordsIndex' + '.' + recordReference, this.recordsIndex()[recordReference]);
344 delete this.recordsIndex()[recordReference];
345 }, this));
346
347 deferredResult.addMethod(this, 'records');
348 deferredResult.addCallback(MochiKit.Base.itemgetter(recordReference));
349 deferredResult.addMethod(this.transientState(), 'setValue', 'deleteRecordsReferences' + '.' + recordReference);
350
351 deferredResult.addMethod(this, 'records');
352 deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) {
353 delete someRecords[recordReference];
354 }, this));
355 deferredResult.callback();
356
357 return deferredResult;
358 },
359
360 //=========================================================================
361
362 'removeDirectLogin': function (aDirectLogin) {
363 this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLogin.reference()]);
364 },
365
366 //-------------------------------------------------------------------------
367
368 'createNewDirectLogin': function (aRecord) {
369 var newDirectLogin;
370 varnewDirectLoginIndexValue;
371
372 newDirectLogin = new Clipperz.PM.DataModel.DirectLogin({record:aRecord});
373 newDirectLoginIndexValue = MochiKit.Base.listMax(MochiKit.Base.map(function (aValue) { return aValue * 1; }, MochiKit.Base.values(this.directLoginsIndex()))) + 1;
374
375 this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin);
376
377 this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue;
378 this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]});
379
380 return newDirectLogin;
381 },
382
383 //=========================================================================
384
385 'deleteAllCleanTextData': function () {
386 return Clipperz.Async.callbacks("User.Header.RecordIndex.deleteAllCleanTextData", [
387 // MochiKit.Base.method(this, 'records'),
388 // MochiKit.Base.values,
389 // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
390
391 MochiKit.Base.method(this, 'recordsData'),
392 MochiKit.Base.methodcaller('deleteAllCleanTextData'),
393 MochiKit.Base.method(this, 'directLoginsData'),
394 MochiKit.Base.methodcaller('deleteAllCleanTextData')
395 ], {trace:false});
396 },
397
398 //-------------------------------------------------------------------------
399
400 'hasAnyCleanTextData': function () {
401 var deferredResult;
402
403 deferredResult = new Clipperz.Async.Deferred({trace:false});
404 deferredResult.collectResults({
405 'recordsData': [
406 MochiKit.Base.method(this, 'recordsData'),
407 MochiKit.Base.methodcaller('hasAnyCleanTextData')
408 ],
409 'directLoginsData':[
410 MochiKit.Base.method(this, 'directLoginsData'),
411 MochiKit.Base.methodcaller('hasAnyCleanTextData')
412 ],
413 // 'records': [
414 // MochiKit.Base.method(this, 'records'),
415 // MochiKit.Base.values,
416 // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
417 // Clipperz.Async.collectAll
418 // ]
419 });
420
421 // deferredResult.addCallback(MochiKit.Base.values);
422 // deferredResult.addCallback(MochiKit.Base.flattenArguments);
423 // deferredResult.addCallback(function(someValues) {
424 // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
425 // });
426 deferredResult.addCallback(Clipperz.Async.or);
427
428 deferredResult.callback();
429
430 return deferredResult;
431 },
432
433 //-------------------------------------------------------------------------
434
435 'hasPendingChanges': function () {
436 vardeferredResult;
437
438 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.hasPendingChanges", {trace:false});
439 deferredResult.collectResults({
440 'recordsData': [
441 MochiKit.Base.method(this, 'recordsData'),
442 MochiKit.Base.methodcaller('hasPendingChanges')
443 ],
444 'directLoginsData': [
445 MochiKit.Base.method(this, 'directLoginsData'),
446 MochiKit.Base.methodcaller('hasPendingChanges')
447 ]
448 });
449 deferredResult.addCallback(Clipperz.Async.or);
450 // deferredResult.addCallback(MochiKit.Base.values);
451 // deferredResult.addCallback(MochiKit.Base.flattenArguments);
452 // deferredResult.addCallback(function(someValues) {
453 // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
454 // });
455 deferredResult.callback();
456
457 return deferredResult;
458 },
459
460 //-------------------------------------------------------------------------
461
462 'commitTransientState': function () {
463 var deferredResult;
464
465 deferredResut = Clipperz.Async.callbacks("User.Header.RecordIndex.commitTransientState", [
466 MochiKit.Base.method(this, 'recordsData'),
467 MochiKit.Base.methodcaller('commitTransientState'),
468
469 MochiKit.Base.method(this, 'directLoginsData'),
470 MochiKit.Base.methodcaller('commitTransientState'),
471
472 MochiKit.Base.method(this, 'resetTransientState', true)
473 ], {trace:false});
474
475 return deferredResult;
476 },
477
478 //-------------------------------------------------------------------------
479
480 'revertChanges': function () {
481 return Clipperz.Async.callbacks("User.Header.RecordIndex.revertChanges", [
482 MochiKit.Base.method(this, 'recordsData'),
483 MochiKit.Base.methodcaller('revertChanges'),
484
485 // MochiKit.Base.method(this, 'directLoginsData'),
486 // MochiKit.Base.methodcaller('revertChanges'),
487
488 MochiKit.Base.method(this, 'records'),
489 MochiKit.Base.bind(function (someRecords) {
490 varrecordReference;
491
492 for (recordReference in this.transientState().getValue('deleteRecordsReferences')) {
493 this.recordsIndex()[recordReference] = this.transientState().getValue('deleteRecordsIndex' + '.' + recordReference);
494 someRecords[recordReference] = this.transientState().getValue('deleteRecordsReferences' + '.' + recordReference);
495 }
496
497 for (recordReference in this.transientState().getValue('newRecordsReferences')) {
498 delete this.recordsIndex()[recordReference];
499 delete someRecords[recordReference];
500 }
501 }, this),
502
503 // MochiKit.Base.method(this, 'directLogins'),
504 MochiKit.Base.bind(function () {
505 vardirectLoginReference;
506
507 //this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin);
508//
509 //this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue;
510 //this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]});
511
512
513 // for (directLoginReference in this.transientState().getValue('deleteDirectLoginReferences')) {
514 // someDirectLogins[directLoginReference] = this.transientState().getValue('deleteDirectLoginReferences' + '.' + recordReference);
515 // }
516
517 for (directLoginReference in this.transientState().getValue('newDirectLoginReferences')) {
518 // this.directLoginsData().removeValue(this.directLoginsIndex()[directLoginReference]);
519 delete this.directLoginsIndex()[directLoginReference];
520 }
521 }, this),
522
523 MochiKit.Base.method(this, 'directLoginsData'),
524 MochiKit.Base.methodcaller('revertChanges'),
525
526 MochiKit.Base.method(this, 'resetTransientState', false)
527 ], {trace:false});
528 },
529
530 //-------------------------------------------------------------------------
531
532 'prepareRemoteDataWithKey': function (aKey) {
533 // "records": {
534 // "index": {
535 // "eeda70e0392261967bda71c3764da78989c45bbd2bb7be6b941b90f81d9b81b5": "0",
536 // "13a5e52976337ab210903cd04872588e1b21fb72bc183e91aa25c494b8138551": "1",
537 // ...
538 // "465a067a0bd2b470fa834de5397e38494de0c7707938262fae3427932e219744": "18",
539 // "4fd1dc2ca860b7fb47cef10a84edb3270da05510b0a30a6b0b083898712d4b9e": "19"
540 // },
541 // "data": "n+AzGEEQXaSRSY4d ... BDypotrXgPo94uHfoXvGFzwCn8w="
542 // },
543 // "directLogins": {
544 // "index": {
545 // "61e87fdc4f1d9112e3b30c1f6812d095dcdb24f014c83319091eb6c9899ec348":"0",
546 // "989593d4c48929f0c8f1581aa96969c622807e99619ed4732026e967530a68ad":"1",
547 // ...
548 // "cb9ae0bba1957075ccdbfd3b3481704d62087687a2ac7c411a4f07d444bde0f7":"17",
549 // "7e1d069b7fa57c03bd7bf48807520feb953157834503aaff8c9d493f37dea69d":"18"
550 // },
551 // "data":"5YG9KKU/OZ5guUgFlms6k1 ... ZG/5Fn0uN+LoAsNfHm+EE62x"
552 // },
553
554 var deferredResult;
555 var result;
556
557 result = {};
558
559 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataWithKey", {trace:false});
560 deferredResult.collectResults({
561 'index':MochiKit.Base.partial(MochiKit.Async.succeed, this.recordsIndex()),
562 'data': [
563 MochiKit.Base.method(this.recordsData(), 'prepareRemoteDataWithKey', aKey),
564 MochiKit.Base.itemgetter('data')
565 ]
566 });
567 deferredResult.addCallback(Clipperz.Async.setItem, result, 'records');
568
569 deferredResult.collectResults({
570 'index':MochiKit.Base.partial(MochiKit.Async.succeed, this.directLoginsIndex()),
571 'data': [
572 MochiKit.Base.method(this.directLoginsData(), 'prepareRemoteDataWithKey', aKey),
573 MochiKit.Base.itemgetter('data')
574 ]
575 });
576 deferredResult.addCallback(Clipperz.Async.setItem, result, 'directLogins');
577
578 deferredResult.addCallback(MochiKit.Async.succeed, result);
579
580 deferredResult.callback();
581
582 return deferredResult;
583 },
584
585 //-------------------------------------------------------------------------
586
587 'updateRecordKeyAndPrepareRemoteData': function (aRecord) {
588 varnewRecordKey;
589 var deferredResult;
590
591 newRecordKey = Clipperz.PM.Crypto.randomKey();
592
593 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.updateRecordKeyAndPrepareRemoteData", {trace:false});
594 deferredResult.addCallback(MochiKit.Base.method(aRecord, 'prepareRemoteDataWithKey', newRecordKey));
595 deferredResult.addCallbackPass(MochiKit.Base.method(this, 'setRecordKey', aRecord.reference(), newRecordKey));
596 deferredResult.callback();
597
598 return deferredResult;
599 },
600
601 //.........................................................................
602
603 'removeNewRecordWithNoChanges': function (aRecord) {
604 var deferredResult;
605 var recordReference;
606
607 recordReference = aRecord.reference();
608
609 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.removeNewRecordWithNoChanges", {trace:false});
610
611 deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]);
612 deferredResult.addCallback(MochiKit.Base.bind(function () {
613 delete this.recordsIndex()[recordReference];
614 }, this));
615
616 deferredResult.addMethod(this, 'records');
617 deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) {
618 delete someRecords[recordReference];
619 }, this));
620 deferredResult.callback();
621
622 return deferredResult;
623 },
624
625 //.........................................................................
626
627 'prepareRemoteDataForChangedRecords': function () {
628 vardeferredResult;
629 varresult;
630
631 result = {};
632
633 deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataForChangedRecords", {trace:false});
634
635 deferredResult.addMethod(this, 'records');
636 deferredResult.addCallback(MochiKit.Base.values);
637 deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('isBrandNewWithNoPendingChanges'));
638 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeNewRecordWithNoChanges'));
639
640 deferredResult.addMethod(this, 'records');
641 deferredResult.addCallback(MochiKit.Base.values);
642 deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('hasPendingChanges'));
643 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'updateRecordKeyAndPrepareRemoteData'));
644 deferredResult.addCallback(Clipperz.Async.collectAll);
645
646 deferredResult.addCallback(Clipperz.Async.deferredIf("updated records != null", [
647 MochiKit.Base.operator.identity
648 ], [
649 MochiKit.Base.partial(MochiKit.Async.succeed, [])
650 ]));
651 deferredResult.addCallback(Clipperz.Async.setItem, result, 'updated');
652
653 deferredResult.addMethod(this.transientState(), 'getValue', 'deleteRecordsReferences');
654 deferredResult.addCallback(MochiKit.Base.keys);
655 deferredResult.addCallback(Clipperz.Async.deferredIf("deleted records != null", [
656 MochiKit.Base.operator.identity
657 ], [
658 MochiKit.Base.partial(MochiKit.Async.succeed, [])
659 ]));
660 deferredResult.addCallback(Clipperz.Async.setItem, result, 'deleted');
661
662 deferredResult.addCallback(MochiKit.Async.succeed, result);
663 deferredResult.callback();
664
665 return deferredResult;
666 },
667
668 //-------------------------------------------------------------------------
669 __syntaxFix__: "syntax fix"
670});
671
672
673
674Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex = function (anIndex) {
675 var result;
676 var key;
677
678 result = {};
679
680 for (key in anIndex) {
681 result[anIndex[key]] = key;
682 }
683
684 return result;
685}; \ No newline at end of file
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js
new file mode 100644
index 0000000..341e9f3
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js
@@ -0,0 +1,53 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.DataModel.User.Subscription depends on Clipperz.PM.DataModel.User!";
26}
27
28Clipperz.PM.DataModel.User.Subscription = function(args) {
29 this._attributes = args;
30 return this;
31}
32
33
34Clipperz.Base.extend(Clipperz.PM.DataModel.User.Subscription, Object, {
35
36 'features': function () {
37 return this._attributes['features'];
38 },
39
40 'type': function () {
41 return this._attributes['type'];
42 },
43
44 'validity': function () {
45 return {
46 'from':this._attributes['fromDate'],
47 'to':this._attributes['toDate']
48 };
49 },
50
51 //=========================================================================
52 __syntaxFix__: "syntax fix"
53});
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.js b/frontend/delta/js/Clipperz/PM/DataModel/User.js
new file mode 100644
index 0000000..1d90800
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.js
@@ -0,0 +1,827 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28
29//#############################################################################
30
31Clipperz.PM.DataModel.User = function (args) {
32 args = args || {};
33
34 Clipperz.PM.DataModel.User.superclass.constructor.apply(this, arguments);
35
36 this._username = args.username || null;
37 this._getPassphraseFunction = args.getPassphraseFunction || null;
38
39 this._data = null;
40
41 this._connection = null;
42 this._connectionVersion = 'current';
43
44 this._subscription = null;
45 this._serverData = null;
46 //this._serverLockValue = null;
47 this._transientState = null;
48
49 this._deferredLocks = {
50 'passphrase': new MochiKit.Async.DeferredLock(),
51 'serverData': new MochiKit.Async.DeferredLock(),
52 // 'recordsIndex': new MochiKit.Async.DeferredLock(),
53 // 'directLoginsIndex':new MochiKit.Async.DeferredLock()
54 // 'preferences': new MochiKit.Async.DeferredLock()
55 // 'oneTimePasswords': new MochiKit.Async.DeferredLock()
56 '__syntaxFix__': 'syntax fix'
57 };
58
59 return this;
60}
61
62Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
63
64 'toString': function () {
65 return "Clipperz.PM.DataModel.User - " + this.username();
66 },
67
68 //-------------------------------------------------------------------------
69
70 'username': function () {
71 return this._username;
72 },
73
74 'setUsername': function (aValue) {
75 this._username = aValue;
76 },
77
78 //-------------------------------------------------------------------------
79
80 //this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(someServerData['subscription']));
81 'subscription': function () {
82 return this._subscription;
83 },
84
85 'setSubscription': function (aValue) {
86 this._subscription = aValue;
87 },
88
89 //-------------------------------------------------------------------------
90
91 'displayName': function() {
92 return "" + this.username() + "";
93 },
94
95 //-------------------------------------------------------------------------
96
97 'data': function () {
98 if (this._data == null) {
99 this._data = new Clipperz.KeyValueObjectStore(/*{'name':'User.data [1]'}*/);
100 };
101
102 return this._data;
103 },
104
105 //-------------------------------------------------------------------------
106/*
107 'serverLockValue': function () {
108 return this._serverLockValue;
109 },
110
111 'setServerLockValue': function (aValue) {
112 this._serverLockValue = aValue;
113 },
114*/
115 //-------------------------------------------------------------------------
116
117 'transientState': function () {
118 if (this._transientState == null) {
119 this._transientState = {}
120 }
121
122 return this._transientState;
123 },
124
125 'resetTransientState': function (isCommitting) {
126 this._transientState = null;
127 },
128
129 //-------------------------------------------------------------------------
130
131 'deferredLockForSection': function(aSectionName) {
132 return this._deferredLocks[aSectionName];
133 },
134
135 //-------------------------------------------------------------------------
136
137 'getPassphrase': function() {
138 var deferredResult;
139
140 deferredResult = new Clipperz.Async.Deferred("User.getPassphrase", {trace:false});
141 deferredResult.acquireLock(this.deferredLockForSection('passphrase'));
142 deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', this.getPassphraseFunction());
143 deferredResult.releaseLock(this.deferredLockForSection('passphrase'));
144 deferredResult.callback();
145
146 return deferredResult;
147 },
148
149 'getPassphraseFunction': function () {
150 return this._getPassphraseFunction;
151 },
152
153 //-------------------------------------------------------------------------
154
155 'getCredentials': function () {
156 return Clipperz.Async.collectResults("User; get username and passphrase", {
157 'username': MochiKit.Base.method(this, 'username'),
158 'password': MochiKit.Base.method(this, 'getPassphrase')
159 }, {trace:false})();
160 },
161
162 //-------------------------------------------------------------------------
163
164 'changePassphrase': function (aNewValue) {
165 return this.updateCredentials(this.username(), aNewValue);
166 },
167
168 //.........................................................................
169
170 'updateCredentials': function (aUsername, aPassphrase) {
171 vardeferredResult;
172
173 deferredResult = new Clipperz.Async.Deferred("User.updateCredentials", {trace:false});
174 // deferredResult.addMethod(this, 'getPassphrase');
175 // deferredResult.setValue('currentPassphrase');
176 deferredResult.addMethod(this.connection(), 'ping');
177 deferredResult.addMethod(this, 'setUsername', aUsername)
178 deferredResult.acquireLock(this.deferredLockForSection('passphrase'));
179 deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', aPassphrase);
180 deferredResult.releaseLock(this.deferredLockForSection('passphrase'));
181 // deferredResult.getValue('currentPassphrase');
182 deferredResult.addMethod(this, 'prepareRemoteDataWithKey', aPassphrase);
183 deferredResult.addMethod(this.connection(), 'updateCredentials', aUsername, aPassphrase);
184 deferredResult.callback();
185
186 return deferredResult;
187 },
188
189 //-------------------------------------------------------------------------
190
191 'initialSetupWithNoData': function () {
192 this._serverData = {
193 'version': '0.1',
194 'statistics': "",
195 'header': {
196 'data': null,
197 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion,
198
199 'recordsIndex': new Clipperz.PM.DataModel.User.Header.RecordIndex({
200 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
201 'recordsData': {'data':null, 'index':{}},
202 'recordsStats': null,
203 'directLoginsData': {'data':null, 'index':{}},
204 'encryptedDataVersion': Clipperz.PM.Crypto.encryptingFunctions.currentVersion,
205 'retrieveRecordDetailFunction':MochiKit.Base.method(this, 'getRecordDetail')
206 }),
207 'preferences': new Clipperz.PM.DataModel.User.Header.Preferences({
208 'name':'preferences',
209 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
210 }),
211 'oneTimePasswords': new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
212 'name':'preferences',
213 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
214 })
215 }
216 };
217
218 // this._serverLockValue = Clipperz.PM.Crypto.randomKey();
219 },
220
221 //.........................................................................
222
223 'registerAsNewAccount': function () {
224 var deferredResult;
225
226 deferredResult = new Clipperz.Async.Deferred("User.registerAsNewAccount", {trace:false});
227 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
228 deferredResult.addMethod(this, 'initialSetupWithNoData')
229 deferredResult.addMethod(this, 'getPassphrase');
230 deferredResult.addMethod(this, 'prepareRemoteDataWithKey');
231 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
232 deferredResult.addMethod(this.connection(), 'register');
233 // deferredResult.addCallback(MochiKit.Base.itemgetter('lock'));
234 // deferredResult.addMethod(this, 'setServerLockValue');
235 // deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyRegistered');
236
237 // deferredResult.addErrback (MochiKit.Base.method(this, 'handleRegistrationFailure'));
238
239 deferredResult.callback();
240
241 return deferredResult;
242 },
243
244 //-------------------------------------------------------------------------
245
246 'login': function () {
247 var deferredResult;
248
249 deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false});
250 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
251 deferredResult.addMethod(this, 'getPassphrase');
252 deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue);
253 deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [
254 // MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}),
255 MochiKit.Base.method(this, 'getCredentials'),
256 MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'),
257 MochiKit.Base.method(this.data(), 'setValue', 'passphrase')
258 ], []));
259 deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase'));
260 deferredResult.addMethod(this.connection(), 'login', false);
261 deferredResult.addMethod(this, 'setupConnectionInfo');
262 // deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn');
263 deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback'));
264
265 deferredResult.callback();
266
267 return deferredResult;
268 },
269
270 //.........................................................................
271
272 'handleConnectionFallback': function(aValue) {
273 var result;
274
275//console.log("USER - handleConnectionFallback", aValue, aValue['isPermanent']);
276 if (aValue instanceof MochiKit.Async.CancelledError) {
277 result = aValue;
278 } else if ((aValue['isPermanent'] === true) || (Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()] == null)) {
279 result = Clipperz.Async.callbacks("User.handleConnectionFallback - failed", [
280 MochiKit.Base.method(this.data(), 'removeValue', 'passphrase'),
281 MochiKit.Base.method(this, 'setConnectionVersion', 'current'),
282 // MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userLoginFailed'),
283 // MochiKit.Base.partial(MochiKit.Async.fail, Clipperz.PM.DataModel.User.exception.LoginFailed)
284 MochiKit.Base.partial(MochiKit.Async.fail, aValue)
285 ], {trace:false});
286 } else {
287 this.setConnectionVersion(Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()]);
288 result = new Clipperz.Async.Deferred("User.handleConnectionFallback - retry");
289 result.addMethod(this, 'login');
290 result.callback();
291 }
292
293 return result;
294 },
295
296 //-------------------------------------------------------------------------
297
298 'setupConnectionInfo': function (aValue) {
299 // this.setLoginInfo(aValue['loginInfo']);
300 this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(aValue['subscription']));
301 },
302
303 //-------------------------------------------------------------------------
304
305 'lock': function () {
306 return Clipperz.Async.callbacks("User.lock", [
307 MochiKit.Base.method(this, 'deleteAllCleanTextData')
308 ], {trace:false});
309 },
310
311 //-------------------------------------------------------------------------
312
313 'logout': function () {
314 return Clipperz.Async.callbacks("User.logout", [
315 MochiKit.Base.method(this, 'deleteAllCleanTextData'),
316 MochiKit.Base.method(this.connection(), 'logout')
317 ], {trace:false});
318 },
319
320 //-------------------------------------------------------------------------
321
322 'headerFormatVersion': function(anHeader) {
323 var result;
324
325 if (anHeader.charAt(0) == '{') {
326 varheaderData;
327
328 headerData = Clipperz.Base.evalJSON(anHeader);
329 result = headerData['version'];
330 } else {
331 result = 'LEGACY';
332 }
333
334 return result;
335 },
336
337 //-------------------------------------------------------------------------
338
339 'unpackServerData': function (someServerData) {
340 var unpackedData;
341 var headerVersion;
342
343 varrecordsIndex;
344 var preferences;
345 var oneTimePasswords;
346
347 // this.setServerLockValue(someServerData['lock']);
348
349 headerVersion = this.headerFormatVersion(someServerData['header']);
350 switch (headerVersion) {
351 case 'LEGACY':
352 varlegacyHeader;
353
354 legacyHeader = new Clipperz.PM.DataModel.User.Header.Legacy({
355 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
356 'remoteData': {
357 'data': someServerData['header'],
358 'version': someServerData['version'],
359 'recordsStats': someServerData['recordsStats']
360 },
361 // 'encryptedDataKeypath': 'data',
362 // 'encryptedVersionKeypath': 'version',
363 'retrieveRecordDetailFunction':MochiKit.Base.method(this, 'getRecordDetail')
364 });
365
366 recordsIndex = legacyHeader;
367 preferences = legacyHeader;
368 oneTimePasswords= legacyHeader;
369 break;
370 case '0.1':
371 varheaderData;
372
373 headerData = Clipperz.Base.evalJSON(someServerData['header']);
374
375 recordsIndex = new Clipperz.PM.DataModel.User.Header.RecordIndex({
376 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
377 'recordsData': headerData['records'],
378 'recordsStats': someServerData['recordsStats'],
379 'directLoginsData': headerData['directLogins'],
380 'encryptedDataVersion': someServerData['version'],
381 'retrieveRecordDetailFunction':MochiKit.Base.method(this, 'getRecordDetail')
382 });
383
384 //Still missing a test case that actually fais with the old version of the code, where the check for undefined was missing
385 if (typeof(headerData['preferences']) != 'undefined') {
386 preferences= new Clipperz.PM.DataModel.User.Header.Preferences({
387 'name':'preferences',
388 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
389 'remoteData': {
390 'data': headerData['preferences']['data'],
391 'version': someServerData['version']
392 }
393 });
394 } else {
395 preferences= new Clipperz.PM.DataModel.User.Header.Preferences({
396 'name':'preferences',
397 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
398 });
399 }
400
401 if (typeof(headerData['oneTimePasswords']) != 'undefined') {
402 oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
403 'name':'preferences',
404 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
405 'remoteData': {
406 'data': headerData['oneTimePasswords']['data'],
407 'version': someServerData['version']
408 }
409 });
410 } else {
411 oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
412 'name':'preferences',
413 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
414 });
415 }
416
417 break;
418 }
419
420 unpackedData = {
421 'version': someServerData['version'],
422 'statistics': someServerData['statistics'],
423 'header': {
424 'data': someServerData['header'],
425 'version': headerVersion,
426
427 'recordsIndex': recordsIndex,
428 'preferences': preferences,
429 'oneTimePasswords': oneTimePasswords
430 }
431 };
432
433 this._serverData = unpackedData;
434
435 return this._serverData;
436 },
437
438 //-------------------------------------------------------------------------
439
440 'getServerData': function() {
441 var deferredResult;
442
443 deferredResult = new Clipperz.Async.Deferred("User.getServerData", {trace:false});
444 deferredResult.acquireLock(this.deferredLockForSection('serverData'));
445 deferredResult.addCallback(MochiKit.Base.bind(function(aResult) {
446 var innerDeferredResult;
447
448 innerDeferredResult = new Clipperz.Async.Deferred("User.getUserDetails.innerDeferred", {trace:false});
449 if (this._serverData == null) {
450 innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadingUserDetails');
451 innerDeferredResult.addMethod(this.connection(), 'message', 'getUserDetails');
452 innerDeferredResult.addMethod(this, 'unpackServerData');
453 innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadedUserDetails');
454 }
455
456 innerDeferredResult.addCallback(MochiKit.Base.bind(function () {
457 return this._serverData;
458 },this));
459 innerDeferredResult.callback();
460
461 return innerDeferredResult;
462 }, this));
463 deferredResult.releaseLock(this.deferredLockForSection('serverData'));
464 deferredResult.callback();
465
466 return deferredResult;
467 },
468
469 //-------------------------------------------------------------------------
470
471 'connectionVersion': function() {
472 return this._connectionVersion;
473 },
474
475 'setConnectionVersion': function(aValue) {
476 if (this._connectionVersion != aValue) {
477 this.resetConnection();
478 }
479 this._connectionVersion = aValue;
480 },
481
482 //-------------------------------------------------------------------------
483
484 'connection': function() {
485 if ((this._connection == null) && (this.connectionVersion() != null) ){
486 this._connection = new Clipperz.PM.Connection.communicationProtocol.versions[this.connectionVersion()]({
487 getCredentialsFunction: MochiKit.Base.method(this, 'getCredentials')
488 });
489 }
490
491 return this._connection;
492 },
493
494 'resetConnection': function(aValue) {
495 if (this._connection != null) {
496 this._connection.reset();
497 }
498
499 this._connection = null;
500 },
501
502 //=========================================================================
503
504 'getHeaderIndex': function (aKey) {
505 return Clipperz.Async.callbacks("User.getHeaderIndex", [
506 MochiKit.Base.method(this, 'getServerData'),
507 MochiKit.Base.itemgetter('header'),
508 MochiKit.Base.itemgetter(aKey)
509 ], {trace:false})
510 },
511
512 //=========================================================================
513
514 'getRecords': function () {
515 return Clipperz.Async.callbacks("User.getRecords", [
516 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
517 MochiKit.Base.methodcaller('records'),
518 MochiKit.Base.values
519 ], {trace:false});
520 },
521
522 'recordWithLabel': function (aLabel) {
523 return Clipperz.Async.callbacks("User.recordWithLabel", [
524 MochiKit.Base.method(this, 'getRecords'),
525 MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aRecord) {
526 return Clipperz.Async.callbacks("User.recordWithLabel - check record label", [
527 MochiKit.Base.methodcaller('label'),
528 MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel)
529 ], {trace:false}, aRecord);
530 }),
531 function (someFilteredResults) {
532 var result;
533
534 switch (someFilteredResults.length) {
535 case 0:
536 result = null;
537 break;
538 case 1:
539 result = someFilteredResults[0];
540 break;
541 default:
542 WTF = TODO;
543 break;
544 }
545
546 return result;
547 }
548 ], {trace:false});
549 },
550
551 //-------------------------------------------------------------------------
552
553 'getRecord': function (aRecordReference) {
554 return Clipperz.Async.callbacks("User.getRecord", [
555 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
556 MochiKit.Base.methodcaller('records'),
557 MochiKit.Base.itemgetter(aRecordReference),
558
559 Clipperz.Async.deferredIf("record != null", [
560 MochiKit.Base.operator.identity
561 ], [
562 function () { throw "Record does not exists"}
563 ])
564 ], {trace:false});
565 },
566
567 //-------------------------------------------------------------------------
568
569 'getRecordDetail': function (aRecordReference) {
570 return this.connection().message('getRecordDetail', {reference: aRecordReference});
571 },
572
573 //-------------------------------------------------------------------------
574
575 'deleteRecord': function (aRecord) {
576 return Clipperz.Async.callbacks("User.deleteRecord", [
577 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
578 MochiKit.Base.methodcaller('deleteRecord', aRecord)
579 ], {trace:false});
580 },
581
582 //-------------------------------------------------------------------------
583
584 'createNewRecord': function () {
585 return Clipperz.Async.callbacks("User.createNewRecord", [
586 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
587 MochiKit.Base.methodcaller('createNewRecord')
588 ], {trace:false});
589 },
590
591 //=========================================================================
592
593 'getDirectLogins': function() {
594 var deferredResult;
595
596 deferredResult = new Clipperz.Async.Deferred("User.getDirectLogins", {trace:false});
597 deferredResult.addMethod(this, 'getRecords');
598 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.compose(MochiKit.Base.values, MochiKit.Base.methodcaller('directLogins')));
599 deferredResult.addCallback(MochiKit.Base.flattenArray);
600 deferredResult.callback();
601
602 return deferredResult;
603 },
604
605 //=========================================================================
606
607 'getOneTimePasswords': function () {
608 return Clipperz.Async.callbacks("User.getOneTimePasswords", [
609 MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'),
610 MochiKit.Base.methodcaller('oneTimePasswords'),
611 MochiKit.Base.values
612 ], {trace:false});
613 },
614
615 //=========================================================================
616
617 'invokeMethodNamedOnHeader': function (aMethodName, aValue) {
618 return Clipperz.Async.collectResults("User.invokeMethodNamedOnHeader [" + aMethodName + "]", {
619 'recordIndex': [
620 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
621 MochiKit.Base.methodcaller(aMethodName, aValue)
622 ],
623 'preferences': [
624 MochiKit.Base.method(this, 'getHeaderIndex', 'preferences'),
625 MochiKit.Base.methodcaller(aMethodName, aValue)
626 ],
627 'oneTimePasswords': [
628 MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'),
629 MochiKit.Base.methodcaller(aMethodName, aValue)
630 ]//,
631 // 'statistics': [
632 // MochiKit.Base.method(this, 'getStatistics'),
633 // MochiKit.Base.methodcaller(aMethodName, aValue)
634 // ]
635 }, {trace:false})();
636 },
637
638 //-------------------------------------------------------------------------
639
640 'invokeMethodNamedOnRecords': function (aMethodName, aValue) {
641 return Clipperz.Async.callbacks("User.invokeMethodNamedOnRecords[" + aMethodName + "]", [
642 MochiKit.Base.method(this, 'getRecords'),
643 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller(aMethodName, aValue)),
644 Clipperz.Async.collectAll
645 ], {trace:false});
646 },
647
648 //=========================================================================
649
650 'hasPendingChanges': function () {
651 vardeferredResult;
652
653 deferredResult = new Clipperz.Async.Deferred("User.hasPendingChanges", {trace:false});
654 deferredResult.collectResults({
655 'header': [
656 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasPendingChanges'),
657 MochiKit.Base.values
658 ],
659 'records': MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasPendingChanges')
660 });
661 deferredResult.addCallback(Clipperz.Async.or);
662 deferredResult.callback();
663 // recordsIndex = legacyHeader;
664 // preferences = legacyHeader;
665 // oneTimePasswords= legacyHeader;
666
667 return deferredResult;
668 },
669
670 //=========================================================================
671
672 'commitTransientState': function () {
673 return Clipperz.Async.callbacks("User.commitTransientState", [
674 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'commitTransientState'),
675 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'commitTransientState'),
676
677 MochiKit.Base.method(this, 'transientState'),
678 // MochiKit.Base.itemgetter('lock'),
679 // MochiKit.Base.method(this, 'setServerLockValue'),
680 MochiKit.Base.method(this, 'resetTransientState', true)
681 ], {trace:false});
682 },
683
684 //-------------------------------------------------------------------------
685
686 'revertChanges': function () {
687 return Clipperz.Async.callbacks("User.revertChanges", [
688 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'),
689 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'),
690 MochiKit.Base.method(this, 'resetTransientState', false)
691 ], {trace:false});
692 },
693
694 //=========================================================================
695
696 'deleteAllCleanTextData': function () {
697 return Clipperz.Async.callbacks("User.deleteAllCleanTextData", [
698 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'deleteAllCleanTextData'),
699 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'deleteAllCleanTextData'),
700
701 MochiKit.Base.method(this.data(), 'removeAllData'),
702 MochiKit.Base.method(this, 'resetTransientState', false)
703 ], {trace:false});
704 },
705
706 //-------------------------------------------------------------------------
707
708 'hasAnyCleanTextData': function () {
709 vardeferredResult;
710
711 deferredResult = new Clipperz.Async.Deferred("User.hasAnyCleanTextData", {trace:false});
712 deferredResult.collectResults({
713 'header':[
714 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasAnyCleanTextData'),
715 MochiKit.Base.values
716 ],
717 'records':MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasAnyCleanTextData'),
718 'data': MochiKit.Base.bind(function () {
719 return MochiKit.Async.succeed(! this.data().isEmpty());
720 }, this),
721 'transientState':MochiKit.Base.bind(function () {
722 return MochiKit.Async.succeed(MochiKit.Base.keys(this.transientState()).length != 0);
723 }, this)
724 });
725 deferredResult.addCallback(Clipperz.Async.or);
726 deferredResult.callback();
727
728 return deferredResult;
729 },
730
731 //=========================================================================
732
733 'prepareRemoteDataWithKey': function (aKey /*, aCurrentKey*/) {
734 var deferredResult;
735 varresult;
736
737 result = {};
738 deferredResult = new Clipperz.Async.Deferred("User.prepareRemoteDataWithKey", {trace:false});
739 deferredResult.addMethod(this, 'invokeMethodNamedOnHeader', 'prepareRemoteDataWithKey', aKey /*, aCurrentKey*/);
740 deferredResult.addCallback(MochiKit.Base.bind(function (aResult, someHeaderPackedData) {
741 var header;
742
743 header = {};
744 header['records'] = someHeaderPackedData['recordIndex']['records'];
745 header['directLogins'] = someHeaderPackedData['recordIndex']['directLogins'];
746 header['preferences'] = {'data': someHeaderPackedData['preferences']['data']};
747 header['oneTimePasswords']= {'data': someHeaderPackedData['oneTimePasswords']['data']};
748 header['version'] = '0.1';
749
750 aResult['header'] = Clipperz.Base.serializeJSON(header);
751 aResult['statistics'] = this._serverData['statistics']; //"someHeaderPackedData['statistics']['data']";
752
753 return aResult;
754 }, this), result);
755 deferredResult.addCallback(Clipperz.Async.setItem, result, 'version', Clipperz.PM.Crypto.encryptingFunctions.currentVersion);
756 // deferredResult.addCallback(Clipperz.Async.setItem, result, 'lock', this.serverLockValue());
757 deferredResult.callback();
758
759 return deferredResult;
760 },
761
762 //=========================================================================
763
764 'saveChanges': function () {
765 vardeferredResult;
766 var messageParameters;
767
768 messageParameters = {};
769
770 deferredResult = new Clipperz.Async.Deferred("User.saveChangaes", {trace:false});
771
772 deferredResult.addMethod(this, 'getHeaderIndex', 'recordsIndex');
773 deferredResult.addCallback(MochiKit.Base.methodcaller('prepareRemoteDataForChangedRecords'));
774 deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'records');
775 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
776
777 deferredResult.addMethod(this, 'getPassphrase');
778 deferredResult.addMethod(this, 'prepareRemoteDataWithKey');
779 deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'user');
780 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
781
782 deferredResult.addCallback(MochiKit.Async.succeed, messageParameters);
783 deferredResult.addMethod(this.connection(), 'message', 'saveChanges');
784 deferredResult.addCallback(MochiKit.Base.update, this.transientState())
785 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
786
787 deferredResult.addMethod(this, 'commitTransientState');
788 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
789 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userDataSuccessfullySaved');
790
791 deferredResult.addErrbackPass(MochiKit.Base.method(this, 'revertChanges'));
792 // deferredResult.addErrbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'failureWhileSavingUserData');
793
794 deferredResult.callback();
795
796 return deferredResult;
797 },
798
799 //=========================================================================
800 __syntaxFix__: "syntax fix"
801});
802
803//-----------------------------------------------------------------------------
804
805Clipperz.PM.DataModel.User.registerNewAccount = function (anUsername, aPassphraseFunction) {
806 vardeferredResult;
807 var user;
808
809 user = new Clipperz.PM.DataModel.User({'username':anUsername, 'getPassphraseFunction':aPassphraseFunction});
810
811 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.User.registerNewAccount", {trace:false});
812 deferredResult.addMethod(user, 'registerAsNewAccount');
813 deferredResult.addMethod(user, 'login');
814 deferredResult.addCallback(MochiKit.Async.succeed, user);
815 deferredResult.callback();
816
817 return deferredResult;
818}
819
820//-----------------------------------------------------------------------------
821
822Clipperz.PM.DataModel.User.exception = {
823 LoginFailed: new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.LoginFailed"),
824 CredentialUpgradeFailed:new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed")
825};
826
827//-----------------------------------------------------------------------------
diff --git a/frontend/delta/js/Clipperz/PM/Date.js b/frontend/delta/js/Clipperz/PM/Date.js
new file mode 100644
index 0000000..a62857e
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Date.js
@@ -0,0 +1,196 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.Date) == 'undefined') { Clipperz.PM.Date = {}; }
27
28Clipperz.PM.Date.VERSION = "0.1";
29Clipperz.PM.Date.NAME = "Clipperz.PM.Date";
30
31MochiKit.Base.update(Clipperz.PM.Date, {
32
33 '__repr__': function () {
34 return "[" + this.NAME + " " + this.VERSION + "]";
35 },
36
37 //-------------------------------------------------------------------------
38
39 'toString': function () {
40 return this.__repr__();
41 },
42
43 //-------------------------------------------------------------------------
44
45 'locale': function() {
46 return {
47 'amDesignation':Clipperz.PM.Strings.getValue('calendarStrings.amDesignation'),
48 'pmDesignation':Clipperz.PM.Strings.getValue('calendarStrings.pmDesignation'),
49 'days': Clipperz.PM.Strings.getValue('calendarStrings.days'),
50 'shortDays': Clipperz.PM.Strings.getValue('calendarStrings.shortDays'),
51 'shortMonths': Clipperz.PM.Strings.getValue('calendarStrings.shortMonths'),
52 'months': Clipperz.PM.Strings.getValue('calendarStrings.months')
53 }
54 },
55
56 //=========================================================================
57/*
58 'formatDateWithPHPLikeTemplate': function(aDate, aTemplate) {
59 return Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
60 },
61
62 'parseDateWithPHPLikeTemplate': function(aDate, aTemplate) {
63 return Clipperz.Date.parseDateWithPHPTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
64 },
65
66 //=========================================================================
67
68 'formatDateWithJavaLikeTemplate': function(aDate, aTemplate) {
69 return Clipperz.Date.formatDateWithJavaLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
70 },
71
72 'parseDateWithJavaLikeTemplate': function(aDate, aTemplate) {
73 return Clipperz.Date.parseDateWithJavaLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
74 },
75*/
76 //=========================================================================
77
78 'formatWithTemplate': function (aTemplate, aDate) {
79 return Clipperz.PM.Date.formatDateWithTemplate(aDate, aTemplate);
80 },
81
82 'formatDateWithTemplate': function(aDate, aTemplate) {
83 var result;
84
85 if (aDate == null) {
86 result = ""
87 } else {
88 result = Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
89 };
90
91 return result;
92 },
93
94 'parseDateWithTemplate': function(aValue, aTemplate) {
95 return Clipperz.Date.parseDateWithPHPTemplateAndLocale(aValue, aTemplate, Clipperz.PM.Date.locale());
96 },
97
98 //=========================================================================
99
100 'formatDateWithUTCFormat': function(aDate) {
101 return Clipperz.Date.formatDateWithUTCFormatAndLocale(aDate, Clipperz.PM.Date.locale());
102 },
103
104 'parseDateWithUTCFormat': function(aValue) {
105 var result;
106
107 if (aValue == null) {
108 result = null;
109 } else {
110 result = Clipperz.Date.parseDateWithUTCFormatAndLocale(aValue, Clipperz.PM.Date.locale());
111 }
112
113 return result;
114 },
115
116 //=========================================================================
117
118 'getElapsedTimeDescription': function(aDate) {
119 var result;
120
121 result = ""
122
123 if (aDate != null) {
124 var now;
125 var elapsedTime;
126
127 var millisencondsInAMinute;
128 var millisencondsInAnHour;
129 var millisencondsInADay;
130 var millisencondsInAWeek;
131 var millisencondsInAMonth;
132
133 now = new Date();
134 elapsedTime = now.getTime() - aDate.getTime();
135
136 millisencondsInAMinute = 60 * 1000;
137 millisencondsInAnHour = millisencondsInAMinute * 60;
138 millisencondsInADay = millisencondsInAnHour * 24;
139 millisencondsInAWeek = millisencondsInADay * 7;
140 millisencondsInAMonth = millisencondsInAWeek * 5;
141
142 if ((elapsedTime / millisencondsInAMonth) > 1) {
143 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.MORE_THAN_A_MONTH_AGO');
144 } else if ((elapsedTime / millisencondsInAWeek) > 1) {
145 var elapsedWeeks;
146
147 elapsedWeeks = Math.floor((elapsedTime / millisencondsInAWeek));
148 if (elapsedWeeks == 1) {
149 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.MORE_THAN_A_WEEK_AGO');
150 } else {
151 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.MORE_THAN_*_WEEKS_AGO').replace(/__elapsed__/, elapsedWeeks);
152 }
153 } else if ((elapsedTime / millisencondsInADay) > 1) {
154 var elapsedDays;
155
156 elapsedDays = Math.floor((elapsedTime / millisencondsInADay));
157 if (elapsedDays == 1) {
158 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.YESTERDAY');
159 } else {
160 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.*_DAYS_AGO').replace(/__elapsed__/, elapsedDays);
161 }
162 } else if ((elapsedTime / millisencondsInAnHour) > 1) {
163 var elapsedHours;
164
165 elapsedHours = Math.floor((elapsedTime / millisencondsInAnHour));
166 if (elapsedHours == 1) {
167 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.ABOUT_AN_HOUR_AGO');
168 } else {
169 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.*_HOURS_AGO').replace(/__elapsed__/, elapsedHours);
170 }
171 } else {
172 var elapsed10Minutes;
173
174 elapsed10Minutes = (Math.floor((elapsedTime / millisencondsInAMinute) / 10)) * 10;
175 if (elapsed10Minutes == 0) {
176 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.JUST_A_FEW_MINUTES_AGO');
177 } else {
178 result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.ABOUT_*_MINUTES_AGO').replace(/__elapsed__/, elapsed10Minutes+"");
179 }
180 }
181 }
182
183 return result;
184 },
185
186 //-------------------------------------------------------------------------
187
188 'parse': function (aValue) {
189 return Clipperz.PM.Date.parseDateWithUTCFormat(aValue);
190 },
191
192 //-------------------------------------------------------------------------
193 __syntaxFix__: "syntax fix"
194
195});
196
diff --git a/frontend/delta/js/Clipperz/PM/PIN.js b/frontend/delta/js/Clipperz/PM/PIN.js
new file mode 100644
index 0000000..a32889a
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/PIN.js
@@ -0,0 +1,132 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.PIN) == 'undefined') { Clipperz.PM.PIN = {}; }
27
28MochiKit.Base.update(Clipperz.PM.PIN, {
29
30 //-------------------------------------------------------------------------
31
32 '__repr__': function () {
33 return "[" + this.NAME + " " + this.VERSION + "]";
34 },
35
36 //-------------------------------------------------------------------------
37
38 'toString': function () {
39 return this.__repr__();
40 },
41
42 'CREDENTIALS': 'CLIPPERZ.CREDENTIALS',
43 'FAILURE_COUNT': 'CLIPPERZ.FAILED_LOGIN_COUNT',
44 'ALLOWED_RETRY': 3,
45
46 //-------------------------------------------------------------------------
47
48 'isSet': function () {
49 return (this.storedCredentials() != null);
50 },
51
52 'storedCredentials': function () {
53 return localStorage[this.CREDENTIALS];
54 },
55
56 //-------------------------------------------------------------------------
57
58 'recordFailedAttempt': function () {
59 varfailureCount;
60 varresult;
61
62 failureCount = localStorage[this.FAILURE_COUNT];
63
64 if (failureCount == null) {
65 failureCount = 0
66 }
67
68 failureCount ++;
69
70 if (failureCount < this.ALLOWED_RETRY) {
71 localStorage[this.FAILURE_COUNT] = failureCount;
72 result = failureCount;
73 } else {
74 this.removeLocalCredentials();
75 result = -1;
76 }
77
78 return result;
79 },
80
81 'resetFailedAttemptCount': function () {
82 localStorage.removeItem(this.FAILURE_COUNT);
83 },
84
85 'failureCount': function () {
86 return localStorage[this.FAILURE_COUNT];
87 },
88
89 //-------------------------------------------------------------------------
90
91 'deriveKeyFromPin': function (aPIN) {
92 return Clipperz.Crypto.SHA.sha256(new Clipperz.ByteArray(aPIN));
93 },
94
95 'credentialsWithPIN': function (aPIN) {
96 varbyteArrayValue;
97 var decryptedValue;
98 varresult;
99
100 byteArrayValue = (new Clipperz.ByteArray()).appendBase64String(localStorage[this.CREDENTIALS]);
101 decryptedValue = Clipperz.Crypto.AES.decrypt(this.deriveKeyFromPin(aPIN), byteArrayValue).asString();
102 try {
103 result = Clipperz.Base.evalJSON(decryptedValue);
104 } catch (error) {
105 result = {'username':'fakeusername', 'passphrase':'fakepassphrase'};
106 }
107
108 return result;
109 },
110
111 'setCredentialsWithPIN': function (aPIN, someCredentials) {
112 varencodedValue;
113 varbyteArrayValue;
114 var encryptedValue;
115
116 encodedValue = Clipperz.Base.serializeJSON(someCredentials);
117 byteArrayValue = new Clipperz.ByteArray(encodedValue);
118 encryptedValue = Clipperz.Crypto.AES.encrypt(this.deriveKeyFromPin(aPIN), byteArrayValue).toBase64String();
119
120 localStorage[this.CREDENTIALS] = encryptedValue;
121 },
122
123 'removeLocalCredentials': function () {
124 localStorage.removeItem(this.CREDENTIALS);
125 localStorage.removeItem(this.FAILURE_COUNT);
126 },
127
128 //-------------------------------------------------------------------------
129 __syntaxFix__: "syntax fix"
130
131});
132
diff --git a/frontend/delta/js/Clipperz/PM/Proxy.js b/frontend/delta/js/Clipperz/PM/Proxy.js
new file mode 100644
index 0000000..2ac684a
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy.js
@@ -0,0 +1,186 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26
27//=============================================================================
28
29Clipperz.PM.Proxy = function(args) {
30 args = args || {};
31
32 this._shouldPayTolls = args.shouldPayTolls || false;
33
34 this._tolls = {
35 'CONNECT':[],
36 'REGISTER':[],
37 'MESSAGE':[]
38 };
39
40 if (args.isDefault === true) {
41 Clipperz.PM.Proxy.defaultProxy = this;
42 }
43
44 return this;
45}
46
47Clipperz.PM.Proxy.prototype = MochiKit.Base.update(null, {
48
49 'toString': function() {
50 return "Clipperz.PM.Proxy";
51 },
52
53 //=========================================================================
54
55 'shouldPayTolls': function() {
56 return this._shouldPayTolls;
57 },
58
59 //-------------------------------------------------------------------------
60
61 'tolls': function() {
62 return this._tolls;
63 },
64
65 //-------------------------------------------------------------------------
66
67 'payToll': function(aRequestType, someParameters) {
68 vardeferredResult;
69
70 if (this.shouldPayTolls()) {
71 deferredResult = new Clipperz.Async.Deferred("Proxy.payToll", {trace:false});
72
73 if (this.tolls()[aRequestType].length == 0) {
74 deferredResult.addMethod(this, 'sendMessage', 'knock', {requestType:aRequestType});
75 deferredResult.addMethod(this, 'setTollCallback');
76 }
77 deferredResult.addMethod(this.tolls()[aRequestType], 'pop');
78 deferredResult.addCallback(MochiKit.Base.methodcaller('deferredPay'));
79 deferredResult.addCallback(function(aToll) {
80 var result;
81
82 result = {
83 parameters: someParameters,
84 toll: aToll
85 }
86
87 return result;
88 });
89
90 deferredResult.callback();
91 } else {
92 deferredResult = MochiKit.Async.succeed({parameters:someParameters});
93 }
94
95 return deferredResult;
96 },
97
98 //-------------------------------------------------------------------------
99
100 'addToll': function(aToll) {
101 this.tolls()[aToll.requestType()].push(aToll);
102 },
103
104 //=========================================================================
105
106 'setTollCallback': function(someParameters) {
107 if (typeof(someParameters['toll']) != 'undefined') {
108 this.addToll(new Clipperz.PM.Toll(someParameters['toll']));
109 }
110
111 return someParameters['result'];
112 },
113
114 //=========================================================================
115
116 'registration': function (someParameters) {
117 return this.processMessage('registration', someParameters, 'REGISTER');
118 },
119
120 'handshake': function (someParameters) {
121 return this.processMessage('handshake', someParameters, 'CONNECT');
122 },
123
124 'message': function (someParameters) {
125 return this.processMessage('message', someParameters, 'MESSAGE');
126 },
127
128 'logout': function (someParameters) {
129 return this.processMessage('logout', someParameters, 'MESSAGE');
130 },
131
132 //=========================================================================
133
134 'processMessage': function (aFunctionName, someParameters, aRequestType) {
135 vardeferredResult;
136
137 deferredResult = new Clipperz.Async.Deferred("Proxy.processMessage", {trace:false});
138 deferredResult.addMethod(this, 'payToll', aRequestType);
139 deferredResult.addMethod(this, 'sendMessage', aFunctionName);
140 deferredResult.addMethod(this, 'setTollCallback');
141 deferredResult.callback(someParameters);
142
143 return deferredResult;
144 },
145
146 //=========================================================================
147
148 '_sendMessage': function (aFunctionName, aVersion, someParameters) {
149 throw Clipperz.Base.exception.AbstractMethod;
150 },
151
152 'sendMessage': function (aFunctionName, someParameters) {
153 var deferredResult;
154
155 //TODO: read actual application version for a property set at build time
156 deferredResult = new Clipperz.Async.Deferred("Proxy.sendMessage", {trace:false});
157 deferredResult.addMethod(this, '_sendMessage', aFunctionName, 'fake-app-version');
158 deferredResult.addErrback(MochiKit.Base.method(this, 'handleError'));
159 deferredResult.callback(someParameters);
160
161 return deferredResult;
162 },
163
164 //-------------------------------------------------------------------------
165
166 'handleError': function (anError) {
167 if (anError['message'] == 'Wrong application version') {
168 anError['isPermanent'] = true;
169 }
170 return anError;
171 },
172
173 //=========================================================================
174
175 'isReadOnly': function () {
176 return false;
177 },
178
179 'canRegisterNewUsers': function () {
180 return true;
181 },
182
183 //=========================================================================
184 __syntaxFix__: "syntax fix"
185
186});
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
new file mode 100755
index 0000000..1638d99
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
@@ -0,0 +1,86 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26
27//=============================================================================
28
29Clipperz.PM.Proxy.JSON = function(args) {
30 Clipperz.PM.Proxy.JSON.superclass.constructor.call(this, args);
31
32 this._url = args.url || Clipperz.Base.exception.raise('MandatoryParameter');
33
34 return this;
35}
36
37Clipperz.Base.extend(Clipperz.PM.Proxy.JSON, Clipperz.PM.Proxy, {
38
39 'toString': function() {
40 return "Clipperz.PM.Proxy.JSON";
41 },
42
43 //=========================================================================
44
45 'url': function () {
46 return this._url;
47 },
48
49 //=========================================================================
50
51 '_sendMessage': function(aFunctionName, aVersion, someParameters) {
52 vardeferredResult;
53 var parameters;
54
55 parameters = {
56 method: aFunctionName,
57 version: aVersion,
58 parameters: Clipperz.Base.serializeJSON(someParameters)
59 };
60
61 deferredResult = new Clipperz.Async.Deferred("Proxy.JSON.sendMessage", {trace:false});
62 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestSent');
63 deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), {
64 method:'POST',
65 sendContent:MochiKit.Base.queryString(parameters),
66 headers:{"Content-Type":"application/x-www-form-urlencoded"}
67 });
68 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestReceived');
69 deferredResult.addCallback(MochiKit.Base.itemgetter('responseText'));
70 deferredResult.addCallback(Clipperz.Base.evalJSON);
71 deferredResult.addCallback(function (someValues) {
72 if (someValues['result'] == 'EXCEPTION') {
73 throw someValues['message'];
74 }
75
76 return someValues;
77 })
78 deferredResult.callback();
79
80 return deferredResult;
81 },
82
83 //=========================================================================
84 __syntaxFix__: "syntax fix"
85
86});
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
new file mode 100644
index 0000000..5711742
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
@@ -0,0 +1,793 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.Proxy.Offline) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.Proxy.Offline.DataStore depends on Clipperz.PM.Proxy.Offline!";
26}
27
28//=============================================================================
29
30Clipperz.PM.Proxy.Offline.DataStore = function(args) {
31 args = args || {};
32
33 this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
34 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
35 this._shouldPayTolls = args.shouldPayTolls || false;
36
37 this._tolls = {};
38 this._currentStaticConnection = null;
39
40 return this;
41}
42
43Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
44
45 //-------------------------------------------------------------------------
46
47 'isReadOnly': function () {
48 return this._isReadOnly;
49 },
50
51 'canRegisterNewUsers': function () {
52 return false;
53 },
54
55
56 //-------------------------------------------------------------------------
57
58 'shouldPayTolls': function() {
59 return this._shouldPayTolls;
60 },
61
62 //-------------------------------------------------------------------------
63
64 'data': function () {
65 return this._data;
66 },
67
68 //-------------------------------------------------------------------------
69
70 'tolls': function () {
71 return this._tolls;
72 },
73
74 //=========================================================================
75
76 'resetData': function() {
77 this._data = {
78 'users': {
79 'catchAllUser': {
80 __masterkey_test_value__: 'masterkey',
81 s: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00',
82 v: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00'
83 }
84 }
85 };
86 },
87
88 //-------------------------------------------------------------------------
89
90 'setupWithEncryptedData': function(someData) {
91 this._data = Clipperz.Base.deepClone(someData);
92 },
93
94 //-------------------------------------------------------------------------
95
96 'setupWithData': function(someData) {
97 var deferredResult;
98 var resultData;
99 var i, c;
100
101//Clipperz.log(">>> Proxy.Test.setupWithData");
102 resultData = this._data;
103
104 deferredResult = new Clipperz.Async.Deferred("Proxy.Test.seupWithData", {trace:false});
105 c = someData['users'].length;
106
107 for (i=0; i<c; i++) {
108 varnewConnection;
109 varrecordConfiguration;
110
111 deferredResult.addMethod(this, 'userSerializedEncryptedData', someData['users'][i]);
112 deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) {
113 resultData['users'][aUserSerializationContext['credentials']['C']] = {
114 's': aUserSerializationContext['credentials']['s'],
115 'v': aUserSerializationContext['credentials']['v'],
116 'version': aUserSerializationContext['data']['connectionVersion'],
117 'userDetails': aUserSerializationContext['encryptedData']['user']['header'],
118 'userDetailsVersion':aUserSerializationContext['encryptedData']['user']['version'],
119 'statistics': aUserSerializationContext['encryptedData']['user']['statistics'],
120 'lock': aUserSerializationContext['encryptedData']['user']['lock'],
121 'records': this.rearrangeRecordsData(aUserSerializationContext['encryptedData']['records'])
122 }
123 }, this));
124 }
125
126 deferredResult.addCallback(MochiKit.Base.bind(function() {
127 this._data = resultData;
128 }, this));
129
130 deferredResult.callback();
131//Clipperz.log("<<< Proxy.Test.setupWithData");
132
133 return deferredResult;
134 },
135
136 //=========================================================================
137
138 'getTollForRequestType': function (aRequestType) {
139 varresult;
140 vartargetValue;
141 var cost;
142
143 targetValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
144 switch (aRequestType) {
145 case 'REGISTER':
146 cost = 5;
147 break;
148 case 'CONNECT':
149 cost = 5;
150 break;
151 case 'MESSAGE':
152 cost = 2;
153 break;
154 }
155
156 result = {
157 requestType: aRequestType,
158 targetValue: targetValue,
159 cost: cost
160 }
161
162 if (this.shouldPayTolls()) {
163 this.tolls()[targetValue] = result;
164 }
165
166 return result;
167 },
168
169 //-------------------------------------------------------------------------
170
171 'checkToll': function (aFunctionName, someParameters) {
172 if (this.shouldPayTolls()) {
173 var localToll;
174 vartollParameters;
175
176 tollParameters = someParameters['toll'];
177 localToll = this.tolls()[tollParameters['targetValue']];
178
179 if (localToll != null) {
180 if (! Clipperz.PM.Toll.validate(tollParameters['targetValue'], tollParameters['toll'], localToll['cost'])) {
181 throw "Toll value too low.";
182 };
183 } else {
184 throw "Missing toll";
185 }
186 }
187 },
188
189 //=========================================================================
190
191 'currentStaticConnection': function () {
192 if (this._currentStaticConnection == null) {
193 this._currentStaticConnection = {};
194 }
195
196 return this._currentStaticConnection;
197 },
198
199 //-------------------------------------------------------------------------
200
201 'getConnectionForRequest': function (aFunctionName, someParameters) {
202 varresult;
203
204 if (this.shouldPayTolls()) {
205 if ((typeof(someParameters['toll']) != 'undefined') && (typeof(someParameters['toll']['targetValue']) != 'undefined')) {
206 result = this.tolls()[someParameters['toll']['targetValue']]['connection'];
207 if (typeof(result) == 'undefined') {
208 result = {};
209 }
210 } else {
211 result = {};
212 }
213 } else {
214 result = this.currentStaticConnection();
215 }
216
217 return result;
218 },
219
220 //-------------------------------------------------------------------------
221
222 'storeConnectionForRequestWithConnectionAndResponse': function (aFunctionName, someParameters, aConnection, aResponse) {
223 if (this.shouldPayTolls()) {
224 if ((typeof(aResponse['toll']) != 'undefined')
225 &&(typeof(aResponse['toll']['targetValue']) != 'undefined')
226 &&(typeof(this.tolls()[aResponse['toll']['targetValue']]) != 'undefined')
227 ) {
228 this.tolls()[aResponse['toll']['targetValue']]['connection'] = aConnection;
229 }
230 }
231 },
232
233 //=========================================================================
234
235 'processMessage': function (aFunctionName, someParameters) {
236 var result;
237 varconnection;
238
239 connection = this.getConnectionForRequest(aFunctionName, someParameters);
240
241 switch(aFunctionName) {
242 case 'knock':
243 result = this._knock(connection, someParameters);
244 break;
245 case 'registration':
246 this.checkToll(aFunctionName, someParameters);
247 result = this._registration(connection, someParameters.parameters);
248 break;
249 case 'handshake':
250 this.checkToll(aFunctionName, someParameters);
251 result = this._handshake(connection, someParameters.parameters);
252 break;
253 case 'message':
254 this.checkToll(aFunctionName, someParameters);
255 result = this._message(connection, someParameters.parameters);
256 break;
257 case 'logout':
258 this._currentStaticConnection = null;
259 result = this._logout(connection, someParameters.parameters);
260 break;
261 }
262
263 this.storeConnectionForRequestWithConnectionAndResponse(aFunctionName, someParameters, connection, result);
264
265 return MochiKit.Async.succeed(result);
266 },
267
268 //=========================================================================
269
270 '_knock': function(aConnection, someParameters) {
271 var result;
272
273 result = {
274 toll: this.getTollForRequestType(someParameters['requestType'])
275 }
276
277 return result;
278 },
279
280 //-------------------------------------------------------------------------
281
282 '_registration': function(aConnection, someParameters) {
283 if (this.isReadOnly() == false) {
284 if (typeof(this.data()['users'][someParameters['credentials']['C']]) == 'undefined') {
285 this.data()['users'][someParameters['credentials']['C']] = {
286 's': someParameters['credentials']['s'],
287 'v': someParameters['credentials']['v'],
288 'version':someParameters['credentials']['version'],
289 // 'lock': Clipperz.Crypto.Base.generateRandomSeed(),
290 'userDetails': someParameters['user']['header'],
291 'statistics': someParameters['user']['statistics'],
292 'userDetailsVersion':someParameters['user']['version'],
293 'records':{}
294 }
295 } else {
296 throw "user already exists";
297 }
298 } else {
299 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
300 }
301
302 result = {
303 result: {
304 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
305 'result':'done'
306 },
307 toll: this.getTollForRequestType('CONNECT')
308 }
309
310 return result;
311 },
312
313 //-------------------------------------------------------------------------
314
315 '_handshake': function(aConnection, someParameters) {
316 var result;
317 varnextTollRequestType;
318
319 result = {};
320 if (someParameters.message == "connect") {
321 var userData;
322 var randomBytes;
323 var v;
324
325 userData = this.data()['users'][someParameters.parameters.C];
326
327 if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
328 aConnection['userData'] = userData;
329 aConnection['C'] = someParameters.parameters.C;
330 } else {
331 aConnection['userData'] = this.data()['users']['catchAllUser'];
332 }
333
334 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
335 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
336 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
337 aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
338
339 aConnection['A'] = someParameters.parameters.A;
340
341 result['s'] = aConnection['userData']['s'];
342 result['B'] = aConnection['B'].asString(16);
343
344 nextTollRequestType = 'CONNECT';
345 } else if (someParameters.message == "credentialCheck") {
346 var v, u, S, A, K, M1;
347
348 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
349 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
350 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
351 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
352
353 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
354
355 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
356 if (someParameters.parameters.M1 == M1) {
357 var M2;
358
359 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
360 result['M2'] = M2;
361 } else {
362 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
363 }
364
365 nextTollRequestType = 'MESSAGE';
366 } else if (someParameters.message == "oneTimePassword") {
367 var otpData;
368
369 otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
370
371 try {
372 if (typeof(otpData) != 'undefined') {
373 if (otpData['status'] == 'ACTIVE') {
374 if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
375 result = {
376 'data': otpData['data'],
377 'version':otpData['version']
378 }
379
380 otpData['status'] = 'REQUESTED';
381 } else {
382 otpData['status'] = 'DISABLED';
383 throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
384 }
385 } else {
386 throw "The requested One Time Password was not active";
387 }
388 } else {
389 throw "The requested One Time Password has not been found"
390 }
391 } catch (exception) {
392 result = {
393 'data': Clipperz.PM.Crypto.randomKey(),
394 'version':Clipperz.PM.Connection.communicationProtocol.currentVersion
395 }
396 }
397 nextTollRequestType = 'CONNECT';
398 } else {
399 Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
400 }
401
402 result = {
403 result: result,
404 toll: this.getTollForRequestType(nextTollRequestType)
405 }
406
407 return result;
408 },
409
410 //-------------------------------------------------------------------------
411
412 '_message': function(aConnection, someParameters) {
413 var result;
414
415 result = {};
416
417 //=====================================================================
418 //
419 // R E A D - O N L Y M e t h o d s
420 //
421 //=====================================================================
422 if (someParameters.message == 'getUserDetails') {
423 var recordsStats;
424 var recordReference;
425
426 recordsStats = {};
427 for (recordReference in aConnection['userData']['records']) {
428 recordsStats[recordReference] = {
429 'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
430 }
431 }
432
433 result['header'] = this.userDetails(aConnection);
434 result['statistics'] = this.statistics(aConnection);
435 result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords'];
436 result['version'] = aConnection['userData']['userDetailsVersion'];
437 result['recordsStats'] = recordsStats;
438
439 if (this.isReadOnly() == false) {
440 varlock;
441
442 if (typeof(aConnection['userData']['lock']) == 'undefined') {
443 aConnection['userData']['lock'] = "<<LOCK>>";
444 }
445
446 result['lock'] = aConnection['userData']['lock'];
447 }
448
449 //=====================================================================
450 } else if (someParameters.message == 'getRecordDetail') {
451/*
452 varrecordData;
453 var currentVersionData;
454
455 recordData = this.userData()['records'][someParameters['parameters']['reference']];
456 result['reference'] = someParameters['parameters']['reference'];
457 result['data'] = recordData['data'];
458 result['version'] = recordData['version'];
459 result['creationData'] = recordData['creationDate'];
460 result['updateDate'] = recordData['updateDate'];
461 result['accessDate'] = recordData['accessDate'];
462
463 currentVersionData = recordData['versions'][recordData['currentVersion']];
464
465 result['currentVersion'] = {};
466 result['currentVersion']['reference'] = recordData['currentVersion'];
467 result['currentVersion']['version'] = currentVersionData['version'];
468 result['currentVersion']['header'] = currentVersionData['header'];
469 result['currentVersion']['data'] = currentVersionData['data'];
470 result['currentVersion']['creationData'] = currentVersionData['creationDate'];
471 result['currentVersion']['updateDate'] = currentVersionData['updateDate'];
472 result['currentVersion']['accessDate'] = currentVersionData['accessDate'];
473 if (typeof(currentVersionData['previousVersion']) != 'undefined') {
474 result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey'];
475 result['currentVersion']['previousVersion'] = currentVersionData['previousVersion'];
476 }
477*/
478 MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]);
479 result['reference'] = someParameters['parameters']['reference'];
480
481 //=====================================================================
482 //
483 // R E A D - W R I T E M e t h o d s
484 //
485 //=====================================================================
486 } else if (someParameters.message == 'upgradeUserCredentials') {
487 if (this.isReadOnly() == false) {
488 var parameters;
489 var credentials;
490
491 parameters = someParameters['parameters'];
492 credentials = parameters['credentials'];
493
494 if ((credentials['C'] == null)
495 ||(credentials['s'] == null)
496 ||(credentials['v'] == null)
497 ||(credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion)
498 ) {
499 result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
500 } else {
501 varoldCValue;
502 oldCValue = aConnection['C'];
503
504 this.data()['users'][credentials['C']] = aConnection['userData'];
505 aConnection['C'] = credentials['C'];
506
507 aConnection['userData']['s'] = credentials['s'];
508 aConnection['userData']['v'] = credentials['v'];
509 aConnection['userData']['version'] = credentials['version'];
510
511 aConnection['userData']['userDetails'] = parameters['user']['header'];
512 aConnection['userData']['userDetailsVersion'] = parameters['user']['version'];
513 aConnection['userData']['statistics'] = parameters['user']['statistics'];
514
515 aConnection['userData']['lock'] = parameters['user']['lock'];
516
517 delete this.data()['users'][oldCValue];
518
519 result = {result:"done", parameters:parameters};
520 }
521 } else {
522 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
523 }
524 //=====================================================================
525 /* } else if (someParameters.message == 'updateData') {
526 if (this.isReadOnly() == false) {
527 var i, c;
528
529 if (this.userData()['lock']!= someParameters['parameters']['user']['lock']) {
530 throw "the lock attribute is not processed correctly"
531 }
532
533 this.userData()['userDetails'] = someParameters['parameters']['user']['header'];
534 this.userData()['statistics'] = someParameters['parameters']['user']['statistics'];
535 this.userData()['userDetailsVersions']= someParameters['parameters']['user']['version'];
536
537 c = someParameters['parameters']['records'].length;
538 for (i=0; i<c; i++) {
539 var currentRecord;
540 var currentRecordData;
541
542 currentRecordData = someParameters['parameters']['records'][i];
543 currentRecord = this.userData()['records'][currentRecordData['record']['reference']];
544
545 if (currentRecord == null) {
546 }
547
548 currentRecord['data'] = currentRecordData['record']['data'];
549 currentRecord['version'] = currentRecordData['record']['version'];
550 currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
551
552 currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
553 'data': currentRecordData['currentRecordVersion']['data'],
554 'version': currentRecordData['currentRecordVersion']['version'],
555 'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
556 'previousVersionKey':currentRecordData['currentRecordVersion']['previousVersionKey']
557 }
558 }
559
560 this.userData()['lock'] = Clipperz.PM.Crypto.randomKey();
561 result['lock'] = this.userData()['lock'];
562 result['result'] = 'done';
563 } else {
564 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
565 }
566 */ //=====================================================================
567 } else if (someParameters.message == 'saveChanges') {
568 if (this.isReadOnly() == false) {
569 var i, c;
570
571 if (aConnection['userData']['lock']!= someParameters['parameters']['user']['lock']) {
572 throw "the lock attribute is not processed correctly"
573 }
574
575 aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header'];
576 aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics'];
577 aConnection['userData']['userDetailsVersion']= someParameters['parameters']['user']['version'];
578
579 c = someParameters['parameters']['records']['updated'].length;
580 for (i=0; i<c; i++) {
581 var currentRecord;
582 var currentRecordData;
583
584 currentRecordData = someParameters['parameters']['records']['updated'][i];
585 currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']];
586
587 if (
588 (typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined')
589 &&
590 (typeof(currentRecordData['currentRecordVersion']) == 'undefined')
591 ) {
592 throw "Record added without a recordVersion";
593 }
594
595 if (currentRecord == null) {
596 currentRecord = {};
597 currentRecord['versions'] = {};
598 currentRecord['creationDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
599 currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
600
601 aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord;
602 }
603
604 currentRecord['data'] = currentRecordData['record']['data'];
605 currentRecord['version']= currentRecordData['record']['version'];
606 currentRecord['updateDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
607
608 if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') {
609 currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
610 currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
611 'data': currentRecordData['currentRecordVersion']['data'],
612 'version': currentRecordData['currentRecordVersion']['version'],
613 'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
614 'previousVersionKey':currentRecordData['currentRecordVersion']['previousVersionKey'],
615 'creationDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
616 'updateDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
617 'accessDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date())
618 }
619 }
620 }
621
622 c = someParameters['parameters']['records']['deleted'].length;
623 for (i=0; i<c; i++) {
624 var currentRecordReference;
625
626 currentRecordReference = someParameters['parameters']['records']['deleted'][i];
627 delete aConnection['userData']['records'][currentRecordReference];
628 }
629
630 aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey();
631 result['lock'] = aConnection['userData']['lock'];
632 result['result'] = 'done';
633 } else {
634 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
635 }
636
637 //=====================================================================
638 //
639 // U N H A N D L E D M e t h o d
640 //
641 //=====================================================================
642 } else {
643 Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
644 }
645
646 result = {
647 result: result,
648 toll: this.getTollForRequestType('MESSAGE')
649 }
650
651 // return MochiKit.Async.succeed(result);
652 return result;
653 },
654
655 //-------------------------------------------------------------------------
656
657 '_logout': function(someParameters) {
658 // return MochiKit.Async.succeed({result: 'done'});
659 return {result: 'done'};
660 },
661
662 //=========================================================================
663 //#########################################################################
664
665 'isTestData': function(aConnection) {
666 return (typeof(aConnection['userData']['__masterkey_test_value__']) != 'undefined');
667 },
668
669 'userDetails': function(aConnection) {
670 var result;
671
672 if (this.isTestData(aConnection)) {
673 var serializedHeader;
674 var version;
675
676//Clipperz.logDebug("### test data");
677 version = aConnection['userData']['userDetailsVersion'];
678 serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']);
679 result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader);
680 } else {
681//Clipperz.logDebug("### NOT test data");
682 result = aConnection['userData']['userDetails'];
683 }
684
685 return result;
686 },
687
688 'statistics': function(aConnection) {
689 var result;
690
691 if (aConnection['userData']['statistics'] != null) {
692 if (this.isTestData(aConnection)) {
693 var serializedStatistics;
694 var version;
695
696 version = aConnection['userData']['userDetailsVersion'];
697 serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']);
698 result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics);
699 } else {
700 result = aConnection['userData']['statistics'];
701 }
702 } else {
703 result = null;
704 }
705
706 return result;
707 },
708
709/*
710 'userSerializedEncryptedData': function(someData) {
711 var deferredResult;
712 var deferredContext;
713
714 deferredContext = { 'data': someData };
715
716 deferredResult = new Clipperz.Async.Deferred('Proxy.Test.serializeUserEncryptedData', {trace:false});
717 deferredResult.addCallback(MochiKit.Base.bind(function(aDeferredContext) {
718 aDeferredContext['user'] = this.createUserUsingConfigurationData(aDeferredContext['data']);
719 return aDeferredContext;
720 }, this));
721 deferredResult.addCallback(function(aDeferredContext) {
722 // return aDeferredContext['user'].encryptedDataUsingVersion(aDeferredContext['data']['version']);
723 return aDeferredContext['user'].serializedDataUsingVersion(MochiKit.Base.values(aDeferredContext['user'].records()), aDeferredContext['data']['version']);
724 });
725 deferredResult.addCallback(function(aUserEncryptedData) {
726 deferredContext['encryptedData'] = aUserEncryptedData;
727 return deferredContext;
728 });
729 deferredResult.addCallback(function(aDeferredContext) {
730 var connection;
731
732 connection = new Clipperz.PM.Connection.communicationProtocol.versions[aDeferredContext['data']['connectionVersion']]()
733 aDeferredContext['credentials'] = connection.serverSideUserCredentials(aDeferredContext['user'].username(),aDeferredContext['user'].passphrase());
734
735 return aDeferredContext;
736 });
737
738 // deferredResult.addCallback(function(aDeferredContext) {
739 // return aDeferredContext['user'].serializedDataUsingVersion(MochiKit.Base.values(aDeferredContext['user'].records()), aDeferredContext['data']['version']);
740 // }, deferredContext);
741 // deferredResult.addCallback(function(aUserSerializedData) {
742 // });
743//
744 // deferredResult.addCallback(MochiKit.Async.succeed, deferredContext);
745 deferredResult.callback(deferredContext);
746
747 return deferredResult;
748 },
749
750 'createUserUsingConfigurationData': function(someData) {
751 var result;
752 var user;
753 var recordLabel;
754
755 user = new Clipperz.PM.DataModel.User();
756 user.initForTests();
757 user.setUsername(someData['username']);
758 user.setPassphrase(someData['passphrase']);
759
760 for (recordLabel in someData['records']) {
761 var recordData;
762 var record;
763 var i, c;
764
765 recordData = someData['records'][recordLabel];
766 record = new Clipperz.PM.DataModel.Record({user:user, label:recordLabel});
767 record.setNotes(recordData['notes']);
768
769 c = recordData['fields'].length;
770 for (i=0; i<c; i++) {
771 var recordField;
772
773 recordField = new Clipperz.PM.DataModel.RecordField();
774 recordField.setLabel(recordData['fields'][i]['name']);
775 recordField.setValue(recordData['fields'][i]['value']);
776 recordField.setType(recordData['fields'][i]['type']);
777 record.addField(recordField);
778 }
779 user.addRecord(record, true);
780 }
781
782 result = user;
783
784 return result;
785 },
786*/
787 //=========================================================================
788 __syntaxFix__: "syntax fix"
789});
790
791Clipperz.PM.Proxy.Offline.DataStore['exception'] = {
792 'ReadOnly': new MochiKit.Base.NamedError("Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly")
793}; \ No newline at end of file
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
new file mode 100644
index 0000000..a3c238c
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
@@ -0,0 +1,420 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.Proxy.Offline.DataStore) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.Proxy.Offline.LocalStorageDataStore depends on Clipperz.PM.Proxy.Offline.DataStore!";
26}
27
28//=============================================================================
29
30Clipperz.PM.Proxy.Offline.LocalStorageDataStore = function(args) {
31 args = args || {};
32
33 this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
34 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
35 this._shouldPayTolls = args.shouldPayTolls || false;
36
37 this._tolls = {};
38 this._currentStaticConnection = null;
39
40 //Clipperz.PM.Proxy.Offline.LocalStorageDataStore.superclass.constructor.apply(this, arguments);
41
42 return this;
43}
44
45Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.PM.Proxy.Offline.DataStore, {
46
47 //=========================================================================
48
49 '_knock': function(aConnection, someParameters) {
50 var result;
51
52 result = {
53 toll: this.getTollForRequestType(someParameters['requestType'])
54 }
55
56 return result;
57 },
58
59 //-------------------------------------------------------------------------
60
61 '_registration': function(aConnection, someParameters) {
62 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
63 },
64
65 //-------------------------------------------------------------------------
66
67 '_handshake': function(aConnection, someParameters) {
68 var result;
69 varnextTollRequestType;
70
71 result = {};
72 if (someParameters.message == "connect") {
73 var userData;
74 var randomBytes;
75 var v;
76
77 userData = this.data()['users'][someParameters.parameters.C];
78
79 if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
80 aConnection['userData'] = userData;
81 aConnection['C'] = someParameters.parameters.C;
82 } else {
83 aConnection['userData'] = this.data()['users']['catchAllUser'];
84 }
85
86 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
87 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
88 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
89 aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
90
91 aConnection['A'] = someParameters.parameters.A;
92
93 result['s'] = aConnection['userData']['s'];
94 result['B'] = aConnection['B'].asString(16);
95
96 nextTollRequestType = 'CONNECT';
97 } else if (someParameters.message == "credentialCheck") {
98 var v, u, S, A, K, M1;
99
100 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
101 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
102 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
103 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
104
105 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
106
107 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
108 if (someParameters.parameters.M1 == M1) {
109 var M2;
110
111 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
112 result['M2'] = M2;
113 } else {
114 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
115 }
116
117 nextTollRequestType = 'MESSAGE';
118 } else if (someParameters.message == "oneTimePassword") {
119 var otpData;
120
121 otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
122
123 try {
124 if (typeof(otpData) != 'undefined') {
125 if (otpData['status'] == 'ACTIVE') {
126 if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
127 result = {
128 'data': otpData['data'],
129 'version':otpData['version']
130 }
131
132 otpData['status'] = 'REQUESTED';
133 } else {
134 otpData['status'] = 'DISABLED';
135 throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
136 }
137 } else {
138 throw "The requested One Time Password was not active";
139 }
140 } else {
141 throw "The requested One Time Password has not been found"
142 }
143 } catch (exception) {
144 result = {
145 'data': Clipperz.PM.Crypto.randomKey(),
146 'version':Clipperz.PM.Connection.communicationProtocol.currentVersion
147 }
148 }
149 nextTollRequestType = 'CONNECT';
150 } else {
151 Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
152 }
153
154 result = {
155 result: result,
156 toll: this.getTollForRequestType(nextTollRequestType)
157 }
158
159 return result;
160 },
161
162 //-------------------------------------------------------------------------
163
164 '_message': function(aConnection, someParameters) {
165 var result;
166
167 result = {};
168
169 //=====================================================================
170 //
171 // R E A D - O N L Y M e t h o d s
172 //
173 //=====================================================================
174 if (someParameters.message == 'getUserDetails') {
175 var recordsStats;
176 var recordReference;
177
178 recordsStats = {};
179 for (recordReference in aConnection['userData']['records']) {
180 recordsStats[recordReference] = {
181 'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
182 }
183 }
184
185 result['header'] = this.userDetails(aConnection);
186 result['statistics'] = this.statistics(aConnection);
187 result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords'];
188 result['version'] = aConnection['userData']['userDetailsVersion'];
189 result['recordsStats'] = recordsStats;
190
191 if (this.isReadOnly() == false) {
192 varlock;
193
194 if (typeof(aConnection['userData']['lock']) == 'undefined') {
195 aConnection['userData']['lock'] = "<<LOCK>>";
196 }
197
198 result['lock'] = aConnection['userData']['lock'];
199 }
200
201 //=====================================================================
202 } else if (someParameters.message == 'getRecordDetail') {
203/*
204 varrecordData;
205 var currentVersionData;
206
207 recordData = this.userData()['records'][someParameters['parameters']['reference']];
208 result['reference'] = someParameters['parameters']['reference'];
209 result['data'] = recordData['data'];
210 result['version'] = recordData['version'];
211 result['creationData'] = recordData['creationDate'];
212 result['updateDate'] = recordData['updateDate'];
213 result['accessDate'] = recordData['accessDate'];
214
215 currentVersionData = recordData['versions'][recordData['currentVersion']];
216
217 result['currentVersion'] = {};
218 result['currentVersion']['reference'] = recordData['currentVersion'];
219 result['currentVersion']['version'] = currentVersionData['version'];
220 result['currentVersion']['header'] = currentVersionData['header'];
221 result['currentVersion']['data'] = currentVersionData['data'];
222 result['currentVersion']['creationData'] = currentVersionData['creationDate'];
223 result['currentVersion']['updateDate'] = currentVersionData['updateDate'];
224 result['currentVersion']['accessDate'] = currentVersionData['accessDate'];
225 if (typeof(currentVersionData['previousVersion']) != 'undefined') {
226 result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey'];
227 result['currentVersion']['previousVersion'] = currentVersionData['previousVersion'];
228 }
229*/
230 MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]);
231 result['reference'] = someParameters['parameters']['reference'];
232
233 //=====================================================================
234 //
235 // R E A D - W R I T E M e t h o d s
236 //
237 //=====================================================================
238 } else if (someParameters.message == 'upgradeUserCredentials') {
239 if (this.isReadOnly() == false) {
240 var parameters;
241 var credentials;
242
243 parameters = someParameters['parameters'];
244 credentials = parameters['credentials'];
245
246 if ((credentials['C'] == null)
247 ||(credentials['s'] == null)
248 ||(credentials['v'] == null)
249 ||(credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion)
250 ) {
251 result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
252 } else {
253 varoldCValue;
254 oldCValue = aConnection['C'];
255
256 this.data()['users'][credentials['C']] = aConnection['userData'];
257 aConnection['C'] = credentials['C'];
258
259 aConnection['userData']['s'] = credentials['s'];
260 aConnection['userData']['v'] = credentials['v'];
261 aConnection['userData']['version'] = credentials['version'];
262
263 aConnection['userData']['userDetails'] = parameters['user']['header'];
264 aConnection['userData']['userDetailsVersion'] = parameters['user']['version'];
265 aConnection['userData']['statistics'] = parameters['user']['statistics'];
266
267 aConnection['userData']['lock'] = parameters['user']['lock'];
268
269 delete this.data()['users'][oldCValue];
270
271 result = {result:"done", parameters:parameters};
272 }
273 } else {
274 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
275 }
276
277 //=====================================================================
278
279 } else if (someParameters.message == 'saveChanges') {
280 if (this.isReadOnly() == false) {
281 var i, c;
282
283 if (aConnection['userData']['lock']!= someParameters['parameters']['user']['lock']) {
284 throw "the lock attribute is not processed correctly"
285 }
286
287 aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header'];
288 aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics'];
289 aConnection['userData']['userDetailsVersion']= someParameters['parameters']['user']['version'];
290
291 c = someParameters['parameters']['records']['updated'].length;
292 for (i=0; i<c; i++) {
293 var currentRecord;
294 var currentRecordData;
295
296 currentRecordData = someParameters['parameters']['records']['updated'][i];
297 currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']];
298
299 if (
300 (typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined')
301 &&
302 (typeof(currentRecordData['currentRecordVersion']) == 'undefined')
303 ) {
304 throw "Record added without a recordVersion";
305 }
306
307 if (currentRecord == null) {
308 currentRecord = {};
309 currentRecord['versions'] = {};
310 currentRecord['creationDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
311 currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
312
313 aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord;
314 }
315
316 currentRecord['data'] = currentRecordData['record']['data'];
317 currentRecord['version']= currentRecordData['record']['version'];
318 currentRecord['updateDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
319
320 if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') {
321 currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
322 currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
323 'data': currentRecordData['currentRecordVersion']['data'],
324 'version': currentRecordData['currentRecordVersion']['version'],
325 'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
326 'previousVersionKey':currentRecordData['currentRecordVersion']['previousVersionKey'],
327 'creationDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
328 'updateDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
329 'accessDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date())
330 }
331 }
332 }
333
334 c = someParameters['parameters']['records']['deleted'].length;
335 for (i=0; i<c; i++) {
336 var currentRecordReference;
337
338 currentRecordReference = someParameters['parameters']['records']['deleted'][i];
339 delete aConnection['userData']['records'][currentRecordReference];
340 }
341
342 aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey();
343 result['lock'] = aConnection['userData']['lock'];
344 result['result'] = 'done';
345 } else {
346 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
347 }
348
349 //=====================================================================
350 //
351 // U N H A N D L E D M e t h o d
352 //
353 //=====================================================================
354 } else {
355 Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
356 }
357
358 result = {
359 result: result,
360 toll: this.getTollForRequestType('MESSAGE')
361 }
362
363 // return MochiKit.Async.succeed(result);
364 return result;
365 },
366
367 //-------------------------------------------------------------------------
368
369 '_logout': function(someParameters) {
370 // return MochiKit.Async.succeed({result: 'done'});
371 return {result: 'done'};
372 },
373
374 //=========================================================================
375 //#########################################################################
376/*
377 'userDetails': function(aConnection) {
378 var result;
379
380 if (this.isTestData(aConnection)) {
381 var serializedHeader;
382 var version;
383
384//Clipperz.logDebug("### test data");
385 version = aConnection['userData']['userDetailsVersion'];
386 serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']);
387 result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader);
388 } else {
389//Clipperz.logDebug("### NOT test data");
390 result = aConnection['userData']['userDetails'];
391 }
392
393 return result;
394 },
395
396 'statistics': function(aConnection) {
397 var result;
398
399 if (aConnection['userData']['statistics'] != null) {
400 if (this.isTestData(aConnection)) {
401 var serializedStatistics;
402 var version;
403
404 version = aConnection['userData']['userDetailsVersion'];
405 serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']);
406 result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics);
407 } else {
408 result = aConnection['userData']['statistics'];
409 }
410 } else {
411 result = null;
412 }
413
414 return result;
415 },
416*/
417 //=========================================================================
418 __syntaxFix__: "syntax fix"
419});
420
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.MemoryDataStore.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.MemoryDataStore.js
new file mode 100644
index 0000000..ecc4408
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.MemoryDataStore.js
@@ -0,0 +1,643 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24try { if (typeof(Clipperz.PM.Proxy.Offline.DataStore) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.Proxy.Offline.MemoryDataStore depends on Clipperz.PM.Proxy.Offline.DataStore!";
26}
27
28//=============================================================================
29
30Clipperz.PM.Proxy.Offline.MemoryDataStore = function(args) {
31 args = args || {};
32
33 this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
34 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
35 this._shouldPayTolls = args.shouldPayTolls || false;
36
37 this._tolls = {};
38 this._currentStaticConnection = null;
39
40 return this;
41}
42
43Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.MemoryDataStore, Clipperz.PM.Proxy.Offline.DataStore, {
44
45 //=========================================================================
46
47 'resetData': function() {
48 this._data = {
49 'users': {
50 'catchAllUser': {
51 __masterkey_test_value__: 'masterkey',
52 s: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00',
53 v: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00'
54 }
55 }
56 };
57 },
58
59 //-------------------------------------------------------------------------
60
61 'setupWithEncryptedData': function(someData) {
62 this._data = Clipperz.Base.deepClone(someData);
63 },
64
65 //-------------------------------------------------------------------------
66
67 'setupWithData': function(someData) {
68 var deferredResult;
69 var resultData;
70 var i, c;
71
72//Clipperz.log(">>> Proxy.Test.setupWithData");
73 resultData = this._data;
74
75 deferredResult = new Clipperz.Async.Deferred("Proxy.Test.seupWithData", {trace:false});
76 c = someData['users'].length;
77
78 for (i=0; i<c; i++) {
79 varnewConnection;
80 varrecordConfiguration;
81
82 deferredResult.addMethod(this, 'userSerializedEncryptedData', someData['users'][i]);
83 deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) {
84 resultData['users'][aUserSerializationContext['credentials']['C']] = {
85 's': aUserSerializationContext['credentials']['s'],
86 'v': aUserSerializationContext['credentials']['v'],
87 'version': aUserSerializationContext['data']['connectionVersion'],
88 'userDetails': aUserSerializationContext['encryptedData']['user']['header'],
89 'userDetailsVersion':aUserSerializationContext['encryptedData']['user']['version'],
90 'statistics': aUserSerializationContext['encryptedData']['user']['statistics'],
91 'lock': aUserSerializationContext['encryptedData']['user']['lock'],
92 'records': this.rearrangeRecordsData(aUserSerializationContext['encryptedData']['records'])
93 }
94 }, this));
95 }
96
97 deferredResult.addCallback(MochiKit.Base.bind(function() {
98 this._data = resultData;
99 }, this));
100
101 deferredResult.callback();
102//Clipperz.log("<<< Proxy.Test.setupWithData");
103
104 return deferredResult;
105 },
106
107 //=========================================================================
108
109 'getTollForRequestType': function (aRequestType) {
110 varresult;
111 vartargetValue;
112 var cost;
113
114 targetValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
115 switch (aRequestType) {
116 case 'REGISTER':
117 cost = 5;
118 break;
119 case 'CONNECT':
120 cost = 5;
121 break;
122 case 'MESSAGE':
123 cost = 2;
124 break;
125 }
126
127 result = {
128 requestType: aRequestType,
129 targetValue: targetValue,
130 cost: cost
131 }
132
133 if (this.shouldPayTolls()) {
134 this.tolls()[targetValue] = result;
135 }
136
137 return result;
138 },
139
140 //-------------------------------------------------------------------------
141
142 'checkToll': function (aFunctionName, someParameters) {
143 if (this.shouldPayTolls()) {
144 var localToll;
145 vartollParameters;
146
147 tollParameters = someParameters['toll'];
148 localToll = this.tolls()[tollParameters['targetValue']];
149
150 if (localToll != null) {
151 if (! Clipperz.PM.Toll.validate(tollParameters['targetValue'], tollParameters['toll'], localToll['cost'])) {
152 throw "Toll value too low.";
153 };
154 } else {
155 throw "Missing toll";
156 }
157 }
158 },
159
160 //=========================================================================
161
162 'currentStaticConnection': function () {
163 if (this._currentStaticConnection == null) {
164 this._currentStaticConnection = {};
165 }
166
167 return this._currentStaticConnection;
168 },
169
170 //-------------------------------------------------------------------------
171
172 'getConnectionForRequest': function (aFunctionName, someParameters) {
173 varresult;
174
175 if (this.shouldPayTolls()) {
176 if ((typeof(someParameters['toll']) != 'undefined') && (typeof(someParameters['toll']['targetValue']) != 'undefined')) {
177 result = this.tolls()[someParameters['toll']['targetValue']]['connection'];
178 if (typeof(result) == 'undefined') {
179 result = {};
180 }
181 } else {
182 result = {};
183 }
184 } else {
185 result = this.currentStaticConnection();
186 }
187
188 return result;
189 },
190
191 //-------------------------------------------------------------------------
192
193 'storeConnectionForRequestWithConnectionAndResponse': function (aFunctionName, someParameters, aConnection, aResponse) {
194 if (this.shouldPayTolls()) {
195 if ((typeof(aResponse['toll']) != 'undefined')
196 &&(typeof(aResponse['toll']['targetValue']) != 'undefined')
197 &&(typeof(this.tolls()[aResponse['toll']['targetValue']]) != 'undefined')
198 ) {
199 this.tolls()[aResponse['toll']['targetValue']]['connection'] = aConnection;
200 }
201 }
202 },
203
204 //=========================================================================
205
206 'processMessage': function (aFunctionName, someParameters) {
207 var result;
208 varconnection;
209
210 connection = this.getConnectionForRequest(aFunctionName, someParameters);
211
212 switch(aFunctionName) {
213 case 'knock':
214 result = this._knock(connection, someParameters);
215 break;
216 case 'registration':
217 this.checkToll(aFunctionName, someParameters);
218 result = this._registration(connection, someParameters.parameters);
219 break;
220 case 'handshake':
221 this.checkToll(aFunctionName, someParameters);
222 result = this._handshake(connection, someParameters.parameters);
223 break;
224 case 'message':
225 this.checkToll(aFunctionName, someParameters);
226 result = this._message(connection, someParameters.parameters);
227 break;
228 case 'logout':
229 this._currentStaticConnection = null;
230 result = this._logout(connection, someParameters.parameters);
231 break;
232 }
233
234 this.storeConnectionForRequestWithConnectionAndResponse(aFunctionName, someParameters, connection, result);
235
236 return MochiKit.Async.succeed(result);
237 },
238
239 //=========================================================================
240
241 '_knock': function(aConnection, someParameters) {
242 var result;
243
244 result = {
245 toll: this.getTollForRequestType(someParameters['requestType'])
246 }
247
248 return result;
249 },
250
251 //-------------------------------------------------------------------------
252
253 '_registration': function(aConnection, someParameters) {
254 if (this.isReadOnly() == false) {
255 if (typeof(this.data()['users'][someParameters['credentials']['C']]) == 'undefined') {
256 this.data()['users'][someParameters['credentials']['C']] = {
257 's': someParameters['credentials']['s'],
258 'v': someParameters['credentials']['v'],
259 'version':someParameters['credentials']['version'],
260 // 'lock': Clipperz.Crypto.Base.generateRandomSeed(),
261 'userDetails': someParameters['user']['header'],
262 'statistics': someParameters['user']['statistics'],
263 'userDetailsVersion':someParameters['user']['version'],
264 'records':{}
265 }
266 } else {
267 throw "user already exists";
268 }
269 } else {
270 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
271 }
272
273 result = {
274 result: {
275 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
276 'result':'done'
277 },
278 toll: this.getTollForRequestType('CONNECT')
279 }
280
281 return result;
282 },
283
284 //-------------------------------------------------------------------------
285
286 '_handshake': function(aConnection, someParameters) {
287 var result;
288 varnextTollRequestType;
289
290 result = {};
291 if (someParameters.message == "connect") {
292 var userData;
293 var randomBytes;
294 var v;
295
296 userData = this.data()['users'][someParameters.parameters.C];
297
298 if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
299 aConnection['userData'] = userData;
300 aConnection['C'] = someParameters.parameters.C;
301 } else {
302 aConnection['userData'] = this.data()['users']['catchAllUser'];
303 }
304
305 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
306 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
307 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
308 aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
309
310 aConnection['A'] = someParameters.parameters.A;
311
312 result['s'] = aConnection['userData']['s'];
313 result['B'] = aConnection['B'].asString(16);
314
315 nextTollRequestType = 'CONNECT';
316 } else if (someParameters.message == "credentialCheck") {
317 var v, u, S, A, K, M1;
318
319 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
320 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
321 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
322 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
323
324 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
325
326 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
327 if (someParameters.parameters.M1 == M1) {
328 var M2;
329
330 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
331 result['M2'] = M2;
332 } else {
333 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
334 }
335
336 nextTollRequestType = 'MESSAGE';
337 } else if (someParameters.message == "oneTimePassword") {
338 var otpData;
339
340 otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
341
342 try {
343 if (typeof(otpData) != 'undefined') {
344 if (otpData['status'] == 'ACTIVE') {
345 if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
346 result = {
347 'data': otpData['data'],
348 'version':otpData['version']
349 }
350
351 otpData['status'] = 'REQUESTED';
352 } else {
353 otpData['status'] = 'DISABLED';
354 throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
355 }
356 } else {
357 throw "The requested One Time Password was not active";
358 }
359 } else {
360 throw "The requested One Time Password has not been found"
361 }
362 } catch (exception) {
363 result = {
364 'data': Clipperz.PM.Crypto.randomKey(),
365 'version':Clipperz.PM.Connection.communicationProtocol.currentVersion
366 }
367 }
368 nextTollRequestType = 'CONNECT';
369 } else {
370 Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
371 }
372
373 result = {
374 result: result,
375 toll: this.getTollForRequestType(nextTollRequestType)
376 }
377
378 return result;
379 },
380
381 //-------------------------------------------------------------------------
382
383 '_message': function(aConnection, someParameters) {
384 var result;
385
386 result = {};
387
388 //=====================================================================
389 //
390 // R E A D - O N L Y M e t h o d s
391 //
392 //=====================================================================
393 if (someParameters.message == 'getUserDetails') {
394 var recordsStats;
395 var recordReference;
396
397 recordsStats = {};
398 for (recordReference in aConnection['userData']['records']) {
399 recordsStats[recordReference] = {
400 'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
401 }
402 }
403
404 result['header'] = this.userDetails(aConnection);
405 result['statistics'] = this.statistics(aConnection);
406 result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords'];
407 result['version'] = aConnection['userData']['userDetailsVersion'];
408 result['recordsStats'] = recordsStats;
409
410 if (this.isReadOnly() == false) {
411 varlock;
412
413 if (typeof(aConnection['userData']['lock']) == 'undefined') {
414 aConnection['userData']['lock'] = "<<LOCK>>";
415 }
416
417 result['lock'] = aConnection['userData']['lock'];
418 }
419
420 //=====================================================================
421 } else if (someParameters.message == 'getRecordDetail') {
422/*
423 varrecordData;
424 var currentVersionData;
425
426 recordData = this.userData()['records'][someParameters['parameters']['reference']];
427 result['reference'] = someParameters['parameters']['reference'];
428 result['data'] = recordData['data'];
429 result['version'] = recordData['version'];
430 result['creationData'] = recordData['creationDate'];
431 result['updateDate'] = recordData['updateDate'];
432 result['accessDate'] = recordData['accessDate'];
433
434 currentVersionData = recordData['versions'][recordData['currentVersion']];
435
436 result['currentVersion'] = {};
437 result['currentVersion']['reference'] = recordData['currentVersion'];
438 result['currentVersion']['version'] = currentVersionData['version'];
439 result['currentVersion']['header'] = currentVersionData['header'];
440 result['currentVersion']['data'] = currentVersionData['data'];
441 result['currentVersion']['creationData'] = currentVersionData['creationDate'];
442 result['currentVersion']['updateDate'] = currentVersionData['updateDate'];
443 result['currentVersion']['accessDate'] = currentVersionData['accessDate'];
444 if (typeof(currentVersionData['previousVersion']) != 'undefined') {
445 result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey'];
446 result['currentVersion']['previousVersion'] = currentVersionData['previousVersion'];
447 }
448*/
449 MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]);
450 result['reference'] = someParameters['parameters']['reference'];
451
452 //=====================================================================
453 //
454 // R E A D - W R I T E M e t h o d s
455 //
456 //=====================================================================
457 } else if (someParameters.message == 'upgradeUserCredentials') {
458 if (this.isReadOnly() == false) {
459 var parameters;
460 var credentials;
461
462 parameters = someParameters['parameters'];
463 credentials = parameters['credentials'];
464
465 if ((credentials['C'] == null)
466 ||(credentials['s'] == null)
467 ||(credentials['v'] == null)
468 ||(credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion)
469 ) {
470 result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
471 } else {
472 varoldCValue;
473 oldCValue = aConnection['C'];
474
475 this.data()['users'][credentials['C']] = aConnection['userData'];
476 aConnection['C'] = credentials['C'];
477
478 aConnection['userData']['s'] = credentials['s'];
479 aConnection['userData']['v'] = credentials['v'];
480 aConnection['userData']['version'] = credentials['version'];
481
482 aConnection['userData']['userDetails'] = parameters['user']['header'];
483 aConnection['userData']['userDetailsVersion'] = parameters['user']['version'];
484 aConnection['userData']['statistics'] = parameters['user']['statistics'];
485
486 aConnection['userData']['lock'] = parameters['user']['lock'];
487
488 delete this.data()['users'][oldCValue];
489
490 result = {result:"done", parameters:parameters};
491 }
492 } else {
493 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
494 }
495
496 //=====================================================================
497
498 } else if (someParameters.message == 'saveChanges') {
499 if (this.isReadOnly() == false) {
500 var i, c;
501
502 if (aConnection['userData']['lock']!= someParameters['parameters']['user']['lock']) {
503 throw "the lock attribute is not processed correctly"
504 }
505
506 aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header'];
507 aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics'];
508 aConnection['userData']['userDetailsVersion']= someParameters['parameters']['user']['version'];
509
510 c = someParameters['parameters']['records']['updated'].length;
511 for (i=0; i<c; i++) {
512 var currentRecord;
513 var currentRecordData;
514
515 currentRecordData = someParameters['parameters']['records']['updated'][i];
516 currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']];
517
518 if (
519 (typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined')
520 &&
521 (typeof(currentRecordData['currentRecordVersion']) == 'undefined')
522 ) {
523 throw "Record added without a recordVersion";
524 }
525
526 if (currentRecord == null) {
527 currentRecord = {};
528 currentRecord['versions'] = {};
529 currentRecord['creationDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
530 currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
531
532 aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord;
533 }
534
535 currentRecord['data'] = currentRecordData['record']['data'];
536 currentRecord['version']= currentRecordData['record']['version'];
537 currentRecord['updateDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
538
539 if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') {
540 currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
541 currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
542 'data': currentRecordData['currentRecordVersion']['data'],
543 'version': currentRecordData['currentRecordVersion']['version'],
544 'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
545 'previousVersionKey':currentRecordData['currentRecordVersion']['previousVersionKey'],
546 'creationDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
547 'updateDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
548 'accessDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date())
549 }
550 }
551 }
552
553 c = someParameters['parameters']['records']['deleted'].length;
554 for (i=0; i<c; i++) {
555 var currentRecordReference;
556
557 currentRecordReference = someParameters['parameters']['records']['deleted'][i];
558 delete aConnection['userData']['records'][currentRecordReference];
559 }
560
561 aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey();
562 result['lock'] = aConnection['userData']['lock'];
563 result['result'] = 'done';
564 } else {
565 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
566 }
567
568 //=====================================================================
569 //
570 // U N H A N D L E D M e t h o d
571 //
572 //=====================================================================
573 } else {
574 Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
575 }
576
577 result = {
578 result: result,
579 toll: this.getTollForRequestType('MESSAGE')
580 }
581
582 // return MochiKit.Async.succeed(result);
583 return result;
584 },
585
586 //-------------------------------------------------------------------------
587
588 '_logout': function(someParameters) {
589 // return MochiKit.Async.succeed({result: 'done'});
590 return {result: 'done'};
591 },
592
593 //=========================================================================
594 //#########################################################################
595
596 'isTestData': function(aConnection) {
597 return (typeof(aConnection['userData']['__masterkey_test_value__']) != 'undefined');
598 },
599
600 'userDetails': function(aConnection) {
601 var result;
602
603 if (this.isTestData(aConnection)) {
604 var serializedHeader;
605 var version;
606
607//Clipperz.logDebug("### test data");
608 version = aConnection['userData']['userDetailsVersion'];
609 serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']);
610 result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader);
611 } else {
612//Clipperz.logDebug("### NOT test data");
613 result = aConnection['userData']['userDetails'];
614 }
615
616 return result;
617 },
618
619 'statistics': function(aConnection) {
620 var result;
621
622 if (aConnection['userData']['statistics'] != null) {
623 if (this.isTestData(aConnection)) {
624 var serializedStatistics;
625 var version;
626
627 version = aConnection['userData']['userDetailsVersion'];
628 serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']);
629 result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics);
630 } else {
631 result = aConnection['userData']['statistics'];
632 }
633 } else {
634 result = null;
635 }
636
637 return result;
638 },
639
640 //=========================================================================
641 __syntaxFix__: "syntax fix"
642});
643
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.js
new file mode 100644
index 0000000..6d6ee1e
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.js
@@ -0,0 +1,72 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26
27//=============================================================================
28
29Clipperz.PM.Proxy.Offline = function(args) {
30 args = args || {};
31
32 Clipperz.PM.Proxy.Offline.superclass.constructor.call(this, args);
33
34 this._dataStore = args.dataStore || new Clipperz.PM.Proxy.Offline.DataStore(args);
35
36 return this;
37}
38
39Clipperz.Base.extend(Clipperz.PM.Proxy.Offline, Clipperz.PM.Proxy, {
40
41 'toString': function () {
42 return "Clipperz.PM.Proxy.Offline";
43 },
44
45 //-------------------------------------------------------------------------
46
47 'dataStore': function () {
48 return this._dataStore;
49 },
50
51 //-------------------------------------------------------------------------
52
53 '_sendMessage': function(aFunctionName, aVersion, someParameters) {
54 return this.dataStore().processMessage(aFunctionName, someParameters);
55 },
56
57 //-------------------------------------------------------------------------
58
59 'isReadOnly': function () {
60 return this.dataStore().isReadOnly();
61 },
62
63 'canRegisterNewUsers': function () {
64 return this.dataStore().canRegisterNewUsers();
65 },
66
67 //-------------------------------------------------------------------------
68
69 __syntaxFix__: "syntax fix"
70
71});
72
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Test.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Test.js
new file mode 100644
index 0000000..83d9244
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Test.js
@@ -0,0 +1,161 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.Proxy) == 'undefined') { Clipperz.PM.Proxy = {}; }
27
28//=============================================================================
29
30Clipperz.PM.Proxy.Test = function(args) {
31 Clipperz.PM.Proxy.Test.superclass.constructor.call(this, args);
32
33 args = args || {};
34
35 this._expectedRequests = (args.shouldCheckExpectedRequests === true) ? [] : null;
36 this._isExpectingRequests = true;
37 this._unexpectedRequests = [];
38
39 this.dataStore().resetData();
40
41 return this;
42}
43
44Clipperz.Base.extend(Clipperz.PM.Proxy.Test, Clipperz.PM.Proxy.Offline, {
45
46 'toString': function() {
47 return "Clipperz.PM.Proxy.Test";
48 },
49
50 //=========================================================================
51
52 'expectedRequests': function () {
53 return this._expectedRequests;
54 },
55
56 //-------------------------------------------------------------------------
57
58 'shouldCheckExpectedRequests': function () {
59 return (this._expectedRequests != null);
60 },
61
62 'setShouldCheckExpectedRequests': function(aValue) {
63 if (aValue) {
64 this._expectedRequests = aValue;
65 } else {
66 this._expectedRequests = null;
67 }
68 },
69
70 //-------------------------------------------------------------------------
71
72 'shouldNotReceiveAnyFurtherRequest': function () {
73 this._isExpectingRequests = false;
74 },
75
76 'mayReceiveMoreRequests': function () {
77 this._isExpectingRequests = true;
78 this.resetUnexpectedRequests();
79 },
80
81 'isExpectingRequests': function () {
82 return this._isExpectingRequests;
83 },
84
85 //-------------------------------------------------------------------------
86
87 'unexpectedRequests': function () {
88 return this._unexpectedRequests;
89 },
90
91 'resetUnexpectedRequests': function () {
92 this._unexpectedRequests = [];
93 },
94
95 //-------------------------------------------------------------------------
96
97 'testExpectedRequestParameters': function (aPath, anActualRequest, anExpectedRequest) {
98 var aKey;
99 for (aKey in anExpectedRequest) {
100 if (typeof(anActualRequest[aKey]) == 'undefined') {
101 throw "the expected paramter [" + aKey + "] is missing from the actual request";
102 }
103 if (typeof(anExpectedRequest[aKey]) == 'object') {
104 this.testExpectedRequestParameters(aPath + "." + aKey, anActualRequest[aKey], anExpectedRequest[aKey])
105 } else {
106 if (! anExpectedRequest[aKey](anActualRequest[aKey])) {
107 throw "wrong value for paramter [" + aKey + "]; got '" + anActualRequest[aKey] + "'";
108 }
109 }
110 }
111 },
112
113 //-------------------------------------------------------------------------
114
115 'checkRequest': function(aFunctionName, someParameters) {
116 if (this.shouldCheckExpectedRequests()) {
117 var expectedRequest;
118
119 expectedRequest = this.expectedRequests().pop();
120 if (expectedRequest == null) {
121 throw "Proxy.Test.sentMessage: no expected result specified. Got request '" + aFunctionName + "': " + someParameters;
122 }
123
124 try {
125 if (aFunctionName != expectedRequest.functionName) {
126 throw "wrong function name. Got '" + aFunctionName + "', expected '" + expectedRequest.request.functionName + "'";
127 }
128
129 this.testExpectedRequestParameters("parameters", someParameters, expectedRequest.parameters);
130 } catch(exception) {
131 throw "Proxy.Test.sentMessage[" + expectedRequest.name + "]: " + exception;
132 }
133 }
134 },
135
136 //=========================================================================
137
138 '_sendMessage': function(aFunctionName, aVersion, someParameters) {
139 var result;
140
141 if (this.isExpectingRequests() == false) {
142 // throw Clipperz.PM.Connection.exception.UnexpectedRequest;
143Clipperz.log("UNEXPECTED REQUEST " + aFunctionName /* + ": " + Clipperz.Base.serializeJSON(someParameters) */);
144 this.unexpectedRequests().push({'functionName':aFunctionName, 'someParameters': someParameters});
145 };
146//if (aFunctionName == 'knock') {
147 //console.log(">>> send message - " + aFunctionName, someParameters);
148//} else {
149 //console.log(">>> SEND MESSAGE - " + aFunctionName + " [" + someParameters['parameters']['message'] + "]", someParameters['parameters']['parameters']);
150//}
151 this.checkRequest(aFunctionName, someParameters);
152 result = Clipperz.PM.Proxy.Test.superclass._sendMessage.call(this, aFunctionName, aVersion, someParameters);
153
154 return result;
155 },
156
157 //=========================================================================
158 __syntaxFix__: "syntax fix"
159
160});
161
diff --git a/frontend/delta/js/Clipperz/PM/Strings.js b/frontend/delta/js/Clipperz/PM/Strings.js
new file mode 100644
index 0000000..7e855ff
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Strings.js
@@ -0,0 +1,285 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.Strings) == 'undefined') { Clipperz.PM.Strings = {}; }
27if (typeof(Clipperz.PM.Strings.Languages) == 'undefined') { Clipperz.PM.Strings.Languages = {}; }
28
29//-----------------------------------------------------------------------------
30/*
31Clipperz.PM.Strings.standardStrings = {
32 'loginPanelSwitchLanguageSelectOptions':[
33/ *
34 {tag:'option', html:"Arabic (Oman) (العربية)", value:'ar-OM', disabled:true},
35 {tag:'option', html:"Arabic (Syria) (العربية)", value:'ar-SY', disabled:true},
36 {tag:'option', html:"Bahasa Indonesia", value:'id-ID', disabled:true},
37 {tag:'option', html:"Bulgarian (Български)", value:'bg-BG', disabled:true},
38 {tag:'option', html:"Català", value:'ca-ES', disabled:true},
39 {tag:'option', html:"Chinese (Simplified) (简体中文)", value:'zh-CN', disabled:true},
40 {tag:'option', html:"Chinese (Traditional) (正體中文)", value:'zh-TW', disabled:true},
41 {tag:'option', html:"Czech (Česky)", value:'cs-CZ', disabled:true},
42 {tag:'option', html:"Dansk", value:'da-DK', disabled:true},
43 {tag:'option', html:"Deutsch", value:'de-DE'/ *, disabled:true* /},
44 {tag:'option', html:"English (American)", value:'en-US'/ *, disabled:true* /},
45 {tag:'option', html:"English (British)", value:'en-GB'/ *, disabled:true* /},
46 {tag:'option', html:"English (Canadian)", value:'en-CA'/ *, disabled:true* /},
47 {tag:'option', html:"Español", value:'es-ES', disabled:true},
48 {tag:'option', html:"Eesti", value:'et-EE', disabled:true},
49 {tag:'option', html:"Français", value:'fr-FR', disabled:true},
50 {tag:'option', html:"Galego", value:'gl-ES', disabled:true},
51 {tag:'option', html:"Greek (Ελληνικά)", value:'el-GR', disabled:true},
52 {tag:'option', html:"Íslenska", value:'is-IS', disabled:true},
53 {tag:'option', html:"Italiano", value:'it-IT'/ *, disabled:true* /},
54 {tag:'option', html:"Japanese (日本語)", value:'ja-JP', disabled:true},
55 {tag:'option', html:"Korean (한국어)", value:'ko-KR', disabled:true},
56 {tag:'option', html:"Latviešu", value:'lv-LV', disabled:true},
57 {tag:'option', html:"Lietuvių", value:'lt-LT', disabled:true},
58 {tag:'option', html:"Macedonian (Македонски)", value:'mk-MK', disabled:true},
59 {tag:'option', html:"Magyar", value:'hu-HU', disabled:true},
60 {tag:'option', html:"Nederlands", value:'nl-NL', disabled:true},
61 {tag:'option', html:"Norsk bokmål", value:'nb-NO', disabled:true},
62 {tag:'option', html:"Norsk nynorsk", value:'nn-NO', disabled:true},
63 {tag:'option', html:"Persian (Western) (فارسى)", value:'fa-IR', disabled:true},
64 {tag:'option', html:"Polski", value:'pl-PL', disabled:true},
65 {tag:'option', html:"Português", value:'pt-PT'/ *, disabled:true* /},
66 {tag:'option', html:"Português Brasileiro", value:'pt-BR'/ *, disabled:true* /},
67 {tag:'option', html:"Românä", value:'ro-RO', disabled:true},
68 {tag:'option', html:"Russian (Русский)", value:'ru-RU', disabled:true},
69 {tag:'option', html:"Slovak (Slovenčina)", value:'sk-SK', disabled:true},
70 {tag:'option', html:"Slovenian (Slovenščina)", value:'sl-SI', disabled:true},
71 {tag:'option', html:"Suomi", value:'fi-FI', disabled:true},
72 {tag:'option', html:"Svenska", value:'sv-SE', disabled:true},
73 {tag:'option', html:"Thai (ไทย)", value:'th-TH', disabled:true},
74 {tag:'option', html:"Türkçe", value:'tr-TR', disabled:true},
75 {tag:'option', html:"Ukrainian (Українська)", value:'uk-UA', disabled:true}
76* /
77 {tag:'option', html:"Arabic (العربية)", value:"ar", disabled:true, cls:'disabledOption'},
78 // {tag:'option', html:"Chinese (中文)", value:"zh", disabled:true},
79 {tag:'option', html:"Chinese (Simplified) (简体中文)", value:'zh-CN'},
80 {tag:'option', html:"Dutch (Nederlands)", value:"nl-NL", disabled:true, cls:'disabledOption'},
81 {tag:'option', html:"English", value:"en-US"},
82 {tag:'option', html:"French (Français)", value:"fr-FR"},
83 {tag:'option', html:"German (Deutsch)", value:"de-DE", disabled:true, cls:'disabledOption'},
84 {tag:'option', html:"Greek (Ελληνικά)", value:"el-GR", disabled:true, cls:'disabledOption'},
85 {tag:'option', html:"Hebrew (עברית)", value:"he-IL", disabled:true, cls:'disabledOption'},
86 {tag:'option', html:"Italian (Italiano)", value:"it-IT"},
87 {tag:'option', html:"Japanese (日本語)", value:"ja-JP"},
88 {tag:'option', html:"Korean (한국어)", value:"ko-KR", disabled:true, cls:'disabledOption'},
89 {tag:'option', html:"Norwegian (Norsk)", value:"no", disabled:true, cls:'disabledOption'},
90 {tag:'option', html:"Persian (فارسی)", value:"fa-IR", disabled:true, cls:'disabledOption'},
91 {tag:'option', html:"Polish (Polski)", value:"pl-PL", disabled:true, cls:'disabledOption'},
92 {tag:'option', html:"Portuguese (Português)", value:"pt-BR"},
93 {tag:'option', html:"Russian (Русский)", value:"ru-RU", disabled:true, cls:'disabledOption'},
94 {tag:'option', html:"Spanish (Español)", value:"es-ES"},
95 {tag:'option', html:"Swedish (Svenska)", value:"sv-SE", disabled:true, cls:'disabledOption'},
96 {tag:'option', html:"Turkish (Türkçe)", value:"tr-TR", disabled:true, cls:'disabledOption'},
97 {tag:'option', html:"Vietnamese (Tiếng Việt)", value:"vi-VN", disabled:true, cls:'disabledOption'}
98 ]
99}
100*/
101
102Clipperz.PM.Strings.GeneralSettings = {
103 'defaults': {
104 // 'loginFormAarghThatsBadUrl':"http://www.clipperz.com/support/faq/account_faq",
105 // 'loginFormVerifyTheCodeUrl':"http://www.clipperz.com/learn_more/reviewing_the_code",
106
107 // 'donateHeaderLinkUrl': "http://www.clipperz.com/donations",
108 // 'creditsHeaderLinkUrl': "http://www.clipperz.com/credits",
109 // 'feedbackHeaderLinkUrl': "http://www.clipperz.com/contact",
110 // 'helpHeaderLinkUrl': "http://www.clipperz.com/support/user_guide",
111 // 'forumHeaderLinkUrl': "http://www.clipperz.com/forum",
112
113 // 'httpAuthBookmarkletConfiguration':{tag:'textarea', id:'httpAuthDefaultConfiguration', html:"" +
114 // "{ \"page\":{\"title\":\"HTTP authentication\"}," + "\n" +
115 // " \"form\":{\"attributes\": {" + "\n" +
116 // " \"action\":\"\"," + "\n" +
117 // " \"type\":\"http_auth\"" + "\n" +
118 // " }, \"inputs\": [" + "\n" +
119 // " {\"type\":\"text\",\"name\":\"url\",\"value\":\"\"}," + "\n" +
120 // " {\"type\":\"text\",\"name\":\"username\",\"value\":\"\"}," + "\n" +
121 // " {\"type\":\"password\",\"name\":\"password\",\"value\":\"\"}" + "\n" +
122 // " ]}, \"version\":\"0.2.3\"}"
123 // },
124
125 'directLoginJumpPageUrl':"",
126 'defaultFaviconUrl': "data:application/octet-stream;charset=utf-8;base64,AAABAAEAFxcAAAEAGAD8BgAAFgAAACgAAAAXAAAALgAAAAEAGAAAAAAAAAAAABIXAAASFwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////9zAC////////////////////////////////////////////////////////////////////////////////////////////9pAG////////////////////////////////////////////////////////////////////////////////////////////9rAC////////////////////////////////////////////////////////////////////////////////////////////9yAHP////////////////////////IyMizs7O6urrq6ur////////////Ozs6zs7Ozs7Pq6ur///////////////////////8AAAD////////////////////V1dWXl5eXl5eXl5elpaX4+Pj////Ozs6Xl5eXl5eXl5eenp7///////////////////////8AAAD////////////////////Ozs6Xl5eXl5eXl5eXl5fBwcHq6uqenp6Xl5eXl5eXl5eXl5f///////////////////////8AAAD////////////////////j4+OXl5eXl5eXl5eXl5eXl5elpaWXl5eXl5eXl5eXl5ezs7P///////////////////////8AAAD////////////////////////IyMiXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eenp7x8fH////////////////////////////////////////////////////4+PilpaWXl5eXl5eXl5eXl5eXl5eXl5eXl5fOzs7////////////////////////////////////////////////////////q6uq6urqXl5eXl5eXl5eXl5eXl5eXl5eenp7V1dX4+Pj///////////////////////8AAAD////////////4+PjOzs6lpaWXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5e6urrj4+P///////////////8AAAD////////////BwcGXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5fx8fH///////////8AAAD///////////+zs7OXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5fj4+P///////////8AAAD////////////IyMiXl5eXl5eXl5eXl5e6urqXl5eXl5eXl5eXl5esrKylpaWXl5eXl5eXl5eenp7x8fH///////////8AAAD////////////////Ozs7Ozs7V1dX4+Pj///+Xl5eXl5eXl5eXl5fOzs7////q6urOzs7Ozs7q6ur///////////////8AAAD///////////////////////////////////+Xl5eXl5eXl5eXl5fOzs7///////////////////////////////////8AAAD///////////////////////////////////+Xl5eXl5eXl5eXl5fOzs7///////////////////////////////////8AAAD///////////////////////////////////+Xl5eXl5eXl5eXl5fOzs7///////////////////////////////////8AAAD////////////////////////////////////IyMiXl5eXl5eenp7x8fH///////////////////////////////////8AAAD////////////////////////////////////////j4+Pj4+Px8fH///////////////////////////////////////8AAAD///////////////////////////////////////////////////////////////////////////////////////////8AAAD///////////////////////////////////////////////////////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo=",
127 'defaultFaviconUrl_IE': "https://www.clipperz.com/images/icons/misc/favicon.ico",
128
129 // 'icons_baseUrl':"https://www.clipperz.com/images/icons",
130
131 // 'passwordGeneratorLowercaseCharset':"abcdefghijklmnopqrstuvwxyz",
132 // 'passwordGeneratorUppercaseCharset':"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
133 // 'passwordGeneratorNumberCharset': "0123456789",
134 // 'passwordGeneratorSymbolCharset': "!@#$%^&*+?[]{}/|\\<>,.;:~=-_",
135
136 // 'passwordGenerator': {
137 // 'lowercaseCharset':"abcdefghijklmnopqrstuvwxyz",
138 // 'uppercaseCharset':"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
139 // 'numberCharset':"0123456789",
140 // 'symbolCharset':"!@#$%^&*+?[]{}/|\\<>,.;:~=-_",
141 // },
142
143 '_': ""
144 }
145}
146
147Clipperz.PM.Strings.defaultLanguages = {
148 'default':"en-us",
149
150 // 'de':"de-de",
151 // 'el':"el-gr",
152 // 'he':"he-il",
153 // 'ru':"ru-ru",
154
155 'fr':"fr-fr",
156 'es':"es-es",
157 'zh':"zh-cn",
158 'ja':"ja-jp",
159 'pt':"pt-br",
160 'it':"it-it",
161 'en': "en-us"
162}
163
164Clipperz.PM.Strings.inputTypeToRecordFieldType = {
165 'text': 'TXT',
166 'password': 'PWD',
167 'checkbox': 'CHECK',
168 'radio': 'RADIO',
169 'select': 'SELECT'
170};
171
172//-----------------------------------------------------------------------------
173
174Clipperz.PM.Strings.translateBookmarklet = function (aBookmarkletString) {
175 var result;
176
177 result = aBookmarkletString;
178
179 result = result.replace(/@BOOKMARKLET_NO_EXCEPTION_MESSAGE@/,Clipperz.PM.Strings.getValue('bookmarkletCopy.noExceptionMessage'));
180 result = result.replace(/@BOOKMARKLET_EXCEPTION_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.exceptionMessage'));
181 result = result.replace(/@BOOKMARKLET_COPY@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.copy'));
182 result = result.replace(/@BOOKMARKLET_SUCCESSFUL_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.successfulMessage'));
183 result = result.replace(/@BOOKMARKLET_FAIL_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.failMessage'));
184
185 return result;
186}
187
188//-----------------------------------------------------------------------------
189
190Clipperz.PM.Strings.Languages.setSelectedLanguage = function(aLanguage) {
191 var language;
192 varselectedLanguage;
193
194 language = (aLanguage || Clipperz.PM.Strings.preferredLanguage || 'default').toLowerCase();
195 if (typeof(Clipperz.PM.Strings.defaultLanguages[language]) != 'undefined') {
196 language = Clipperz.PM.Strings.defaultLanguages[language];
197 }
198
199 if (typeof(Clipperz.PM.Strings.Languages[language]) != 'undefined') {
200 selectedLanguage = language;
201 } else if (typeof(Clipperz.PM.Strings.defaultLanguages[language.substr(0,2)]) != 'undefined') {
202 selectedLanguage = Clipperz.PM.Strings.defaultLanguages[language.substr(0,2)];
203 } else {
204 selectedLanguage = Clipperz.PM.Strings.defaultLanguages['default'];
205 }
206
207 if (selectedLanguage != Clipperz.PM.Strings.selectedLanguage) {
208 vartranslations;
209
210 Clipperz.PM.Strings.selectedLanguage = selectedLanguage;
211
212 translations = {};
213 // MochiKit.Base.update(translations, Clipperz.PM.Strings.standardStrings)
214
215 MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.Languages['defaults']);
216 MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.GeneralSettings['defaults']);
217
218 MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.Languages[Clipperz.PM.Strings.defaultLanguages['default']]);
219 MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.GeneralSettings[Clipperz.PM.Strings.defaultLanguages['default']]);
220
221 MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.Languages[selectedLanguage]);
222 MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.GeneralSettings[selectedLanguage]);
223
224 Clipperz.PM.Strings.stringsObjectStore = new Clipperz.KeyValueObjectStore(/*{'name':'String.stringsObjectStore [1]'}*/);
225 Clipperz.PM.Strings.stringsObjectStore.initWithValues(translations);
226
227 if (typeof(bookmarklet) != 'undefined') {
228 Clipperz.PM.Strings.stringsObjectStore.setValue('bookmarklet', Clipperz.PM.Strings.translateBookmarklet(bookmarklet));
229 }
230
231 MochiKit.Signal.signal(Clipperz.PM.Strings.Languages, 'switchLanguage', selectedLanguage);
232 }
233}
234
235//-----------------------------------------------------------------------------
236
237Clipperz.PM.Strings.getValue = function (aKeyPath, someKeyValues) {
238 varresult;
239
240 result = Clipperz.PM.Strings.stringsObjectStore.getValue(aKeyPath);
241
242 if (typeof(result) == 'string') {
243 if (typeof (someKeyValues) != 'undefined') {
244 varkey;
245
246 for (key in someKeyValues) {
247 result = result.replace( new RegExp(key), someKeyValues[key]);
248 }
249 }
250
251 result = result.replace(new RegExp('\n'), '<br>');
252 }
253
254 return result;
255}
256
257Clipperz.PM.Strings.errorDescriptionForException = function (anException) {
258 var result;
259
260 result = Clipperz.PM.Strings.getValue('exceptionsMessages' + '.' + anException.name);
261
262 if (result == null) {
263 result = anException.message;
264 }
265
266 return result;
267},
268
269//-----------------------------------------------------------------------------
270
271Clipperz.PM.Strings.Languages.initSetup = function() {
272 varlanguage;
273 varlanguageParser;
274
275 language = navigator.language || navigator.userLanguage; //en, en-US, .... "de", "nb-no"
276 languageParser = new RegExp("language=([a-z]{2}(?:\-[a-z]{2})?)(\&|$)", "i");
277 if (languageParser.test(window.location.search)) {
278 language = RegExp.$1;
279 }
280
281 Clipperz.PM.Strings.preferredLanguage = language.toLowerCase();
282 Clipperz.PM.Strings.Languages.setSelectedLanguage(Clipperz.PM.Strings.preferredLanguage);
283}
284
285//-----------------------------------------------------------------------------
diff --git a/frontend/delta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js b/frontend/delta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js
new file mode 100644
index 0000000..7565d2d
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js
@@ -0,0 +1,384 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.Strings) == 'undefined') { Clipperz.PM.Strings = {}; }
27
28Clipperz.PM.Strings.messagePanelConfigurations = {
29
30
31 //-------------------------------------------------------------------------
32 //
33 // Registration - connection
34 //
35 'registration_verify': function() {
36 return {
37 'title': null,
38 'text': Clipperz.PM.Strings['connectionRegistrationSendingRequestMessageText']
39 }
40 },
41
42 'registration_sendingCredentials': function() {
43 return {
44 'title': null,
45 'text': Clipperz.PM.Strings['connectionRegistrationSendingCredentialsMessageText']
46 }
47 },
48
49 //-------------------------------------------------------------------------
50 //
51 // One Time Password login message panel
52 //
53
54 'OTP_login_start': function() {
55 return {
56 'title': Clipperz.PM.Strings['OTPloginMessagePanelInitialTitle'],
57 'text': Clipperz.PM.Strings['OTPloginMessagePanelInitialText'],
58 'steps': '+3',
59 'buttons': {}
60 }
61 },
62
63 'OTP_login_loadingOTP': function() {
64 return {
65 'title': Clipperz.PM.Strings['OTPloginMessagePanelLoadingTitle'],
66 'text': Clipperz.PM.Strings['OTPloginMessagePanelLoadingText']
67 }
68 },
69
70 'OTP_login_extractingPassphrase': function() {
71 return {
72 'title': Clipperz.PM.Strings['OTPloginMessagePanelProcessingTitle'],
73 'text': Clipperz.PM.Strings['OTPloginMessagePanelProcessingText']
74 }
75 },
76
77
78 //-------------------------------------------------------------------------
79 //
80 // Login message panel
81 //
82 'login_start': function() {
83 return {
84 'title': Clipperz.PM.Strings['loginMessagePanelInitialTitle'],
85 'text': Clipperz.PM.Strings['loginMessagePanelInitialText'],
86 'steps': '+7',
87 'buttons': {
88 'ok': Clipperz.PM.Strings['loginMessagePanelInitialButtonLabel']
89 }
90 }
91 },
92
93 'login_connected': function() {
94 return {
95 'title': Clipperz.PM.Strings['loginMessagePanelConnectedTitle'],
96 'text': Clipperz.PM.Strings['loginMessagePanelConnectedText'],
97 'buttons': {}
98 }
99 },
100
101 'login_failed':function() {
102 return {
103 'title': Clipperz.PM.Strings['loginMessagePanelFailureTitle'],
104 'text': Clipperz.PM.Strings['loginMessagePanelFailureText'],
105 'button': Clipperz.PM.Strings['loginMessagePanelFailureButtonLabel']
106 }
107 },
108
109 //-------------------------------------------------------------------------
110 //
111 // Login message panel - connection
112 //
113 'connection_sendingCredentials': function() {
114 return {
115 'title': Clipperz.PM.Strings['connectionLoginSendingCredentialsMessageTitle'],
116 'text': Clipperz.PM.Strings['connectionLoginSendingCredentialsMessageText']
117 }
118 },
119
120 'connection_credentialVerification': function() {
121 return {
122 'title': Clipperz.PM.Strings['connectionLoginCredentialsVerificationMessageTitle'],
123 'text': Clipperz.PM.Strings['connectionLoginCredentialsVerificationMessageText']
124 }
125 },
126
127 'connection_loggedIn': function() {
128 return {
129 'title': Clipperz.PM.Strings['connectionLoginDoneMessageTitle'],
130 'text': Clipperz.PM.Strings['connectionLoginDoneMessageText']
131 }
132 },
133
134 //-------------------------------------------------------------------------
135 //
136 //Login message panel - user
137 //
138 'connection_upgrading': function() {
139 return {
140 'title': Clipperz.PM.Strings['userLoginPanelUpgradingUserCredentialsMessageTitle'],
141 'text': Clipperz.PM.Strings['userLoginPanelUpgradingUserCredentialsMessageText'],
142 'steps': '+1'
143 }
144 },
145
146 'connection_done': function() {
147 return {
148 'title': Clipperz.PM.Strings['userLoginPanelConnectedMessageTitle'],
149 'text': Clipperz.PM.Strings['userLoginPanelConnectedMessageText']
150 }
151 },
152
153 'connection_tryOlderSchema': function() {
154 return {
155 'title': Clipperz.PM.Strings['userLoginPanelTryingAnOlderConnectionSchemaMessageTitle'],
156 'text': Clipperz.PM.Strings['userLoginPanelTryingAnOlderConnectionSchemaMessageText'],
157 'steps': '+4'
158 }
159 },
160
161 'connection_loadingUserData': function() {
162 return {
163 'title': Clipperz.PM.Strings['userLoginPanelLoadingUserDataMessageTitle'],
164 'text': Clipperz.PM.Strings['userLoginPanelLoadingUserDataMessageText']
165 }
166 },
167
168 'connection_decryptingUserData': function() {
169 return {
170 'title': Clipperz.PM.Strings['userLoginPanelDecryptingUserDataMessageTitle'],
171 'text': Clipperz.PM.Strings['userLoginPanelDecryptingUserDataMessageText'],
172 'steps': '+1'
173 }
174 },
175
176 'connection_decryptingUserStatistics': function() {
177 return {
178 'title': Clipperz.PM.Strings['userLoginPanelDecryptingUserStatisticsMessageTitle'],
179 'text': Clipperz.PM.Strings['userLoginPanelDecryptingUserStatisticsMessageText']
180 }
181 },
182
183 'collectingEntropy': function() {
184 return {
185 'text': Clipperz.PM.Strings['panelCollectingEntryopyMessageText'],
186 'steps': '+1'
187 }
188 },
189
190 //-------------------------------------------------------------------------
191 //
192 // Cards block - delete card panel
193 //
194 'deleteRecord_collectData': function() {
195 return {
196 'title': Clipperz.PM.Strings['deleteRecordPanelCollectRecordDataMessageTitle'],
197 'text': Clipperz.PM.Strings['deleteRecordPanelCollectRecordDataMessageText']
198 }
199 },
200
201 'deleteRecord_encryptData': function() {
202 return {
203 'title': Clipperz.PM.Strings['deleteRecordPanelEncryptUserDataMessageTitle'],
204 'text': Clipperz.PM.Strings['deleteRecordPanelEncryptUserDataMessageText']
205 }
206 },
207
208 'deleteRecord_sendingData': function() {
209 return {
210 'title': Clipperz.PM.Strings['deleteRecordPanelSendingDataToTheServerMessageTitle'],
211 'text': Clipperz.PM.Strings['deleteRecordPanelSendingDataToTheServerMessageText']
212 }
213 },
214
215 'deleteRecord_updatingInterface': function() {
216 return {
217 'title': Clipperz.PM.Strings['deleteRecordPanelUpdatingTheInterfaceMessageTitle'],
218 'text': Clipperz.PM.Strings['deleteRecordPanelUpdatingTheInterfaceMessageText']
219 }
220 },
221
222
223 //-------------------------------------------------------------------------
224 //
225 //Cards block - save card panel
226 //
227 'saveCard_collectRecordInfo': function() {
228 return {
229 'title': Clipperz.PM.Strings['recordSaveChangesPanelCollectRecordInfoMessageTitle'],
230 'text': Clipperz.PM.Strings['recordSaveChangesPanelCollectRecordInfoMessageText']
231 }
232 },
233
234 'saveCard_encryptUserData': function() {
235 return {
236 'title': Clipperz.PM.Strings['recordSaveChangesPanelEncryptUserDataMessageTitle'],
237 'text': Clipperz.PM.Strings['recordSaveChangesPanelEncryptUserDataMessageText']
238 }
239 },
240
241 'saveCard_encryptRecordData': function() {
242 return {
243 'title': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordDataMessageTitle'],
244 'text': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordDataMessageText']
245 }
246 },
247
248 'saveCard_encryptRecordVersions': function() {
249 return {
250 'title': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordVersionDataMessageTitle'],
251 'text': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordVersionDataMessageText']
252 }
253 },
254
255 'saveCard_sendingData': function() {
256 return {
257 'title': Clipperz.PM.Strings['recordSaveChangesPanelSendingDataToTheServerMessageTitle'],
258 'text': Clipperz.PM.Strings['recordSaveChangesPanelSendingDataToTheServerMessageText']
259 }
260 },
261
262 'saveCard_updatingInterface': function() {
263 return {
264 'title': Clipperz.PM.Strings['recordSaveChangesPanelUpdatingTheInterfaceMessageTitle'],
265 'text': Clipperz.PM.Strings['recordSaveChangesPanelUpdatingTheInterfaceMessageText']
266 }
267 },
268
269 //-------------------------------------------------------------------------
270 //
271 //Account panel - user preferences
272 //
273 'account_savingPreferences_1': function() {
274 return {
275 'title': Clipperz.PM.Strings['accountPreferencesSavingPanelTitle_Step1'],
276 'text': Clipperz.PM.Strings['accountPreferencesSavingPanelText_Step1'],
277 'steps': '+3'
278 }
279 },
280
281 'account_savingPreferences_2': function() {
282 return {
283 'title': Clipperz.PM.Strings['accountPreferencesSavingPanelTitle_Step2'],
284 'text': Clipperz.PM.Strings['accountPreferencesSavingPanelText_Step2']
285 }
286 },
287
288
289 //-------------------------------------------------------------------------
290 //
291 //Account panel - change credentials
292 //
293 'changeCredentials_encryptingData': function() {
294 return {
295 'title': Clipperz.PM.Strings['changeCredentialsPanelEncryptingDataMessageTitle'],
296 'text': Clipperz.PM.Strings['changeCredentialsPanelEncryptingDataMessageText']
297 }
298 },
299
300 'changeCredentials_creatingNewCredentials': function() {
301 return {
302 'title': Clipperz.PM.Strings['changeCredentialsPanelCreatingNewCredentialsMessageTitle'],
303 'text': Clipperz.PM.Strings['changeCredentialsPanelCreatingNewCredentialsMessageText']
304 }
305 },
306
307 'changeCredentials_sendingCredentials': function() {
308 return {
309 'title': Clipperz.PM.Strings['changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle'],
310 'text': Clipperz.PM.Strings['changeCredentialsPanelSendingNewCredentialsToTheServerMessageText']
311 }
312 },
313
314 'changeCredentials_done': function() {
315 return {
316 'title': Clipperz.PM.Strings['changeCredentialsPanelDoneMessageTitle'],
317 'text': Clipperz.PM.Strings['changeCredentialsPanelDoneMessageText']
318 }
319 },
320
321
322 //-------------------------------------------------------------------------
323 //
324 //Account panel - change credentials
325 //
326 'saveOTP_encryptUserData': function() {
327 return {
328 'title': Clipperz.PM.Strings['saveOTP_encryptUserDataTitle'],
329 'text': Clipperz.PM.Strings['saveOTP_encryptUserDataText'],
330 'steps': '+4'
331 }
332 },
333
334 'saveOTP_encryptOTPData': function() {
335 return {
336 'title': Clipperz.PM.Strings['saveOTP_encryptOTPDataTitle'],
337 'text': Clipperz.PM.Strings['saveOTP_encryptOTPDataText']
338 }
339 },
340
341 'saveOTP_sendingData': function() {
342 return {
343 'title': Clipperz.PM.Strings['saveOTP_sendingDataTitle'],
344 'text': Clipperz.PM.Strings['saveOTP_sendingDataText']
345 }
346 },
347
348 'saveOTP_updatingInterface': function() {
349 return {
350 'title': Clipperz.PM.Strings['saveOTP_updatingInterfaceTitle'],
351 'text': Clipperz.PM.Strings['saveOTP_updatingInterfaceText']
352 }
353 },
354
355
356 //-------------------------------------------------------------------------
357 //
358 //Data panel - processingImportData
359 //
360 'parseImportData': function() {
361 return {
362 'title': Clipperz.PM.Strings['importData_parsingDataTitle'],
363 'text': Clipperz.PM.Strings['importData_parsingDataText']
364 }
365 },
366
367 'previewImportData': function() {
368 return {
369 'title': Clipperz.PM.Strings['importData_previewingDataTitle'],
370 'text': Clipperz.PM.Strings['importData_previewingDataText']
371 }
372 },
373
374 'processingImportData': function() {
375 return {
376 'title': Clipperz.PM.Strings['importData_processingDataTitle'],
377 'text': Clipperz.PM.Strings['importData_processingDataText']
378 }
379 },
380
381 //-------------------------------------------------------------------------
382 __syntaxFix__: "syntax fix"
383
384}
diff --git a/frontend/delta/js/Clipperz/PM/Strings/Strings_defaults.js b/frontend/delta/js/Clipperz/PM/Strings/Strings_defaults.js
new file mode 100644
index 0000000..aefd94a
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Strings/Strings_defaults.js
@@ -0,0 +1,385 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.Strings) == 'undefined') { Clipperz.PM.Strings = {}; }
27if (typeof(Clipperz.PM.Strings.Languages) == 'undefined') { Clipperz.PM.Strings.Languages = {}; }
28
29//=============================================================================
30//
31 // D E F A U L T S ( defaults )
32//
33//=============================================================================
34
35Clipperz.PM.Strings.Languages['defaults'] = {
36
37'elapsedTimeDescriptions': {
38 'MORE_THAN_A_MONTH_AGO': "more than a month ago",
39 'MORE_THAN_A_WEEK_AGO': "more than a week ago",
40 'MORE_THAN_*_WEEKS_AGO': "more than __elapsed__ weeks ago",
41 'YESTERDAY': "yesterday",
42 '*_DAYS_AGO': "__elapsed__ days ago",
43 'ABOUT_AN_HOUR_AGO': "about an hour ago",
44 '*_HOURS_AGO': "__elapsed__ hours ago",
45 'JUST_A_FEW_MINUTES_AGO': "just a few minutes ago",
46 'ABOUT_*_MINUTES_AGO': "about __elapsed__ minutes ago"
47},
48/*
49 'unknown_ip': "unknown",
50
51'countries': {
52 '--': "unknown",
53 'AD': "Andorra",
54 'AE': "United Arab Emirates",
55 'AF': "Afghanistan",
56 'AG': "Antigua and Barbuda",
57 'AI': "Anguilla",
58 'AL': "Albania",
59 'AM': "Armenia",
60 'AN': "Netherlands Antilles",
61 'AO': "Angola",
62 'AP': "Non-Spec Asia Pas Location",
63 'AR': "Argentina",
64 'AS': "American Samoa",
65 'AT': "Austria",
66 'AU': "Australia",
67 'AW': "Aruba",
68 'AX': "Aland Islands",
69 'AZ': "Azerbaijan",
70 'BA': "Bosnia and Herzegowina",
71 'BB': "Barbados",
72 'BD': "Bangladesh",
73 'BE': "Belgium",
74 'BF': "Burkina Faso",
75 'BG': "Bulgaria",
76 'BH': "Bahrain",
77 'BI': "Burundi",
78 'BJ': "Benin",
79 'BM': "Bermuda",
80 'BN': "Brunei Darussalam",
81 'BO': "Bolivia",
82 'BR': "Brazil",
83 'BS': "Bahamas",
84 'BT': "Bhutan",
85 'BW': "Botswana",
86 'BY': "Belarus",
87 'BZ': "Belize",
88 'CA': "Canada",
89 'CD': "Congo the Democratic Republic of the",
90 'CF': "Central African Republic",
91 'CH': "Switzerland",
92 'CI': "Cote D'ivoire",
93 'CK': "Cook Islands",
94 'CL': "Chile",
95 'CM': "Cameroon",
96 'CN': "China",
97 'CO': "Colombia",
98 'CR': "Costa Rica",
99 'CS': "Serbia and Montenegro",
100 'CU': "Cuba",
101 'CY': "Cyprus",
102 'CZ': "Czech Republic",
103 'DE': "Germany",
104 'DJ': "Djibouti",
105 'DK': "Denmark",
106 'DO': "Dominican Republic",
107 'DZ': "Algeria",
108 'EC': "Ecuador",
109 'EE': "Estonia",
110 'EG': "Egypt",
111 'ER': "Eritrea",
112 'ES': "Spain",
113 'ET': "Ethiopia",
114 'EU': "European Union",
115 'FI': "Finland",
116 'FJ': "Fiji",
117 'FM': "Micronesia Federated States of",
118 'FO': "Faroe Islands",
119 'FR': "France",
120 'GA': "Gabon",
121 'GB': "United Kingdom",
122 'GD': "Grenada",
123 'GE': "Georgia",
124 'GF': "French Guiana",
125 'GG': "Guernsey",
126 'GH': "Ghana",
127 'GI': "Gibraltar",
128 'GL': "Greenland",
129 'GM': "Gambia",
130 'GP': "Guadeloupe",
131 'GR': "Greece",
132 'GT': "Guatemala",
133 'GU': "Guam",
134 'GW': "Guinea-Bissau",
135 'GY': "Guyana",
136 'HK': "Hong Kong",
137 'HN': "Honduras",
138 'HR': "Croatia (Local Name: Hrvatska)",
139 'HT': "Haiti",
140 'HU': "Hungary",
141 'ID': "Indonesia",
142 'IE': "Ireland",
143 'IL': "Israel",
144 'IM': "Isle of Man",
145 'IN': "India",
146 'IO': "British Indian Ocean Territory",
147 'IQ': "Iraq",
148 'IR': "Iran (Islamic Republic of)",
149 'IS': "Iceland",
150 'IT': "Italy",
151 'JE': "Jersey",
152 'JM': "Jamaica",
153 'JO': "Jordan",
154 'JP': "Japan",
155 'KE': "Kenya",
156 'KG': "Kyrgyzstan",
157 'KH': "Cambodia",
158 'KI': "Kiribati",
159 'KN': "Saint Kitts and Nevis",
160 'KR': "Korea Republic of",
161 'KW': "Kuwait",
162 'KY': "Cayman Islands",
163 'KZ': "Kazakhstan",
164 'LA': "Lao People's Democratic Republic",
165 'LB': "Lebanon",
166 'LC': "Saint Lucia",
167 'LI': "Liechtenstein",
168 'LK': "Sri Lanka",
169 'LR': "Liberia",
170 'LS': "Lesotho",
171 'LT': "Lithuania",
172 'LU': "Luxembourg",
173 'LV': "Latvia",
174 'LY': "Libyan Arab Jamahiriya",
175 'MA': "Morocco",
176 'MC': "Monaco",
177 'MD': "Moldova Republic of",
178 'MG': "Madagascar",
179 'MH': "Marshall Islands",
180 'MK': "Macedonia the Former Yugoslav Republic of",
181 'ML': "Mali",
182 'MM': "Myanmar",
183 'MN': "Mongolia",
184 'MO': "Macau",
185 'MP': "Northern Mariana Islands",
186 'MR': "Mauritania",
187 'MS': "Montserrat",
188 'MT': "Malta",
189 'MU': "Mauritius",
190 'MV': "Maldives",
191 'MW': "Malawi",
192 'MX': "Mexico",
193 'MY': "Malaysia",
194 'MZ': "Mozambique",
195 'NA': "Namibia",
196 'NC': "New Caledonia",
197 'NF': "Norfolk Island",
198 'NG': "Nigeria",
199 'NI': "Nicaragua",
200 'NL': "Netherlands",
201 'NO': "Norway",
202 'NP': "Nepal",
203 'NR': "Nauru",
204 'NU': "Niue",
205 'NZ': "New Zealand",
206 'OM': "Oman",
207 'PA': "Panama",
208 'PE': "Peru",
209 'PF': "French Polynesia",
210 'PG': "Papua New Guinea",
211 'PH': "Philippines",
212 'PK': "Pakistan",
213 'PL': "Poland",
214 'PR': "Puerto Rico",
215 'PS': "Palestinian Territory Occupied",
216 'PT': "Portugal",
217 'PW': "Palau",
218 'PY': "Paraguay",
219 'QA': "Qatar",
220 'RO': "Romania",
221 'RS': "Serbia",
222 'RU': "Russian Federation",
223 'RW': "Rwanda",
224 'SA': "Saudi Arabia",
225 'SB': "Solomon Islands",
226 'SC': "Seychelles",
227 'SD': "Sudan",
228 'SE': "Sweden",
229 'SG': "Singapore",
230 'SI': "Slovenia",
231 'SK': "Slovakia (Slovak Republic)",
232 'SL': "Sierra Leone",
233 'SM': "San Marino",
234 'SN': "Senegal",
235 'SR': "Suriname",
236 'SV': "El Salvador",
237 'SY': "Syrian Arab Republic",
238 'SZ': "Swaziland",
239 'TC': "Turks and Caicos Islands",
240 'TG': "Togo",
241 'TH': "Thailand",
242 'TJ': "Tajikistan",
243 'TM': "Turkmenistan",
244 'TN': "Tunisia",
245 'TO': "Tonga",
246 'TR': "Turkey",
247 'TT': "Trinidad and Tobago",
248 'TV': "Tuvalu",
249 'TW': "Taiwan Province of China",
250 'TZ': "Tanzania United Republic of",
251 'UA': "Ukraine",
252 'UG': "Uganda",
253 'US': "United States",
254 'UY': "Uruguay",
255 'UZ': "Uzbekistan",
256 'VA': "Holy See (Vatican City State)",
257 'VE': "Venezuela",
258 'VG': "Virgin Islands (British)",
259 'VI': "Virgin Islands (U.S.)",
260 'VN': "Viet Nam",
261 'VU': "Vanuatu",
262 'WF': "Wallis and Futuna Islands",
263 'WS': "Samoa",
264 'YE': "Yemen",
265 'ZA': "South Africa",
266 'ZM': "Zambia",
267 'ZW': "Zimbabwe",
268 'ZZ': "Reserved"
269},
270
271'browsers': {
272 'UNKNOWN': "Unknown",
273 'MSIE': "Internet Explorer",
274 'FIREFOX': "Firefox",
275 'OPERA': "Opera",
276 'SAFARI': "Safari",
277 'OMNIWEB': "OmniWeb",
278 'CAMINO': "Camino",
279 'CHROME': "Chrome"
280},
281
282'operatingSystems': {
283 'UNKNOWN': "Unknown",
284 'WINDOWS': "Windows",
285 'MAC': "Mac",
286 'LINUX': "Linux",
287 'IPHONE': "iPhone",
288 'MOBILE': "Mobile",
289 'OPENBSD': "OpenBSD",
290 'FREEBSD': "FreeBSD",
291 'NETBSD': "NetBSD"
292},
293*/
294
295 //Calendar texts
296'calendarStrings': {
297 'months': {
298 '0':"January",
299 '1':"February",
300 '2':"March",
301 '3':"April",
302 '4':"May",
303 '5':"June",
304 '6':"July",
305 '7':"August",
306 '8':"September",
307 '9':"October",
308 '10':"November",
309 '11':"December"
310 },
311 'shortMonths':{
312 '0':"Jan",
313 '1':"Feb",
314 '2':"Mar",
315 '3':"Apr",
316 '4':"May",
317 '5':"Jun",
318 '6':"Jul",
319 '7':"Aug",
320 '8':"Sep",
321 '9':"Oct",
322 '10':"Nov",
323 '11':"Dec"
324 },
325
326 'days':{
327 '0':"Sunday",
328 '1':"Monday",
329 '2':"Tuesday",
330 '3':"Wednesday",
331 '4':"Thursday",
332 '5':"Friday",
333 '6':"Saturday"
334 },
335
336 'shortDays':{
337 '0':"Sun",
338 '1':"Mon",
339 '2':"Tue",
340 '3':"Wed",
341 '4':"Thu",
342 '5':"Fri",
343 '6':"Sat"
344 },
345
346 'veryShortDays':{
347 '0':"Su",
348 '1':"Mo",
349 '2':"Tu",
350 '3':"We",
351 '4':"Th",
352 '5':"Fr",
353 '6':"Sa"
354 },
355
356 'amDesignation':"am",
357 'pmDesignation':"pm"
358
359},
360
361// Date format
362 'fullDate_format':"l, F d, Y H:i:s",
363
364//################################################################################
365
366'pageHeader': {
367 'donation':"donate",
368 'forum':"forum",
369 'credits':"credits",
370 'feedback':"feedback",
371 'help': "help"
372},
373
374'bookmarkletCopy': {
375 'noExceptionMessage':"The direct login configuration has been collected.",
376 'exceptionMessage': "Sorry! There was an error while processing the page.",
377 'copy': "copy",
378 'successfulMessage':"DONE!",
379 'failMessage': "Failed! :("
380},
381
382//################################################################################
383
384__syntaxFix__: "syntax fix"
385}
diff --git a/frontend/delta/js/Clipperz/PM/Strings/Strings_en-US.js b/frontend/delta/js/Clipperz/PM/Strings/Strings_en-US.js
new file mode 100644
index 0000000..72460ba
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Strings/Strings_en-US.js
@@ -0,0 +1,1336 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24//=============================================================================
25//
26 // E N G L I S H A M E R I C A N ( en_US )
27//
28//=============================================================================
29
30Clipperz.PM.Strings.Languages['en-us'] = {
31/*
32 //Login page - description
33'clipperzServiceDescription': "\
34 <!-- FIX CSS DONE -->\
35 <h2>Keep it to yourself!</h2>\
36 <ul>\
37 <li>\
38 <h3>Clipperz is:</h3>\
39 <ul>\
40 <li><p>a secure and simple password manager</p></li>\
41 <li><p>an effective single sign-on solution</p></li>\
42 <li><p>a digital vault for your personal data</p></li>\
43 </ul>\
44 </li>\
45 <li>\
46 <h3>With Clipperz you can:</h3>\
47 <ul>\
48 <li><p>store and manage your passwords and online credentials</p></li>\
49 <li><p>login to your web services without entering any username or password</p></li>\
50 <li><p>protect all your sensitive data: codes for burglar alarms, PINs, credit card numbers, …</p></li>\
51 <li><p>share secrets with family members and associates (coming soon)</p></li>\
52 </ul>\
53 </li>\
54 <li>\
55 <h3>Clipperz benefits:</h3>\
56 <ul>\
57 <li><p>free and completely anonymous</p></li>\
58 <li><p>access it any time from any computer</p></li>\
59 <li><p>no software to download and nothing to install</p></li>\
60 <li><p>avoid keeping secrets on your PC or on paper</p></li>\
61 </ul>\
62 </li>\
63 <li>\
64 <h3>Clipperz security:</h3>\
65 <ul>\
66 <li><p>your secrets are locally encrypted by your browser before being uploaded to Clipperz</p></li>\
67 <li><p>the encryption key is a passphrase known only to you</p></li>\
68 <li><p>Clipperz hosts your sensitive data in encrypted form and could never actually access the data in its plain form</p></li>\
69 <li><p>Clipperz is built upon standard encryption schemes, nothing fancies or homemade</p></li>\
70 <li><p>you can review the source code anytime you like, but you need to know nothing about cryptography to be an happy user!</p></li>\
71 </ul>\
72 </li>\
73 <li>\
74 <a href=\"http://www.clipperz.com\" target=\"_blank\">Learn more</a>\
75 </li>\
76 </ul>",
77
78
79 'loginFormTitle': "login with your Clipperz account",
80 'loginFormUsernameLabel': "username",
81 'loginFormPassphraseLabel': "passphrase",
82 'loginFormDontHaveAnAccountLabel': "don\'t have an account?",
83 'loginFormCreateOneLabel': "create one",
84 'loginFormForgotYourCredentialsLabel': "forgot your credentials?",
85 'loginFormAarghThatsBadLabel': "aargh! that\'s bad!",
86 'loginFormAfraidOfMaliciousScriptsLabel': "afraid of malicious scripts?",
87 'loginFormVerifyTheCodeLabel': "verify the code",
88 'loginFormButtonLabel': "Login",
89 'loginFormOneTimePasswordCheckboxLabel': "use a one-time passphrase",
90'loginFormOneTimePasswordCheckboxDescription': "",
91
92// Login page - language selection
93 'loginPanelSwithLanguageDescription': "<h5>Switch to your preferred language</h5>",
94
95// Login page - browser compatibility
96 'browserCompatibilityDescription': "<p>Have a better and safer Clipperz experience with Firefox. However Clipperz works just fine also with Opera, Safari and MS Internet Explorer!</p>",
97
98// Login with OTP - message panel
99 'OTPloginMessagePanelInitialTitle': "Logging in using a one-time passphrase",
100 'OTPloginMessagePanelInitialText': "Sending OTP credentials …",
101 'OTPloginMessagePanelLoadingTitle': "Logging in using a one-time passphrase",
102 'OTPloginMessagePanelLoadingText': "Fetching encrypted authentication data from the server …",
103 'OTPloginMessagePanelProcessingTitle': "Logging in using a one-time passphrase",
104 'OTPloginMessagePanelProcessingText': "Local decryption of authentication data",
105
106// Regular login - message panel
107 'loginMessagePanelInitialTitle': "Logging in …",
108 'loginMessagePanelInitialText': "---",
109 'loginMessagePanelInitialButtonLabel': "Cancel",
110 'loginMessagePanelConnectedTitle': "Connected",
111 'loginMessagePanelConnectedText': "Done",
112 'loginMessagePanelFailureTitle': "Error",
113 'loginMessagePanelFailureText': "Login failed",
114 'loginMessagePanelFailureButtonLabel': "Close",
115
116// Regular login - message panel - connection
117 'connectionLoginSendingCredentialsMessageTitle': "Verifying credentials",
118 'connectionLoginSendingCredentialsMessageText': "Sending credentials",
119 'connectionLoginCredentialsVerificationMessageTitle':"Verifying credentials",
120 'connectionLoginCredentialsVerificationMessageText':"Performing SRP authentication",
121 'connectionLoginDoneMessageTitle': "Verifying credentials",
122 'connectionLoginDoneMessageText': "Connected",
123
124 //Regular login - message panel - user
125 'userLoginPanelUpgradingUserCredentialsMessageTitle': "Verifying credentials",
126 'userLoginPanelUpgradingUserCredentialsMessageText': "Upgrading your credentials to a new authentication schema",
127 'userLoginPanelConnectedMessageTitle': "User authenticated",
128 'userLoginPanelConnectedMessageText': "Successfully logged in",
129 'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Verifying credentials",
130 'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Trying an older authentication schema",
131 'userLoginPanelLoadingUserDataMessageTitle': "User authenticated",
132 'userLoginPanelLoadingUserDataMessageText': "Downloading encrypted card headers from Clipperz",
133 'userLoginPanelDecryptingUserDataMessageTitle': "User authenticated",
134 'userLoginPanelDecryptingUserDataMessageText': "Local decryption of card headers",
135 'userLoginPanelDecryptingUserStatisticsMessageTitle': "User authenticated",
136 'userLoginPanelDecryptingUserStatisticsMessageText': "Local decryption of usage statistics",
137
138 //Registration page - splash alert
139 'splashAlertTitle':"Welcome to Clipperz!",
140'splashAlertText': "\
141 <!-- FIX CSS DONE! -->\
142 <p>Some security advice</p>\
143 <ul>\
144 <li><p>Storing your data at Clipperz is as secure as the passphrase you choose to protect them. Nobody can access them unless they know your passphrase.</p></li>\
145 <li><p>If you are going to use Clipperz for safeguarding sensitive and critical information please make sure to use a strong passphrase. The longer the better!</p></li>\
146 <li><p>Clipperz will not be able to recover a lost passphrase!</p></li>\
147 </ul>\
148 <p>For any further information, please refer to <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a> website.</p>",
149 'splashAlertCloseButtonLabel':"Ok",
150
151 // Registration page - form
152 'registrationFormTitle': "create your account",
153 'registrationFormUsernameLabel': "username",
154 'registrationFormPassphraseLabel': "passphrase",
155 'registrationFormRetypePassphraseLabel': "re-enter passphrase",
156 'registrationFormSafetyCheckLabel': "I understand that Clipperz will not be able to recover a lost passphrase.",
157 'registrationFormTermsOfServiceCheckLabel': "I have read and agreed to the <a href='https://www.clipperz.com/terms_service' target='_blank'>Terms of Service</a>.",
158 'registrationFormDoYouAlreadyHaveAnAccountLabel': "do you already have an account?",
159 'registrationFormSimplyLoginLabel': "simply login",
160 'registrationFormButtonLabel': "Register",
161
162// Registration page - warning messages
163 'registrationFormWarningMessageNotMatchingPassphrases':"Your passphrases don't match, please re-type them.",
164 'registrationFormWarningMessageSafetyCheckNotSelected':"Please read and check all the boxes below.",
165 'registrationFormWarningMessageTermsOfServiceCheckNotSelected':"You need to agree to the Terms of Service.",
166
167 // Registration page - message panel
168 'registrationMessagePanelInitialTitle': "Creating account …",
169 'registrationMessagePanelInitialText': "---",
170 'registrationMessagePanelInitialButtonLabel': "Cancel",
171 'registrationMessagePanelRegistrationDoneTitle': "Registration",
172 'registrationMessagePanelRegistrationDoneText': "Done",
173 'registrationMessagePanelFailureTitle': "Registration failed",
174 'registrationMessagePanelFailureButtonLabel': "Close",
175
176// Registration page - message panel - connection
177 'connectionRegistrationSendingRequestMessageText': "Verifying credentials",
178 'connectionRegistrationSendingCredentialsMessageText':"Sending credentials",
179
180// Registration page - splash panel
181 'registrationSplashPanelTitle': "Security advice",
182 'registrationSplashPanelDescription': "<p>These are your Clipperz credentials, take good care of them. Clipperz will never display your username and passphrase a second time!</p>",
183 'registrationSplashPanelUsernameLabel': "username",
184 'registrationSplashPanelPassphraseLabel':"passphrase",
185
186 'registrationSplashPanelShowPassphraseButtonLabel':"show passphrase",
187
188 //Header links
189 'donateHeaderLinkLabel': "donate",
190 'creditsHeaderLinkLabel': "credits",
191 'feedbackHeaderLinkLabel': "feedback",
192 'helpHeaderLinkLabel': "help",
193 'forumHeaderLinkLabel': "forum",
194
195 //Menu labels
196 'recordMenuLabel': "cards",
197 'accountMenuLabel': "account",
198 'dataMenuLabel': "data",
199 'contactsMenuLabel': "contacts",
200 'toolsMenuLabel': "tools",
201 'logoutMenuLabel': "logout",
202 'lockMenuLabel': "lock",
203
204 //Lock dialog
205 'lockTitle': "The account is locked",
206 'lockDescription': "<p>To unlock your account, please enter your passphrase.</p>",
207 'unlockButtonLabel': "Unlock",
208
209 //Account panel - change passphrase
210 'changePasswordTabLabel': "Change your passphrase",
211 'changePasswordTabTitle': "Change your passphrase",
212
213 'changePasswordFormUsernameLabel': "username",
214 'changePasswordFormOldPassphraseLabel': "old passphrase",
215 'changePasswordFormNewPassphraseLabel': "new passphrase",
216 'changePasswordFormRetypePassphraseLabel':"re-enter new passphrase",
217 'changePasswordFormSafetyCheckboxLabel':"I understand that Clipperz will not be able to recover a lost passphrase.",
218 'changePasswordFormSubmitLabel': "Change passphrase",
219
220 //Account panel - change passphrase - warning messages
221 'changePasswordFormWrongUsernameWarning': "Wrong username",
222 'changePasswordFormWrongPassphraseWarning': "Wrong passphrase",
223 'changePasswordFormWrongRetypePassphraseWarning':"Your passphrases don't match, please re-type them.",
224 'changePasswordFormSafetyCheckWarning': "Please read and check the box below.",
225
226 //Account panel - change passphrase - progress dialog
227 'changePasswordFormProgressDialogTitle': "Changing user credentials",
228 'changePasswordFormProgressDialogEmptyText': "---",
229 'changePasswordFormProgressDialogConnectedMessageTitle': "Connected",
230 'changePasswordFormProgressDialogConnectedMessageText': "Done",
231 'changePasswordFormProgressDialogErrorMessageTitle': "Error",
232 'changePasswordFormProgressDialogErrorMessageText': "Credentials change failed!",
233
234 'changeCredentialsPanelEncryptingDataMessageTitle': "Changing your passphrase",
235 'changeCredentialsPanelEncryptingDataMessageText': "Local encryption of card headers",
236 'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Changing your passphrase",
237 'changeCredentialsPanelCreatingNewCredentialsMessageText': "Updating your credentials",
238 'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle':"Changing your passphrase",
239 'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText':"Uploading your encrypted credentials to Clipperz",
240 'changeCredentialsPanelDoneMessageTitle': "Changing your passphrase",
241 'changeCredentialsPanelDoneMessageText': "Done",
242
243 //Account panel - OTP
244 'manageOTPTabLabel': "Manage your one-time passphrases",
245 'manageOTPTabTitle': "Manage your one-time passphrases",
246
247 'manageOTPTabDescription':"\
248 <p>A one-time passphrase works like your regular passphrase, but can be used only once.</p>\
249 <p>If the same passphrase is used again at a later stage in a login attempt it will be rejected and the login process will fail.</p>\
250 <p>Immediately after a successful login, your one-time passphrase will be deleted preventing any fraudulent access.</p>\
251 <p>One-time passphrases are an excellent choice if one is concerned about keyloggers or spyware infections that may be collecting data from compromised machines.</p>\
252 <p><b>It's strongly advisable to use one-time passphrases when accessing Clipperz from public terminals, such as Internet cafes and libraries.</b></p>",
253
254 //Account panel - OTP - OTP table
255'oneTimePasswordReadOnlyMessage': "\
256 <h6>Sorry!</h6>\
257 <p>You cannot manage your one-time passphrases when using the offline version of Clipperz.</p>",
258
259 'oneTimePasswordLoadingMessage':"\
260 <h6>Loading data</h6>\
261 <p>Please wait …</p>",
262
263 'oneTimePasswordNoPasswordAvailable':"\
264 <h6>No one-time passphrase available</h6>\
265 <p>Click the “New” button above to add one-time passphrases to your account.</p>",
266
267 'createNewOTPButtonLabel': "New",
268 'deleteOTPButtonLabel': "Delete",
269 'printOTPButtonLabel': "Print",
270
271 'disabledOneTimePassword_warning': "disabled",
272
273 'oneTimePasswordSelectionLink_selectLabel':"Select:",
274 'oneTimePasswordSelectionLink_all': "all",
275 'oneTimePasswordSelectionLink_none': "none",
276 'oneTimePasswordSelectionLink_used': "used",
277 'oneTimePasswordSelectionLink_unused': "unused",
278
279//Account panel - OTP - saving new OTP dialog
280 'saveOTP_encryptUserDataTitle': "Saving one-time passphrase",
281 'saveOTP_encryptUserDataText': "Processing new OTP credentials …",
282 'saveOTP_encryptOTPDataTitle': "Saving one-time passphrase",
283 'saveOTP_encryptOTPDataText': "Local encryption of authentication data …",
284 'saveOTP_sendingDataTitle': "Saving one-time passphrase",
285 'saveOTP_sendingDataText': "Sending authentication data to the server …",
286 'saveOTP_updatingInterfaceTitle': "Saving one-time passphrase",
287 'saveOTP_updatingInterfaceText': "Updating interface",
288
289// Account panel - preferences
290 'accountPreferencesLabel': "Preferences",
291 'accountPreferencesTabTitle': "Preferences",
292
293 'accountPreferencesLanguageTitle': "Language",
294 'accountPreferencesLanguageDescription':"<p>Choose your preferred language from the list below.</p>",
295
296 'showDonationReminderPanelTitle': "Donation reminders",
297 'showDonationReminderPanelDescription': "<p>Show donation reminders</p>",
298
299 'saveUserPreferencesFormSubmitLabel': "Save",
300 'cancelUserPreferencesFormSubmitLabel': "Cancel",
301
302// Account panel - preferences - saving dialog
303 'accountPreferencesSavingPanelTitle_Step1': "Saving preferences",
304 'accountPreferencesSavingPanelText_Step1': "Local encryption of your preferences",
305 'accountPreferencesSavingPanelTitle_Step2': "Saving preferences",
306 'accountPreferencesSavingPanelText_Step2': "Sending encrypted preferences to Clipperz",
307
308 //Account panel - login history
309 'accountLoginHistoryLabel': "Login history",
310 'loginHistoryTabTitle': "Login history",
311
312 'loginHistoryReadOnlyMessage': "\
313 <h6>Sorry!</h6>\
314 <p>The login history is not available while using the offline version of Clipperz.</p>",
315
316 'loginHistoryLoadingMessage': "\
317 <h6>Loading data</h6>\
318 <p>Please wait …</p>",
319
320 'loginHistoryLoadedMessage': "\
321 <h6>Your latest 10 logins</h6>\
322 <p></p>",
323
324 'loginHistoryIPLabel': "IP",
325 'loginHistoryTimeLabel': "date",
326 'loginHistoryCurrentSessionText': "current session",
327 'loginHistoryReloadButtonLabel': "Reload login history",
328
329 //Account panel - delete account
330 'deleteAccountTabLabel': "Delete your account",
331 'deleteAccountTabTitle': "Delete your account",
332
333 'deleteAccountFormUsernameLabel': "username",
334 'deleteAccountFormPassphraseLabel': "passphrase",
335 'deleteAccountFormSafetyCheckboxLabel': "I understand that all my data will be deleted and that this action is irreversible.",
336 'deleteAccountFormSubmitLabel': "Delete my account",
337
338//Account panel - delete account - warnings
339 'deleteAccountFormWrongUsernameWarning':"Wrong username",
340 'deleteAccountFormWrongPassphraseWarning':"Wrong passphrase",
341 'deleteAccountFormSafetyCheckWarning': "Please read and check the box below.",
342
343//Account panel - delete account - confirmation
344 'accountPanelDeletingAccountPanelConfirmationTitle':"ATTENTION",
345 'accountPanelDeleteAccountPanelConfirmationText': "Are your sure you want to delete your account?",
346 'accountPanelDeleteAccountPanelConfirmButtonLabel': "Yes",
347 'accountPanelDeleteAccountPanelDenyButtonLabel': "No",
348
349//Account panel - delete account - confirmation
350 'accountPanelDeletingAccountPanelProgressTitle': "Deleting the account data",
351 'accountPanelDeletingAccountPanelProgressText': "The operation could take long, please be patient.",
352
353//Data panel - offline copy
354 'offlineCopyTabLabel': "Offline copy",
355 'offlineCopyTabTitle': "Offline copy",
356
357'offlineCopyTabDescription': "\
358 <!-- FIX CSS DONE! -->\
359 <p>With just one click you can dump all your encrypted data from Clipperz servers to your hard disk and create a read-only offline version of Clipperz to be used when you are not connected to the Internet.</p>\
360 <p>The read-only version is as secure as the read-and-write one and will not expose your data to higher risks since they both share the same code and security architecture.</p>\
361 <ol>\
362 <li><p>Click the link below to start the download.</p></li>\
363 <li><p>The browser will ask you what to do with the “Clipperz_YYYYMMDD.html” file. Save it on your hard disk.</p></li>\
364 <li><p>Double click on the downloaded file to launch the offline version in your browser.</p></li>\
365 <li><p>Enter the usual username and passphrase.</p></li>\
366 </ol>",
367
368 'offlineCopyDownloadLinkLabel': "Download",
369
370 //Data panel - offline copy - not updated
371 'offlineCopyDownloadWarning': "\
372 <!-- FIX CSS DONE! -->\
373 <h4><a href=\"#\" id=\"offlineCopyDownloadWarningLink\">Update your “offline copy”!</a></h4>\
374 <p>You have recently created or modified one or more cards, it would be wise to download a new copy of the offline version.</p>",
375
376 'offlineCopyDownloadOk': "",
377
378 //Data panel - sharing
379 'sharingTabLabel': "Sharing",
380 'sharingTabTitle': "Sharing",
381
382 'sharingTabDescription': "\
383 <p>Quite often a confidential piece of information needs to be shared with one or more persons.</p>\
384 <p>This could be as simple as giving your colleague the access code of your voice mailbox when you are out of the office, or as complicated as enabling the entitled heirs to access your safe deposit box at the local bank when you pass on.</p>\
385 <p>Clipperz can make sharing your secrets a secure and straightforward process.</p>\
386 <p></p>\
387 <p><b>Coming soon …</b></p>",
388
389 // Data panel - import
390 'importTabLabel': "Import",
391 'importTabTitle': "Import",
392
393 'importTabDescription': "<p>You can bulk import data to your Clipperz account from several file formats.</p>",
394
395 //Data panel - export
396 'printingTabLabel': "Export",
397 'printingTabTitle': "Export",
398
399 'printingTabDescription': "\
400 <h5>Printing</h5>\
401 <p>Click on the link below to open a new window displaying all your cards in a printable format.</p>\
402 <p>If you are going to print for backup purposes, please consider the safer option provided by the “offline copy”.</p>",
403
404 'printingLinkLabel': "Printable version",
405
406 'exportTabDescription': "\
407 <h5>Exporting to JSON</h5>\
408 <p>JSON enables a “lossless” export of your cards. All the information will be preserved, including direct login configurations.</p>\
409 <p>This custom format it’s quite convenient if you need to move some of all of your cards to a different Clipperz account. Or if you want to restore a card that has been accidentally deleted.</p>\
410 <p>Click on the link below to start the export process.</p>",
411
412 'exportLinkLabel': "Export to JSON",
413
414 'exportDataInProgressDescription':"<h4>Exporting, please wait while your data are being processed …</h4>",
415
416 'exportDataDescription': "\
417 <h4>Instructions</h4>\
418 <p>Copy the text below to your favorite editor and save it. (e.g. “clipperz_export_20071217.json”)</p>",
419
420 //Contacts panel
421 'contactsTabLabel': "Contacts",
422 'contactsTabTitle': "Contacts",
423
424//Tools panel - password generator
425 'passwordGeneratorTabLabel': "Password generator",
426 'bookmarkletTabLabel': "Bookmarklet",
427 'compactTabLabel': "Compact edition",
428 'httpAuthTabLabel': "HTTP authentication",
429
430 'passwordGeneratorTabTitle': "Password generator",
431 'bookmarkletTabTitle': "Bookmarklet",
432 'compactTabTitle': "Compact edition",
433 'httpAuthTabTitle': "HTTP authentication",
434
435
436 //Tools panel - password generator - description
437 'paswordGeneratorTabDescription':"<p></p>",
438 'passwordGeneratorTabButtonLabel':"Generate password",
439
440 //Tools panel - bookmarklet
441 'bookmarkletTabLabel': "Bookmarklet",
442 'bookmarkletTabTitle': "Bookmarklet",
443
444 'bookmarkletTabDescription': "\
445 <!-- FIX CSS DONE! -->\
446 <p>A bookmarklet is a simple “one-click” tool that can perform very useful tasks. It can be saved and used like a normal web page bookmark.</p>\
447 <p>The Clipperz bookmarklet will help you to quickly create new cards and new “direct logins” within existing cards.</p>\
448 <p><b>Please note that the bookmarklet does not include any information related to your account (e.g. your username or passphrase), the bookmarklet is a general tool containing the same code for every Clipperz user.</b></p>\
449 <h3>How to install the bookmarklet</h3>\
450 <h>Firefox, Camino, Opera, Safari</h5>\
451 <ol>\
452 <li><p>Make sure that the “Bookmarks Bar” is displayed by selecting “View > Toolbars > Bookmarks”, or similar menu items, from the browser menu.</p></li>\
453 <li><p>Drag and drop the “Add to Clipperz” link below to the bookmark bar.</p></li>\
454 </ol>\
455 \
456 <h5>Internet Explorer</h5>\
457 <ol>\
458 <li><p>Make sure that the “Links” toolbar is displayed by selecting “View > Toolbars > Links” from the browser menu.</p></li>\
459 <li><p>Right-click on the “Add to Clipperz” link below.</p></li>\
460 <li><p>Select “Add to favorites” from the contextual menu.</p></li>\
461 <li><p>Click “Yes” for any security message that pops up.</p></li>\
462 <li><p>Open the “Links” folder and click “OK”</p></li>\
463 </ol>",
464
465 'bookmarkletTabBookmarkletTitle':"Add to Clipperz",
466
467 //Tools panel - bookmarklet - instructions
468 'bookmarkletTabInstructions': "\
469 <!-- FIX CSS DONE! -->\
470 <h3>How to create a new card inclusive of a “direct login” link to an online service</h3>\
471 <ol>\
472 <li><p>Open the web page where the login form is hosted. (this is the page where you usually enter your sign-in credentials)</p></li>\
473 <li><p>Launch the bookmarklet by clicking on it: a pop-up window will appear over the web page.</p></li>\
474 <li><p>Copy to the clipboard the content of the large text area within the pop-up. (ctrl-C)</p></li>\
475 <li><p>Enter your Clipperz account and click on the <b>Add new card</b> button.</p></li>\
476 <li><p>Select the “Direct login” template and paste the content of the clipboard to the large text area in the form. (ctrl-V)</p></li>\
477 <li><p>Press the <b>Create</b> button, complete and review the details, then click <b>Save</b>.</p></li>\
478 </ol>\
479 \
480 <h3>How to add a “direct login” link to an existing card</h3>\
481 <ol>\
482 <li><p>Same as above.</p></li>\
483 <li><p>Same as above.</p></li>\
484 <li><p>Same as above.</p></li>\
485 <li><p>Enter your Clipperz account and select the card containing the credentials for the web service you just visited and click the <b>Edit</b> button.</p></li>\
486 <li><p>Paste the content of the clipboard to the large text area in the “Direct logins” section. (ctrl-V)</p></li>\
487 <li><p>Press the <b>Add direct login</b> button, review the details and then click <b>Save</b>.</p></li>\
488 </ol>\
489 \
490 <p></p>\
491 <p>Further information about the bookmarklet are <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">available here</a>.</p>",
492
493 //Tools panel - Compact - instructions
494 'compactTabDescription': "\
495 <!-- FIX CSS DONE! -->\
496 <p>Clipperz Compact is a special version of Clipperz designed to be opened in the Firefox sidebar.</p>\
497 <p>Its purpose is to keep your collection of “direct logins” always at hand. Read more <a href=\"http://www.clipperz.com/support/user_guide/clipperz_compact\", target=\"blank\">here</a></p>\
498 \
499 <h3>How to launch Clipperz Compact in the sidebar</h3>\
500 <ol>\
501 <li><p>Get Firefox! Sidebars are only available in Firefox and you need to switch to Firefox in order to enjoy the convenience of Clipperz Compact.</p></li>\
502 <li>\
503 <p>Add the following URL to Firefox bookmarks, or even better, drag it to the bookmark bar.</p>\
504 <div id=\"compactLinkBox\"><a href=\"https://www.clipperz.com/beta/index.html?compact\" target=\"_search\">Clipperz Compact</a></div>\
505 </li>\
506 <li><p>Change the properties of the bookmark so that “load this bookmark in the sidebar” is checked.</p></li>\
507 </ol>\
508 \
509 <h5>Added bonus: Clipperz Compact works also in Opera’s panel.</h5>",
510
511 //Tools panel - HTTP authentication - instructions
512 'httpAuthTabDescription': "\
513 <!-- FIX CSS DONE! -->\
514 <p>HTTP authentication is a method designed to allow a web browser to provide credentials – in the form of a username and password – including them in a website address (HTTP or HTTPS URL).</p>\
515 <p>Nowadays it is rarely used, but it can still be found on small, private websites. You can tell that a website is protected by HTTP authentication when the browser displays a pop-up window to enter username and password.</p>\
516 <p>Unfortunately the Clipperz bookmarklet does not work on websites that use HTTP authentication. However you can still create a “direct login”.</p>\
517 \
518 <h3>How to create a “direct login” for a website that uses HTTP authentication</h3>\
519 <ol>\
520 <li><p>Store website URL, username and password in a new card.</p></li>\
521 <li><p>Copy the configuration below and paste it to the large text area in the “Direct logins” section of the new card.</p></li>\
522 <li><p>Press the <b>Add direct login</b> button, bind URL, username and password fields and then click <b>Save</b>.</p></li>\
523 </ol>\
524 \
525 <h5><a href=\"http://support.microsoft.com/kb/834489\" target=\"_blank\">Warning: Internet Explorer does not support HTTP authentication.</a></h5>",
526
527// Direct logins block
528 'mainPanelDirectLoginBlockLabel': "Direct logins",
529 'directLinkReferenceShowButtonLabel': "show",
530
531// Direct logins - blank slate
532 'mainPanelDirectLoginBlockDescription': "\
533 <!-- FIX CSS DONE! -->\
534 <p>Add “direct logins” to sign in to your web accounts without typing usernames and passwords!</p>\
535 <p>“Direct logins” greatly enhance your password security since you can:</p>\
536 <ul>\
537 <li><p>conveniently adopt and enter complex passwords;</p></li>\
538 <li><p>never re-use the same and easy-to-guess password.</p></li>\
539 </ul>\
540 <p>Simple and quick configuration with the <b>Clipperz bookmarklet</b>.</p>\
541 <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Learn more about “direct logins”</a>",
542
543 // Cards block
544 'mainPanelRecordsBlockLabel': "Cards",
545 'mainPanelAddRecordButtonLabel': "Add new card",
546 'mainPanelRemoveRecordButtonLabel': "Delete card",
547
548// Cards block - filter tabs
549 'mainPanelRecordFilterBlockAllLabel': "all",
550 'mainPanelRecordFilterBlockTagsLabel': "tags",
551 'mainPanelRecordFilterBlockSearchLabel':"search",
552
553// Cards block - blank slate
554 'recordDetailNoRecordAtAllTitle': "Welcome to Clipperz!",
555 'recordDetailNoRecordAtAllDescription': "\
556 <h5>Get started by adding cards to your account.</h5>\
557 <p>Cards are simple and flexible forms where you can store your passwords and any other confidential data.</p>\
558 <p>Cards could contain credentials for accessing a web site, the combination of your bicycle lock, details of your credit card, …</p>\
559 \
560 <h5>Don't forget the Clipperz bookmarklet!</h5>\
561 <p>Before you start, install the “Add to Clipperz” bookmarklet: it will make creating cards easier and more fun.</p>\
562 <p>Go to the “Tools” tab to discover how to install it and how it use it.</p>\
563 <p></p>\
564 <p>Then simply click the <b>\"Add new card\"</b> button and enjoy your Clipperz account.</p>\
565 <p></p>\
566 <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Learn more about creating and managing cards</a>",
567
568// Cards block - new card wizard - bookmarklet configuration
569 'newRecordWizardTitleBox': "\
570 <h5>Please select a template</h5>\
571 <p>Cards are simple and flexible forms where you can store passwords or any other confidential data.</p>\
572 <p>Start choosing one of the templates below. You can always customize your cards later by adding or removing fields.</p>",
573
574 'newRecordWizardBookmarkletConfigurationTitle': "Direct login",
575 'newRecordWizardBookmarkletConfigurationDescription':"\
576 <p>Paste below the configuration code generated by the Clipperz bookmarklet.</p>\
577 <p>A new card complete with a direct login to your web account will be created.</p>",
578
579 'newRecordWizardCreateButtonLabel': "Create",
580 'newRecordWizardCancelButtonLabel': "Cancel",
581
582 //Create new card - Donation splash
583 'donateSplashPanelTitle': "Support Clipperz, make a donation today!",
584 'donateSplashPanelDescription': "\
585 <!-- FIX CSS DONE! -->\
586 <p>A few good reasons to make a donation:</p>\
587 <ul>\
588 <li><p>support the development of new features</p></li>\
589 <li><p>keep Clipperz free</p></li>\
590 <li><p>show appreciation for our hard work</p></li>\
591 </ul>\
592 <p>For any further information, please visit our <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">Donations page</a>.</p>\
593 <p><b>Ready to donate?</b></p>",
594
595 'donateCloseButtonLabel': "Not yet",
596 'donateDonateButtonLabel': "Yes",
597
598// Card templates
599'recordTemplates': {
600
601//Web password
602 'WebAccount': {
603 'title': "Web password",
604 'description':"<p>A simple card to store login credentials for your online services.</p>",
605 'fields': [
606 {label:"Web address", type:'URL'},
607 {label:"Username or email", type:'TXT'},
608 {label:"Password", type:'PWD'}
609 ]
610 },
611
612 //Bank account
613 'BankAccount': {
614 'title': "Bank account",
615 'description':"<p>Safely store your bank account number and online banking credentials.</p>",
616 'fields': [
617 {label:"Bank", type:'TXT'},
618 {label:"Account number", type:'TXT'},
619 {label:"Bank website", type:'URL'},
620 {label:"Online banking ID", type:'TXT'},
621 {label:"Online banking password", type:'PWD'}
622 ]
623 },
624
625 // Credit card
626 'CreditCard': {
627 'title': "Credit card",
628 'description':"<p>Card number, expire date, CVV2 and PIN always at hand with Clipperz.</p>",
629 'fields': [
630 {label:"Type (Visa, AmEx, …)", type:'TXT'},
631 {label:"Number", type:'TXT'},
632 {label:"Owner name", type:'TXT'},
633 {label:"Expiry date", type:'TXT'},
634 {label:"CVV2", type:'TXT'},
635 {label:"PIN", type:'PWD'},
636 {label:"Card website", type:'URL'},
637 {label:"Username", type:'TXT'},
638 {label:"Password", type:'PWD'}
639 ]
640 },
641
642 // Address book entry
643 'AddressBookEntry': {
644 'title': "Address book entry",
645 'description':"<p>Clipperz could also work as your new private address book. Use this template to easily add a new entry.</p>",
646 'fields': [
647 {label:"Name", type:'TXT'},
648 {label:"Email", type:'TXT'},
649 {label:"Phone", type:'TXT'},
650 {label:"Mobile", type:'TXT'},
651 {label:"Address", type:'ADDR'}
652 ]
653 },
654
655//Custom card
656 'Custom': {
657 'title': "Custom card",
658 'description':"<p>No matter which kind of confidential data you need to protect, create a custom card to match your needs.</p>",
659 'fields': [
660 {label:"Label 1", type:'TXT'},
661 {label:"Label 2", type:'TXT'},
662 {label:"Label 3", type:'TXT'}
663 ]
664 }
665},
666
667
668'recordFieldTypologies': {
669 'TXT': {
670 description: "simple text field",
671 shortDescription: "text"
672 },
673 'PWD': {
674 description: "simple text field, with default status set to hidden",
675 shortDescription: "password"
676 },
677 'URL': {
678 description: "simple text field in edit mode, that became an active url in view mode",
679 shortDescription: "web address"
680 },
681 'DATE': {
682 description: "a value set with a calendar helper",
683 shortDescription: "date"
684 },
685 'ADDR': {
686 description: "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
687 shortDescription: "street address"
688 },
689 'CHECK': {
690 description: "check description",
691 shortDescription: "check"
692 },
693 'RADIO': {
694 description: "radio description",
695 shortDescription: "radio"
696 },
697 'SELECT': {
698 description: "select description",
699 shortDescription: "select"
700 }
701},
702
703// Cards block - new card - warnings
704 'newRecordPanelGeneralExceptionTitle': "Error",
705 'newRecordPanelGeneralExceptionMessage': "The configuration text is not valid. Make sure to get your text from the bookmarklet pop-up and retry.",
706 'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Error",
707 'newRecordPanelWrongBookmarkletVersionExceptionMessage':"The configuration text has been generated by an old version of the bookmarklet. Please update your bookmarklet and retry.",
708 'newRecordPanelExceptionPanelCloseButtonLabel': "Cancel",
709
710// Cards block - delete card
711 'mainPanelDeletingRecordPanelConfirmationTitle': "Deleting selected card",
712 'mainPanelDeleteRecordPanelConfirmationText': "Do your really want to delete the selected card?",
713 'mainPanelDeleteRecordPanelConfirmButtonLabel': "Yes",
714 'mainPanelDeleteRecordPanelDenyButtonLabel': "No",
715 'mainPanelDeletingRecordPanelInitialTitle': "Deleting selected card",
716 'mainPanelDeletingRecordPanelInitialText': "---",
717 'mainPanelDeletingRecordPanelCompletedText': "Done",
718
719// Cards block - delete card panel
720 'deleteRecordPanelCollectRecordDataMessageTitle': "Delete card",
721 'deleteRecordPanelCollectRecordDataMessageText': "Updating card list",
722 'deleteRecordPanelEncryptUserDataMessageTitle': "Delete card",
723 'deleteRecordPanelEncryptUserDataMessageText': "Local encryption of card headers",
724 'deleteRecordPanelSendingDataToTheServerMessageTitle': "Delete card",
725 'deleteRecordPanelSendingDataToTheServerMessageText': "Uploading encrypted card headers to Clipperz",
726 'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Delete card",
727 'deleteRecordPanelUpdatingTheInterfaceMessageText': "Updating the interface",
728
729// Cards block - no record selected
730 'recordDetailNoRecordSelectedTitle': "No card selected",
731 'recordDetailNoRecordSelectedDescription': "<p>Please select a card from the list on the left.</p>",
732
733 // Cards block - loading messages
734 'recordDetailLoadingRecordMessage': "Downloading encrypted card from Clipperz",
735 'recordDetailDecryptingRecordMessage': "Local decryption of card\'s data",
736 'recordDetailLoadingRecordVersionMessage': "Downloading latest card version",
737 'recordDetailDecryptingRecordVersionMessage': "Local decryption of latest version",
738 'recordDetailLoadingErrorMessageTitle': "Error while downloading the card",
739
740// Cards block - card details
741 'recordDetailNotesLabel': "Notes",
742 'recordDetailLabelFieldColumnLabel': "Field label",
743 'recordDetailDataFieldColumnLabel': "Field data",
744 'recordDetailTypeFieldColumnLabel': "Type",
745
746 'recordDetailSavingChangesMessagePanelInitialTitle': "Saving card",
747 'recordDetailSavingChangesMessagePanelInitialText': "---",
748
749 'recordDetailRemoveFieldButtonLabel': "-",
750 'recordDetailAddFieldButtonLabel': "Add new field",
751 'recordDetailPasswordFieldHelpLabel': "click the stars to select the password and then Ctrl-C to copy",
752
753 'recordDetailPasswordFieldScrambleLabel': "scramble",
754 'recordDetailPasswordFieldUnscrambleLabel': "unscramble",
755
756 'recordDetailDirectLoginBlockTitle': "Direct logins",
757 'recordDetailNewDirectLoginDescription': "<p>Direct login configuration</p>",
758
759 'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription':"\
760 <p>Does this card contain credentials to access an online service?</p>\
761 <p>Use the bookmarklet to configure a “direct login” from Clipperz with just one click!</p>",
762
763 'recordDetailDeleteDirectLoginButtonLabel': "-",
764 'recordDetailAddNewDirectLoginButtonLabel': "Add new direct login",
765
766 'recordDetailEditButtonLabel': "Edit",
767 'recordDetailSaveButtonLabel': "Save",
768 'recordDetailCancelButtonLabel': "Cancel",
769
770 'newRecordTitleLabel': "_new card_",
771 'newDirectLoginLabelSuffix': "",
772
773// Cards block - save card panel
774 'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Save card",
775 'recordSaveChangesPanelCollectRecordInfoMessageText': "Updating card headers",
776 'recordSaveChangesPanelEncryptUserDataMessageTitle': "Save card",
777 'recordSaveChangesPanelEncryptUserDataMessageText': "Local encryption of card headers",
778 'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Save card",
779 'recordSaveChangesPanelEncryptRecordDataMessageText': "Local encryption of card's data",
780 'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle':"Save card",
781 'recordSaveChangesPanelEncryptRecordVersionDataMessageText':"Local encryption of card's version data",
782 'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Save card",
783 'recordSaveChangesPanelSendingDataToTheServerMessageText': "Uploading encrypted card's header to Clipperz",
784 'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Save card",
785 'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Updating the interface",
786
787 //Password Generator strings
788 'passwordGeneratorPanelTitle': "Password generator",
789 'passwordGeneratorPanelOkLabel': "Ok",
790 'passwordGeneratorPanelCancelLabel': "Cancel",
791
792 'passwordGeneratorLowercaseLabel': "abc",
793 'passwordGeneratorUppercaseLabel': "ABC",
794 'passwordGeneratorNumberLabel': "012",
795 'passwordGeneratorSymbolLabel': "@#$",
796
797 'passwordGeneratorLengthLabel': "length:",
798
799
800 //Miscellaneous strings
801
802 'comingSoon': "coming soon …",
803 'panelCollectingEntryopyMessageText': "Collecting entropy",
804 'directLoginConfigurationCheckBoxFieldSelectedValue': "Yes",
805 'directLoginConfigurationCheckBoxFieldNotSelectedValue': "No",
806
807
808
809// NEW - Import panel
810 'importFormats':{
811 'CSV': {
812 'label': "CSV",
813 'description':"<p>A widely recognized file format that stores tabular data. Several password managers can export data to this format.</p>"
814 },
815 'Excel': {
816 'label': "Excel",
817 'description':"<p>The popular spreadsheet from Microsoft. Storing passwords in Excel files is very common but not advisable.</p>"
818 },
819 'KeePass': {
820 'label': "KeePass",
821 'description':"<p>The custom TXT file created by KeePass password manager.</p>"
822 },
823 'PasswordPlus': {
824 'label': "Password Plus",
825 'description':"<p>The custom CSV format produced by Password Plus, a password manager mostly used on mobile devices.</p>"
826 },
827 'Roboform': {
828 'label': "RoboForm",
829 'description':"<p>The special HTML file created by Roboform password manager when displaying Passcard and Safenotes for printing.</p>"
830 },
831 'ClipperzExport': {
832 'label': "JSON",
833 'description':"<p>The file created by Clipperz itself in JSON format. It preserves all information contained in your cards, even direct login configurations.</p>"
834 }
835},
836
837 //JSON
838 'Clipperz_ImportWizard_Title': "JSON import",
839 'importOptions_clipperz_description': "<p>Open the JSON file exported from Clipperz in a text editor. Then copy and paste its content to the text area below.</p>",
840
841 //CSV
842 'CSV_ImportWizard_Title': "CSV import",
843 'importOptions_csv_description_': "\
844 <p>Open the CSV file in a text editor. Then copy and paste its content to the text area below.</p>\
845 <p>Please select the special characters used within your file.</p>",
846
847 //Excel
848 'Excel_ImportWizard_Title': "Excel import",
849 'importOptions_excel_description_': "<p>Open the Excel file and select the cells you want to import. Then copy and paste them to the text area below.</p>",
850
851 //KeePass
852 'KeePass_ImportWizard_Title': "KeePass import",
853 'importOptions_keePass_description_': "<p>Open the TXT file created by Keepass in a text editor. Then copy and paste its content to the text area below.</p>",
854
855 //PasswordPlus
856 'PasswordPlus_ImportWizard_Title': "Password Plus import",
857 'importOptions_passwordPlus_description':"<p>Open the CSV file created by PasswordPlus in a text editor. Then copy and paste its content to the text area below.</p>",
858
859 //RoboForm
860 'RoboForm_ImportWizard_Title': "RoboForm import",
861 'importOptions_roboForm_description': "<p>Open the HTML file created by RoboForm in a text editor. Then copy and paste its content to the text area below.</p>",
862
863
864 'importData_parsingDataTitle': "Import",
865 'importData_parsingDataText': "Parsing data …",
866
867 'importData_previewingDataTitle': "Import",
868 'importData_previewingDataText': "Processing data …",
869
870 'importData_processingDataTitle': "Import",
871 'importData_processingDataText': "Creating new cards …",
872
873'ImportWizard': {
874 'EDIT': "edit",
875 'PREVIEW': "preview",
876 'IMPORT': "import",
877
878 'KEEPASS_SETTINGS': "settings",
879
880 'CSV_EDIT': "paste",
881 'CSV_COLUMNS': "columns",
882 'CSV_HEADER': "labels",
883 'CSV_TITLE': "titles",
884 'CSV_NOTES': "notes",
885 'CSV_FIELDS': "types",
886
887 'EXCEL_EDIT': "edit"
888},
889
890 'CSV_ImportWizard_Columns': "<p>Select the columns you want to import.</p>",
891 'CSV_ImportWizard_Header': "<p>If the first row of the CSV file contains field labels, tick off the checkbox below.</p>",
892 'CSV_ImportWizard_Header_Settings_firstRowHeaderLabel':"Use the first row as labels?",
893 'CSV_ImportWizard_Title': "<p>Select the column that contains titles of the cards you are importing. (mandatory)</p>",
894 'CSV_ImportWizard_Notes': "<p>Select the column that represents a \"notes\" field. (optional)</p>",
895 'CSV_ImportWizard_Notes_Settings_noSelectionLabel': "\"notes\" field not present",
896 'CSV_ImportWizard_Fields': "<p>Select the correct type for each column from the drop down lists.</p>",
897 'CSV_ImportWizard_Fields_MissingLabelWarning': "Missing label",
898
899 'importData_importConfirmation_title': "Import",
900 'importData_importConfirmation_text': "Do you want to import __numberOfRecords__ cards?",
901
902
903 //Vulnerability warning
904 'VulnerabilityWarning_Panel_title': "Vulnerability warning",
905 'VulnerabilityWarning_Panel_message': "The action as been aborted due to a catched vulnerability",
906 'VulnerabilityWarning_Panel_buttonLabel':"Close",
907
908
909
910 //All the loginInfo panel infos
911
912 'WELCOME_BACK': "Welcome back!",
913
914 'currentConnectionText': "You are connected from ip&nbsp;__ip__, apparently from __country__, using __browser__ on __operatingSystem__.",
915 'latestConnectionText': "Your latest connection was __elapsedTimeDescription__ (__time__) from ip&nbsp;__ip__, apparently from __country__, using __browser__ on __operatingSystem__.",
916
917 'fullLoginHistoryLinkLabel': "show login history",
918
919'elapsedTimeDescriptions': {
920 'MORE_THAN_A_MONTH_AGO': "more than a month ago",
921 'MORE_THAN_A_WEEK_AGO': "more than a week ago",
922 'MORE_THAN_*_WEEKS_AGO': "more than __elapsed__ weeks ago",
923 'YESTERDAY': "yesterday",
924 '*_DAYS_AGO': "__elapsed__ days ago",
925 'ABOUT_AN_HOUR_AGO': "about an hour ago",
926 '*_HOURS_AGO': "__elapsed__ hours ago",
927 'JUST_A_FEW_MINUTES_AGO': "just a few minutes ago",
928 'ABOUT_*_MINUTES_AGO': "about __elapsed__ minutes ago"
929},
930
931 'unknown_ip': "unknown",
932
933'countries': {
934 '--': "unknown",
935 'AD': "Andorra",
936 'AE': "United Arab Emirates",
937 'AF': "Afghanistan",
938 'AG': "Antigua and Barbuda",
939 'AI': "Anguilla",
940 'AL': "Albania",
941 'AM': "Armenia",
942 'AN': "Netherlands Antilles",
943 'AO': "Angola",
944 'AP': "Non-Spec Asia Pas Location",
945 'AR': "Argentina",
946 'AS': "American Samoa",
947 'AT': "Austria",
948 'AU': "Australia",
949 'AW': "Aruba",
950 'AX': "Aland Islands",
951 'AZ': "Azerbaijan",
952 'BA': "Bosnia and Herzegowina",
953 'BB': "Barbados",
954 'BD': "Bangladesh",
955 'BE': "Belgium",
956 'BF': "Burkina Faso",
957 'BG': "Bulgaria",
958 'BH': "Bahrain",
959 'BI': "Burundi",
960 'BJ': "Benin",
961 'BM': "Bermuda",
962 'BN': "Brunei Darussalam",
963 'BO': "Bolivia",
964 'BR': "Brazil",
965 'BS': "Bahamas",
966 'BT': "Bhutan",
967 'BW': "Botswana",
968 'BY': "Belarus",
969 'BZ': "Belize",
970 'CA': "Canada",
971 'CD': "Congo the Democratic Republic of the",
972 'CF': "Central African Republic",
973 'CH': "Switzerland",
974 'CI': "Cote D'ivoire",
975 'CK': "Cook Islands",
976 'CL': "Chile",
977 'CM': "Cameroon",
978 'CN': "China",
979 'CO': "Colombia",
980 'CR': "Costa Rica",
981 'CS': "Serbia and Montenegro",
982 'CU': "Cuba",
983 'CY': "Cyprus",
984 'CZ': "Czech Republic",
985 'DE': "Germany",
986 'DJ': "Djibouti",
987 'DK': "Denmark",
988 'DO': "Dominican Republic",
989 'DZ': "Algeria",
990 'EC': "Ecuador",
991 'EE': "Estonia",
992 'EG': "Egypt",
993 'ER': "Eritrea",
994 'ES': "Spain",
995 'ET': "Ethiopia",
996 'EU': "European Union",
997 'FI': "Finland",
998 'FJ': "Fiji",
999 'FM': "Micronesia Federated States of",
1000 'FO': "Faroe Islands",
1001 'FR': "France",
1002 'GA': "Gabon",
1003 'GB': "United Kingdom",
1004 'GD': "Grenada",
1005 'GE': "Georgia",
1006 'GF': "French Guiana",
1007 'GG': "Guernsey",
1008 'GH': "Ghana",
1009 'GI': "Gibraltar",
1010 'GL': "Greenland",
1011 'GM': "Gambia",
1012 'GP': "Guadeloupe",
1013 'GR': "Greece",
1014 'GT': "Guatemala",
1015 'GU': "Guam",
1016 'GW': "Guinea-Bissau",
1017 'GY': "Guyana",
1018 'HK': "Hong Kong",
1019 'HN': "Honduras",
1020 'HR': "Croatia (Local Name: Hrvatska)",
1021 'HT': "Haiti",
1022 'HU': "Hungary",
1023 'ID': "Indonesia",
1024 'IE': "Ireland",
1025 'IL': "Israel",
1026 'IM': "Isle of Man",
1027 'IN': "India",
1028 'IO': "British Indian Ocean Territory",
1029 'IQ': "Iraq",
1030 'IR': "Iran (Islamic Republic of)",
1031 'IS': "Iceland",
1032 'IT': "Italy",
1033 'JE': "Jersey",
1034 'JM': "Jamaica",
1035 'JO': "Jordan",
1036 'JP': "Japan",
1037 'KE': "Kenya",
1038 'KG': "Kyrgyzstan",
1039 'KH': "Cambodia",
1040 'KI': "Kiribati",
1041 'KN': "Saint Kitts and Nevis",
1042 'KR': "Korea Republic of",
1043 'KW': "Kuwait",
1044 'KY': "Cayman Islands",
1045 'KZ': "Kazakhstan",
1046 'LA': "Lao People's Democratic Republic",
1047 'LB': "Lebanon",
1048 'LC': "Saint Lucia",
1049 'LI': "Liechtenstein",
1050 'LK': "Sri Lanka",
1051 'LR': "Liberia",
1052 'LS': "Lesotho",
1053 'LT': "Lithuania",
1054 'LU': "Luxembourg",
1055 'LV': "Latvia",
1056 'LY': "Libyan Arab Jamahiriya",
1057 'MA': "Morocco",
1058 'MC': "Monaco",
1059 'MD': "Moldova Republic of",
1060 'MG': "Madagascar",
1061 'MH': "Marshall Islands",
1062 'MK': "Macedonia the Former Yugoslav Republic of",
1063 'ML': "Mali",
1064 'MM': "Myanmar",
1065 'MN': "Mongolia",
1066 'MO': "Macau",
1067 'MP': "Northern Mariana Islands",
1068 'MR': "Mauritania",
1069 'MS': "Montserrat",
1070 'MT': "Malta",
1071 'MU': "Mauritius",
1072 'MV': "Maldives",
1073 'MW': "Malawi",
1074 'MX': "Mexico",
1075 'MY': "Malaysia",
1076 'MZ': "Mozambique",
1077 'NA': "Namibia",
1078 'NC': "New Caledonia",
1079 'NF': "Norfolk Island",
1080 'NG': "Nigeria",
1081 'NI': "Nicaragua",
1082 'NL': "Netherlands",
1083 'NO': "Norway",
1084 'NP': "Nepal",
1085 'NR': "Nauru",
1086 'NU': "Niue",
1087 'NZ': "New Zealand",
1088 'OM': "Oman",
1089 'PA': "Panama",
1090 'PE': "Peru",
1091 'PF': "French Polynesia",
1092 'PG': "Papua New Guinea",
1093 'PH': "Philippines",
1094 'PK': "Pakistan",
1095 'PL': "Poland",
1096 'PR': "Puerto Rico",
1097 'PS': "Palestinian Territory Occupied",
1098 'PT': "Portugal",
1099 'PW': "Palau",
1100 'PY': "Paraguay",
1101 'QA': "Qatar",
1102 'RO': "Romania",
1103 'RS': "Serbia",
1104 'RU': "Russian Federation",
1105 'RW': "Rwanda",
1106 'SA': "Saudi Arabia",
1107 'SB': "Solomon Islands",
1108 'SC': "Seychelles",
1109 'SD': "Sudan",
1110 'SE': "Sweden",
1111 'SG': "Singapore",
1112 'SI': "Slovenia",
1113 'SK': "Slovakia (Slovak Republic)",
1114 'SL': "Sierra Leone",
1115 'SM': "San Marino",
1116 'SN': "Senegal",
1117 'SR': "Suriname",
1118 'SV': "El Salvador",
1119 'SY': "Syrian Arab Republic",
1120 'SZ': "Swaziland",
1121 'TC': "Turks and Caicos Islands",
1122 'TG': "Togo",
1123 'TH': "Thailand",
1124 'TJ': "Tajikistan",
1125 'TM': "Turkmenistan",
1126 'TN': "Tunisia",
1127 'TO': "Tonga",
1128 'TR': "Turkey",
1129 'TT': "Trinidad and Tobago",
1130 'TV': "Tuvalu",
1131 'TW': "Taiwan Province of China",
1132 'TZ': "Tanzania United Republic of",
1133 'UA': "Ukraine",
1134 'UG': "Uganda",
1135 'US': "United States",
1136 'UY': "Uruguay",
1137 'UZ': "Uzbekistan",
1138 'VA': "Holy See (Vatican City State)",
1139 'VE': "Venezuela",
1140 'VG': "Virgin Islands (British)",
1141 'VI': "Virgin Islands (U.S.)",
1142 'VN': "Viet Nam",
1143 'VU': "Vanuatu",
1144 'WF': "Wallis and Futuna Islands",
1145 'WS': "Samoa",
1146 'YE': "Yemen",
1147 'ZA': "South Africa",
1148 'ZM': "Zambia",
1149 'ZW': "Zimbabwe",
1150 'ZZ': "Reserved"
1151},
1152
1153'browsers': {
1154 'UNKNOWN': "Unknown",
1155 'MSIE': "Internet Explorer",
1156 'FIREFOX': "Firefox",
1157 'OPERA': "Opera",
1158 'SAFARI': "Safari",
1159 'OMNIWEB': "OmniWeb",
1160 'CAMINO': "Camino",
1161 'CHROME': "Chrome"
1162},
1163
1164'operatingSystems': {
1165 'UNKNOWN': "Unknown",
1166 'WINDOWS': "Windows",
1167 'MAC': "Mac",
1168 'LINUX': "Linux",
1169 'IPHONE': "iPhone",
1170 'MOBILE': "Mobile",
1171 'OPENBSD': "OpenBSD",
1172 'FREEBSD': "FreeBSD",
1173 'NETBSD': "NetBSD"
1174},
1175
1176
1177 //Calendar texts
1178'calendarStrings': {
1179 'months': {
1180 '0':"January",
1181 '1':"February",
1182 '2':"March",
1183 '3':"April",
1184 '4':"May",
1185 '5':"June",
1186 '6':"July",
1187 '7':"August",
1188 '8':"September",
1189 '9':"October",
1190 '10':"November",
1191 '11':"December"
1192 },
1193 'shortMonths':{
1194 '0':"Jan",
1195 '1':"Feb",
1196 '2':"Mar",
1197 '3':"Apr",
1198 '4':"May",
1199 '5':"Jun",
1200 '6':"Jul",
1201 '7':"Aug",
1202 '8':"Sep",
1203 '9':"Oct",
1204 '10':"Nov",
1205 '11':"Dec"
1206 },
1207
1208 'days':{
1209 '0':"Sunday",
1210 '1':"Monday",
1211 '2':"Tuesday",
1212 '3':"Wednesday",
1213 '4':"Thursday",
1214 '5':"Friday",
1215 '6':"Saturday"
1216 },
1217
1218 'shortDays':{
1219 '0':"Sun",
1220 '1':"Mon",
1221 '2':"Tue",
1222 '3':"Wed",
1223 '4':"Thu",
1224 '5':"Fri",
1225 '6':"Sat"
1226 },
1227
1228 'veryShortDays':{
1229 '0':"Su",
1230 '1':"Mo",
1231 '2':"Tu",
1232 '3':"We",
1233 '4':"Th",
1234 '5':"Fr",
1235 '6':"Sa"
1236 },
1237
1238 'amDesignation':"am",
1239 'pmDesignation':"pm"
1240
1241},
1242
1243// Date format
1244 'fullDate_format':"l, F d, Y H:i:s",
1245*/
1246//################################################################################
1247/*
1248'pageHeader': {
1249 'donation':"donAte",
1250 'forum':"foRum",
1251 'credits':"creDits",
1252 'feedback':"feeDback",
1253 'help': "hElp"
1254},
1255
1256
1257'bookmarkletCopy': {
1258 'noExceptionMessage':"The direct login configuration has been collected.",
1259 'exceptionMessage': "Sorry! There was an error while processing the page.",
1260 'copy': "copy",
1261 'successfulMessage':"DONE!",
1262 'failMessage': "Failed! :("
1263},
1264*/
1265//################################################################################
1266
1267'Wizards': {
1268 'DirectLoginWizard': {
1269 'LABEL': {
1270 'name': "label",
1271 'description': "Enter a name for your new direct login."
1272 },
1273 'TYPE': {
1274 'name': "type",
1275 'description': "short description of the different types of direct login available"
1276 },
1277 'CONFIGURATION': {
1278 'name': "config", //"bookmarklet config",
1279 'description': "Paste the code collected by the bookmarklet. (To install the bookmarklet drag the link below to the bookmark bar of your browser.)"
1280 },
1281 'BINDINGS': {
1282 'name': "bindings",
1283 'description': "Select the right value for each field from the drop down menus."
1284 },
1285 'FAVICON': {
1286 'name': "favicon",
1287 'description': "If you are not satisfied with the small icon for this direct login, enter the URL of a new image file (.ico, .png, .jpg)."
1288 },
1289 'DONE': {
1290 'name': "done",
1291 'description': "Congratulations! You have created a new direct login using credentials contained in your '__cardName__' card.\nEnjoy 1-clik access to '__directLoginName__'!"
1292 }
1293 },
1294 'NewUserWizard': {
1295 'CREDENTIALS': {
1296 'name': "credentials",
1297 'description': "[choose you credentials]"
1298 },
1299 'CHECK_CREDENTIALS': {
1300 'name': "check credentials",
1301 'description': "[check credentials]"
1302 },
1303 'TERMS_OF_SERVICE': {
1304 'name': "terms of service",
1305 'description': "[terms of service]"
1306 },
1307 'CREATE_USER': {
1308 'name': "login",
1309 'description': "[create user]"
1310 }//,
1311/*
1312 'LOGIN': {
1313 'name': "login",
1314 'description': "[enjoy Clipperz]"
1315 },
1316*/
1317 }
1318},
1319
1320
1321'exceptionsMessages': {
1322 'Clipperz': {
1323 'Crypto': {
1324 'Base': {
1325 'exception': {
1326 'CorruptedMessage': "Corrupted message"
1327 }
1328 }
1329 }
1330 }
1331},
1332
1333
1334__syntaxFix__: "syntax fix"
1335
1336}
diff --git a/frontend/delta/js/Clipperz/PM/Toll.js b/frontend/delta/js/Clipperz/PM/Toll.js
new file mode 100644
index 0000000..e9c3092
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/Toll.js
@@ -0,0 +1,189 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26
27//=============================================================================
28
29Clipperz.PM.Toll = function(args) {
30 args = args || {};
31
32 this._requestType = args.requestType;
33 this._targetValue = args.targetValue;
34 this._cost = args.cost;
35 this._toll = null;
36
37 return this;
38}
39
40Clipperz.PM.Toll.prototype = MochiKit.Base.update(null, {
41
42 'toString': function() {
43 return "Clipperz.PM.Toll (" + this.requestType() + ": " + this.cost() + " - " + ((this.toll() == null)? 'UNPAID' : 'PAID') + ")";
44 },
45
46 //-------------------------------------------------------------------------
47
48 'requestType': function() {
49 return this._requestType;
50 },
51
52 //-------------------------------------------------------------------------
53
54 'targetValue': function() {
55 return this._targetValue;
56 },
57
58 //-------------------------------------------------------------------------
59
60 'cost': function() {
61 return this._cost;
62 },
63
64 //-------------------------------------------------------------------------
65
66 'toll': function() {
67 return this._toll;
68 },
69
70 //-------------------------------------------------------------------------
71/*
72 '__pay': function() {
73 varresult;
74 vartargetData;
75 vartargetMatchSize;
76 var prefixMatchingBits;
77 varpayment;
78 var i;
79
80 if (this.toll() == null) {
81 i = 0;
82 targetData = new Clipperz.ByteArray("0x" + this.targetValue());
83 targetMatchSize = this.cost();
84
85 payment = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32);
86
87 do {
88 varpaymentData;
89
90 //payment = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32);
91 payment.increment();
92 paymentData = Clipperz.Crypto.SHA.sha256(payment);
93 // prefixMatchingBits = this.prefixMatchingBits(targetData, paymentData);
94 prefixMatchingBits = Clipperz.ByteArray.prefixMatchingBits(targetData, paymentData);
95 i++;
96 } while (prefixMatchingBits < targetMatchSize);
97
98 this._toll = payment.toHexString().substring(2)
99 }
100
101 return this;
102 },
103 */
104 //-------------------------------------------------------------------------
105
106 'innerDeferredPay': function (aTargetValue, aCost, aPayment) {
107 var deferredResult;
108 var result;
109 var payment;
110 var i;
111
112 result = null;
113 payment = aPayment;
114 i = 0;
115
116 while ((result == null) && (i < Clipperz.PM.Toll.numberOfCloseLoopIterations)) {
117 if (Clipperz.ByteArray.prefixMatchingBits(aTargetValue, Clipperz.Crypto.SHA.sha256(payment)) > aCost) {
118 result = payment;
119 } else {
120 payment.increment();
121 }
122
123 i ++;
124 }
125
126 if (result == null) {
127 deferredResult = MochiKit.Async.callLater(Clipperz.PM.Toll.pauseBetweenEachCloseLoop, MochiKit.Base.method(this, 'innerDeferredPay', aTargetValue, aCost, aPayment));
128 } else {
129 deferredResult = MochiKit.Async.succeed(result);
130 }
131
132 return deferredResult;
133 },
134
135 'deferredPay': function () {
136 vardeferredResult;
137 vartoll;
138
139 toll = this;
140 deferredResult = new Clipperz.Async.Deferred("Toll.deferredPay");
141//deferredResult.addLog("--->>> deferredPay - " + this.cost());
142 deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'getRandomBytes', 32);
143 deferredResult.addMethod(toll, 'innerDeferredPay', new Clipperz.ByteArray("0x" + this.targetValue()), this.cost());
144 deferredResult.addCallback(MochiKit.Base.bind(function(aPayment) {
145 var result;
146
147 result = {
148 targetValue: this.targetValue(),
149 toll: aPayment.toHexString().substr(2)
150 };
151
152 return result;
153 }, this));
154//deferredResult.addLog("<<<--- deferredPay - " + this.cost());
155 deferredResult.callback();
156
157 return deferredResult;
158 },
159
160 //=========================================================================
161 __syntaxFix__: "syntax fix"
162
163});
164
165
166Clipperz.PM.Toll.validate = function(aTargetValue, aToll, aCost) {
167 var result;
168 vartollValue;
169 var targetValue;
170 var hashedTollValue;
171 var payedToll;
172
173 tollValue = new Clipperz.ByteArray("0x" + aToll);
174 targetValue = new Clipperz.ByteArray("0x" + aTargetValue);
175 hashedTollValue = Clipperz.Crypto.SHA.sha256(tollValue);
176
177 payedToll = Clipperz.ByteArray.prefixMatchingBits(targetValue, hashedTollValue);
178
179 if (payedToll < aCost) {
180 result = false;
181 } else {
182 result = true;
183 }
184
185 return result;
186};
187
188Clipperz.PM.Toll.numberOfCloseLoopIterations = 50;
189Clipperz.PM.Toll.pauseBetweenEachCloseLoop = 0.5; \ No newline at end of file
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js b/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
new file mode 100644
index 0000000..df514a2
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
@@ -0,0 +1,142 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.CardDetail = React.createClass({
25
26 getDefaultProps: function () {
27 return {
28 // searchDelay: 0.3
29 }
30 },
31
32 propTypes: {
33 card: React.PropTypes.object.isRequired
34 },
35
36 getInitialState: function () {
37 return {
38 // showSearch: false,
39 // searchTimer: null,
40 starred: false
41 };
42 },
43
44 handleDirectLoginClick: function (aDirectLoginReference, anEvent) {
45 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference});
46 },
47
48 //=========================================================================
49
50 normalizeFieldValue: function (aValue) {
51 varresult = [];
52 varrows = aValue.split('\n');
53
54 for (var i = 0; i < rows.length; i++) {
55 if (i > 0) {
56 result.push(React.DOM.br());
57 }
58 result.push(rows[i].replace(/[\s]/g, '\u00A0'));
59 }
60
61 return result;
62 },
63
64 renderField: function (aField) {
65//console.log("FIELD", aField);
66 varactionLabel;
67
68 if (aField['actionType'] == 'URL') {
69 actionLabel = "go";
70 } else if (aField['actionType'] == 'PASSWORD') {
71 actionLabel = "locked";
72 } else if (aField['actionType'] == 'EMAIL') {
73 actionLabel = "email";
74 } else {
75 actionLabel = "";
76 }
77
78 returnReact.DOM.div({className:'listItem ' + aField['actionType']}, [
79 React.DOM.div({className:'fieldWrapper'}, [
80 React.DOM.div({className:'fieldInnerWrapper'}, [
81 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])),
82 React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + aField['actionType']}, this.normalizeFieldValue(aField['value'])))
83 ])
84 ]),
85 React.DOM.div({className:'actionWrapper'}, [
86 React.DOM.div({className:aField['actionType']}, actionLabel)
87 ])
88 ]);
89 },
90
91 renderDirectLogin: function (aDirectLogin) {
92//console.log("DIRECT LOGIN", aDirectLogin);
93 returnReact.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [
94 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])),
95 React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})),
96 React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go"))
97 ]);
98 },
99
100 handleBackClick: function (anEvent) {
101 window.history.back();
102 },
103
104 handleStarClick: function (anEvent) {
105 this.setState({starred: !this.state['starred']});
106 },
107
108 //=========================================================================
109
110 render: function () {
111 var card = this.props.card;
112 var starredStatus = (this.state['starred'] ? "starred" : "unstarred");
113
114 if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) {
115 card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] })
116 }
117
118 returnReact.DOM.div({className:'cardDetail'}, [
119 React.DOM.div({className:'header'}, [
120 React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)),
121 // React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title + ' ' + card.title + ' ' + card.title + ' ' + card.title)),
122 React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
123 React.DOM.div({className:'starWrapper'}, React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus))
124 ]),
125 React.DOM.div({className:'content'}, [
126 card.fields ? React.DOM.div({className:'fields'}, MochiKit.Base.map(this.renderField, card.fields)) : null,
127 card.directLogins ? React.DOM.div({className:'directLogins'}, MochiKit.Base.map(this.renderDirectLogin,card.directLogins)): null
128 ]),
129 React.DOM.div({className:'footer'}, [
130 /*
131 // React.DOM.a({className:'cancel'}, "cancel"),
132 // React.DOM.a({className:'save'}, "save")
133
134 React.DOM.a({className:'cancel button'}, "failed"),
135 React.DOM.a({className:'save button'}, "done")
136*/
137 ])
138 ]);
139 }
140
141 //=========================================================================
142});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js b/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
new file mode 100644
index 0000000..66d20f1
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
@@ -0,0 +1,161 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.CardList = React.createClass({
25
26 getDefaultProps: function () {
27 return {
28 selectedCard: null,
29 searchDelay: 0.3
30 }
31 },
32
33 propTypes: {
34 searchDelay: React.PropTypes.number
35 },
36
37 getInitialState: function () {
38 return {
39 showSearch: false,
40 searchTimer: null,
41 searchText: '',
42 // passphrase: '',
43 // pin: ''
44 };
45 },
46
47 //=========================================================================
48
49 toggleSearch: function (anEvent) {
50 varshowSearchBox;
51
52 showSearchBox = !this.state.showSearch;
53
54 this.setState({showSearch: showSearchBox});
55
56 if (showSearchBox) {
57 MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, 'focusOnSearchField'));
58 }
59 },
60
61 updateSearchText: function (anEvent) {
62 varsearchText;
63
64 searchText = anEvent.target.value;
65//console.log(">>> updateSearchText", searchText);
66
67 if ((this.state['searchTimer'] != null) && (searchText != this.state['searchText'])) {
68 this.state['searchTimer'].cancel();
69 }
70
71 if (searchText != this.state['searchText']) {
72 this.state['searchText'] = searchText;
73 this.state['searchTimer'] = MochiKit.Async.callLater(this.props['searchDelay'], MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'searchCards', searchText);
74 }
75 },
76
77 focusOnSearchField: function () {
78console.log("focusOnSearchField", this.refs['searchField']);
79 this.refs['searchField'].getDOMNode.focus();
80 },
81
82 searchBox: function () {
83 var result;
84
85 if (this.state.showSearch) {
86 result =React.DOM.div({className:'searchBox'}, [
87 React.DOM.div(null, [
88 React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText})
89 ])
90 ]);
91 } else {
92 result = null;
93 }
94
95 return result;
96 },
97
98 //=========================================================================
99
100 cardItem: function (aRecordReference) {
101 varreference = aRecordReference['_reference'];
102 varselectedCard = (reference == this.props.selectedCard);
103
104 returnReact.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [
105 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)),
106 // React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)),
107 React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')),
108 React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail")))
109 ]);
110 },
111
112 handleClickOnCardDetail: function (aRecordReference, anEvent) {
113 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference);
114 },
115
116 cardListItems: function () {
117 varlist;
118 varresult;
119
120 list = this.props['cardList'];
121
122 if (typeof(list) != 'undefined') {
123 result = MochiKit.Base.map(MochiKit.Base.method(this, 'cardItem'), list);
124 } else {
125 result = null;
126 }
127
128 return result;
129 },
130
131 //=========================================================================
132
133 handleChange: function (anEvent) {
134 // varrefs = this.refs;
135 // var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
136 // var newState = {};
137//
138 // newState[refName] = event.target.value;
139 // this.setState(newState);
140 },
141
142 //=========================================================================
143
144 render: function() {
145 returnReact.DOM.div(null, [
146 React.DOM.div({className:'header'}, [
147 React.DOM.a({className:'account'}, 'clipperz'),
148 React.DOM.div({className:'features'}, [
149 React.DOM.a({className:'addCard'}, 'add'),
150 React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'),
151 React.DOM.a({className:'settings'}, 'settings')
152 ]),
153 // this.searchBox()
154 ]),
155 this.searchBox(),
156 React.DOM.div({className:'content cardList'}, this.cardListItems()),
157 ]);
158 }
159
160 //=========================================================================
161});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/ErrorPage.js b/frontend/delta/js/Clipperz/PM/UI/Components/ErrorPage.js
new file mode 100644
index 0000000..a1979ec
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/ErrorPage.js
@@ -0,0 +1,46 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.ErrorPage = React.createClass({
25
26 getDefaultProps: function () {
27 return {
28 template: Clipperz.PM.UI.Components.PageTemplate
29 }
30 },
31
32 'propTypes': {
33 // type: React.PropTypes.oneOf(['PERMANENT', 'TEMPORARY']),
34 message:React.PropTypes.string.isRequired,
35 template:React.PropTypes.func
36 },
37
38
39 _render: function () {
40 returnReact.DOM.div({className:'error-message'}, this.props.message);
41 },
42
43 render: function () {
44 returnnew this.props.template({'innerComponent': this._render()});
45 }
46});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js b/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
new file mode 100644
index 0000000..2b5b4a4
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
@@ -0,0 +1,150 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.LoginForm = React.createClass({
25
26 getDefaultProps: function () {
27 return {
28 mode: 'CREDENTIALS',
29 isNewUserRegistrationAvailable: false,
30 disabled: false,
31 template: Clipperz.PM.UI.Components.PageTemplate
32 }
33 },
34
35 propTypes: {
36 mode: React.PropTypes.oneOf(['CREDENTIALS','PIN']),
37 isNewUserRegistrationAvailable:React.PropTypes.bool,
38 disabled: React.PropTypes.bool,
39 template: React.PropTypes.func
40 },
41
42 getInitialState: function () {
43 return {
44 username: '',
45 passphrase: '',
46 pin: ''
47 };
48 },
49
50 //=========================================================================
51
52 handleChange: function (anEvent) {
53 varrefs = this.refs;
54 var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
55 var newState = {};
56
57 newState[refName] = event.target.value;
58 this.setState(newState);
59 },
60
61 //=========================================================================
62
63 handleCredentialSubmit: function (event) {
64 event.preventDefault();
65
66 this.refs['passphrase'].getDOMNode().blur();
67
68 var credentials = {
69 'username': this.refs['username'].getDOMNode().value,
70 'passphrase': this.refs['passphrase'].getDOMNode().value
71 }
72 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', credentials);
73 },
74
75 handleRegistrationLinkClick: function (event) {
76 event.preventDefault();
77 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRegistrationForm');
78 },
79
80 //-------------------------------------------------------------------------
81
82 shouldEnableLoginButton: function () {
83 var result;
84
85 return(
86 ((this.state['username'] != '') && (this.state['passphrase'] != ''))
87 ||
88 (this.state['pin'] != '')
89 ) && !this.props['disabled'];
90 },
91
92
93 loginForm: function () {
94 registrationLink =React.DOM.div({'className':'registrationLink'}, [
95 React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Need an account")
96 ]);
97 returnReact.DOM.div({'className':'loginForm credentials'},[
98 React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [
99 React.DOM.div(null,[
100 React.DOM.label({'for':'name'}, "username"),
101 React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
102 React.DOM.label({'for':'passphrase'}, "passphrase"),
103 React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
104 ]),
105 React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
106 ]),
107 this.props.isNewUserRegistrationAvailable ? registrationLink : null
108 ]);
109 },
110
111 handlePINSubmit: function (event) {
112 event.preventDefault();
113
114 this.refs['pin'].getDOMNode().blur();
115
116 var credentials = {
117 pin: this.refs['pin'].getDOMNode().value
118 }
119
120 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', credentials);
121 },
122
123 pinForm: function () {
124 returnReact.DOM.div({'className':'loginForm pin'},[
125 React.DOM.form({onChange: this.handleChange, onSubmit:this.handlePINSubmit}, [
126 React.DOM.div(null,[
127 React.DOM.label({'for':'pin'}, "pin"),
128 React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'})
129 ]),
130 React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login")
131 ])
132 ]);
133 },
134
135 setInitialFocus: function () {
136 if (this.props.mode == 'PIN') {
137 this.refs['pin'].getDOMNode().select();
138 } else {
139 if (this.refs['username'].getDOMNode().value == '') {
140 this.refs['username'].getDOMNode().focus();
141 } else{
142 this.refs['passphrase'].getDOMNode().select();
143 }
144 }
145 },
146
147 render: function() {
148 returnnew this.props.template({'innerComponent': this.props.mode == 'PIN' ? this.pinForm() : this.loginForm()});
149 }
150});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js b/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
new file mode 100644
index 0000000..cc4a06c
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
@@ -0,0 +1,122 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.UI.Components');
25
26Clipperz.PM.UI.Components.Overlay = function(args) {
27 args = args || {};
28
29 this._defaultDelay = 2;
30 this._element = MochiKit.DOM.getElement('overlay');
31
32 return this;
33}
34
35//=============================================================================
36
37Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, {
38
39 //-------------------------------------------------------------------------
40
41 'toString': function () {
42 return "Clipperz.PM.UI.Components.Overlay component";
43 },
44
45 'element': function () {
46 // return MochiKit.DOM.getElement('overlay');
47 return this._element;
48 },
49
50 'getElement': function (aClass) {
51 return MochiKit.Selector.findChildElements(this.element(), ['.'+aClass])[0];
52 },
53
54 //-------------------------------------------------------------------------
55
56 'show': function (aMessage) {
57 this.resetStatus();
58 this.setMessage(aMessage);
59 MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-hide');
60 MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-show');
61 },
62
63 'done': function (aMessage, aDelayBeforeHiding) {
64 this.completed(this.showDoneIcon, aMessage, aDelayBeforeHiding);
65 },
66
67 'failed': function (aMessage, aDelayBeforeHiding) {
68 this.completed(this.showFailIcon, aMessage, aDelayBeforeHiding);
69 },
70
71 //-------------------------------------------------------------------------
72
73 'resetStatus': function () {
74 MochiKit.Style.showElement(this.element());
75 MochiKit.Style.showElement(this.getElement('spinner'));
76 MochiKit.Style.hideElement(this.getElement('done'));
77 MochiKit.Style.hideElement(this.getElement('failed'));
78 },
79
80 'setMessage': function (aMessage) {
81 if (typeof(aMessage) != 'undefined') {
82 this.getElement('title').innerHTML = aMessage;
83 }
84 },
85
86 'completed': function (aFunctionToShowResult, aMessage, aDelayBeforeHiding) {
87 var delay = aDelayBeforeHiding || this.defaultDelay();
88
89 this.hideSpinner();
90 MochiKit.Base.bind(aFunctionToShowResult, this)();
91 this.setMessage(aMessage);
92
93 MochiKit.Async.callLater(delay, MochiKit.Base.bind(this.hide, this))
94 },
95
96 'hide': function () {
97 MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-show');
98 MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-hide');
99 MochiKit.Async.callLater(1, MochiKit.Style.hideElement, this.element());
100 },
101
102 'hideSpinner': function () {
103 MochiKit.Style.hideElement(this.getElement('spinner'));
104 },
105
106 'showDoneIcon': function () {
107 MochiKit.Style.showElement(this.getElement('done'));
108 },
109
110 'showFailIcon': function () {
111 MochiKit.Style.showElement(this.getElement('failed'));
112 },
113
114 //-------------------------------------------------------------------------
115
116 'defaultDelay': function () {
117 return this._defaultDelay;
118 },
119
120 //-------------------------------------------------------------------------
121 __syntaxFix__: "syntax fix"
122});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/PageTemplate.js b/frontend/delta/js/Clipperz/PM/UI/Components/PageTemplate.js
new file mode 100644
index 0000000..9b7c748
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/PageTemplate.js
@@ -0,0 +1,33 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.PageTemplate = React.createClass({
25 render: function() {
26 returnReact.DOM.div(null, [
27 React.DOM.div({'className': 'header'}, [
28 React.DOM.h1(null, "clipperz")
29 ]),
30 React.DOM.div({'className': 'content'}, this.props.innerComponent)
31 ])
32 }
33});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js b/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js
new file mode 100644
index 0000000..051dcc5
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/RegistrationWizard.js
@@ -0,0 +1,240 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
25
26 getDefaultProps: function () {
27 return {
28 steps: [
29 {name:'CREDENTIALS', label:'registration', _label:'credentials',description:"Choose your credentails"},
30 {name:'PASSWORD_VERIFICATION', label:'registration', _label:'verify', description:"Verify your passphrase"},
31 {name:'TERMS_OF_SERVICE', label:'registration', _label:'terms', description:"Check our terms of service"}
32 ],
33 disabled: false,
34 template: Clipperz.PM.UI.Components.PageTemplate
35 }
36 },
37
38 getInitialState: function () {
39 return {
40 currentStep: this.props['steps'][0]['name'],
41 username: '',
42 passphrase: '',
43 verify_passphrase: '',
44 no_password_recovery: false,
45 agree_terms_of_service: false
46 };
47 },
48
49 'propTypes': {
50 // steps: React.PropTypes.array,
51 disabled:React.PropTypes.bool,
52 template:React.PropTypes.func
53 },
54
55 //=========================================================================
56
57 currentStepIndex: function () {
58 return this.indexOfStepNamed(this.state['currentStep']);
59 },
60
61 indexOfStepNamed: function (aStepName) {
62 var stepConfiguration;
63 varresult;
64
65 stepConfiguration = this.props['steps'].filter(function (aConfig) { return aConfig['name'] == aStepName})[0];
66 result = this.props['steps'].indexOf(stepConfiguration);
67 return result;
68 },
69
70 //=========================================================================
71
72 statusClassForStep: function (aStep) {
73 varcurrentStepIndex = this.currentStepIndex();
74 var stepIndex = this.indexOfStepNamed(aStep['name']);
75 varresult;
76
77 if (stepIndex < currentStepIndex) {
78 result = 'left';
79 } else if (stepIndex == currentStepIndex) {
80 result = 'center';
81 } else {
82 result = 'right';
83 }
84
85 return result;
86 },
87
88 //=========================================================================
89
90 handleBackClick: function (anEvent) {
91 var nextStep;
92 anEvent.preventDefault();
93
94 if (this.currentStepIndex() > 0) {
95 nextStep = this.props['steps'][this.currentStepIndex() - 1];
96 this.setState({currentStep: nextStep['name']});
97 } else {
98 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
99 }
100 },
101
102 handleForwardClick: function (anEvent) {
103 var nextStep;
104 anEvent.preventDefault();
105
106 if (this.canMoveForward()) {
107
108 if (this.currentStepIndex() < this.props['steps'].length - 1) {
109 nextStep = this.props['steps'][this.currentStepIndex() + 1];
110 this.setState({currentStep: nextStep['name']});
111 } else {
112 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'registerNewUser', {
113 username: this.state['username'],
114 passphrase: this.state['passphrase']
115 })
116 }
117 }
118 },
119
120 //-------------------------------------------------------------------------
121
122 canMoveForward: function () {
123 var result;
124 var currentStep;
125
126 result = false;
127 currentStep = this.state['currentStep'];
128 if (currentStep == 'CREDENTIALS') {
129 result = ((this.state['username'] != '') && (this.state['passphrase'] != ''));
130 } else if (currentStep == 'PASSWORD_VERIFICATION') {
131 result = (this.state['passphrase'] == this.state['verify_passphrase']);
132 } else if (currentStep == 'TERMS_OF_SERVICE') {
133 result = (this.state['no_password_recovery'] && this.state['agree_terms_of_service']);
134 }
135
136 return result && !this.props['disabled'];
137 },
138
139 //=========================================================================
140
141 handleChange: function (anEvent) {
142 varrefs = this.refs;
143 var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
144 var newState = {};
145
146 if ((event.target.type == 'checkbox') || (event.target.type == 'radio')) {
147 newState[refName] = event.target.checked;
148 } else {
149 newState[refName] = event.target.value;
150 }
151 this.setState(newState);
152 },
153
154 //=========================================================================
155
156 renderIndexStep: function (aStep) {
157 returnReact.DOM.div({'className':'stepIndexItem ' + this.statusClassForStep(aStep)}, '.');
158 },
159
160 renderButtons: function () {
161 return [
162 React.DOM.a({className:'back button step_' + (this.currentStepIndex() - 1), onClick:this.handleBackClick}, '<<'),
163 React.DOM.a({className:'forward button step_' + (this.currentStepIndex() + 1) + ' ' + (this.canMoveForward() ? 'enabled' : 'disabled'), onClick:this.handleForwardClick}, '>>')
164 ];
165 },
166
167 render_CREDENTIALS: function () {
168 returnReact.DOM.div(null,[
169 React.DOM.label({'for':'name'}, "username"),
170 React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'/*, value:this.state.username*/}),
171 React.DOM.label({'for':'passphrase'}, "passphrase"),
172 React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'/*, value:this.state.passphrase*/})
173 ]);
174 },
175
176 render_PASSWORD_VERIFICATION: function () {
177 returnReact.DOM.div(null,[
178 React.DOM.label({'for':'verify_passphrase'}, "passphrase"),
179 React.DOM.input({'type':'password', 'name':'verify_passphrase', 'ref':'verify_passphrase', 'placeholder':"verify passphrase", 'key':'verify_passphrase'})
180 ]);
181 },
182
183 render_TERMS_OF_SERVICE: function () {
184 returnReact.DOM.div(null, [
185 React.DOM.div({className:'checkboxBlock'}, [
186 React.DOM.label({'for':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
187 React.DOM.input({'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'key':'no_password_recovery'}),
188 React.DOM.p(null, "I understand that Clipperz will not be able to recover a lost passphrase.")
189 ]),
190 React.DOM.div({className:'checkboxBlock'}, [
191 React.DOM.label({'for':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
192 React.DOM.input({'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'key':'agree_terms_of_service'}),
193 React.DOM.p(null, [
194 "I have read and agreed to the ",
195 React.DOM.a({href:'https://clipperz.com/terms_service/', target:'_blank'}, "Terms of Service.")
196 ])
197 ])
198 ]);
199 },
200
201 renderStep: function (aStep) {
202 returnReact.DOM.div({'className':'step' + ' ' + aStep['name'] + ' ' + this.statusClassForStep(aStep) + ' step_' + this.currentStepIndex()}, [
203 React.DOM.h1(null, aStep['label']),
204 React.DOM.p(null, aStep['description']),
205 this['render_' + aStep['name']].apply(),
206 React.DOM.div({'className':'stepIndex'}, MochiKit.Base.map(this.renderIndexStep, this.props['steps'])),
207 React.DOM.div({'className':'buttons'}, this.renderButtons())
208 ]);
209 },
210
211 _render: function () {
212 returnReact.DOM.div({'className':'registrationForm'},[
213 React.DOM.form({onChange: this.handleChange}, [
214 React.DOM.div({'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps']))
215 ])
216 ]);
217 },
218
219 render: function () {
220 returnnew this.props.template({'innerComponent': this._render()});
221 },
222
223 //=========================================================================
224
225 setInitialFocus: function () {
226 this.refs['username'].getDOMNode().focus();
227 },
228
229 componentDidUpdate: function (prevProps, prevState, rootNode) {
230 if (prevState['currentStep'] != this.state['currentStep']) {
231 if (this.state['currentStep'] == 'CREDENTIALS') {
232 this.refs['passphrase'].getDOMNode().select();
233 } else if (this.state['currentStep'] == 'PASSWORD_VERIFICATION') {
234 this.refs['verify_passphrase'].getDOMNode().select();
235 }
236 }
237 }
238
239 //=========================================================================
240});
diff --git a/frontend/delta/js/Clipperz/PM/UI/DirectLoginController.js b/frontend/delta/js/Clipperz/PM/UI/DirectLoginController.js
new file mode 100644
index 0000000..d9dfe6d
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/DirectLoginController.js
@@ -0,0 +1,256 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.UI');
25
26Clipperz.PM.UI.DirectLoginRunner = function(args) {
27 this._directLogin = args['directLogin'] || Clipperz.Base.exception.raise('MandatoryParameter');
28 this._target = Clipperz.PM.Crypto.randomKey();
29
30 return this;
31}
32
33MochiKit.Base.update(Clipperz.PM.UI.DirectLoginRunner.prototype, {
34
35 'toString': function() {
36 return "Clipperz.PM.UI.DirectLoginRunner";
37 },
38
39 //-----------------------------------------------------------------------------
40
41 'directLogin': function () {
42 return this._directLogin;
43 },
44
45 //-----------------------------------------------------------------------------
46
47 'target': function () {
48 return this._target;
49 },
50
51 //=============================================================================
52
53 'setWindowTitle': function (aWindow, aTitle) {
54 aWindow.document.title = aTitle;
55 },
56
57 'setWindowBody': function (aWindow, anHTML) {
58 aWindow.document.body.innerHTML = anHTML;
59 },
60
61 //=============================================================================
62
63 'initialWindowSetup': function (aWindow) {
64 this.setWindowTitle(aWindow, "Loading Clipperz Direct Login");
65 this.setWindowBody (aWindow, MochiKit.DOM.toHTML(MochiKit.DOM.H3("Loading Clipperz Direct Login ...")));
66 },
67
68 //-----------------------------------------------------------------------------
69
70 'updateWindowWithDirectLoginLabel': function (aWindow, aLabel) {
71 var titleText;
72 var bodyText;
73
74 titleText = "Loading '__label__' Direct Login".replace(/__label__/, aLabel)
75 bodyText = "Loading '__label__' Direct Login... ".replace(/__label__/, aLabel)
76
77 this.setWindowTitle(aWindow, titleText);
78 this.setWindowBody (aWindow, MochiKit.DOM.toHTML(MochiKit.DOM.H3(bodyText)));
79 },
80
81 //-----------------------------------------------------------------------------
82
83 'updateWindowWithHTMLContent': function (aWindow, anHtml) {
84 this.setWindowBody(aWindow, anHtml);
85 },
86
87 //=============================================================================
88
89 'submitLoginForm': function(aWindow, aSubmitFunction) {
90 MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function () {
91 var formElement;
92 var submitButtons;
93
94 formElement = MochiKit.DOM.getElement('directLoginForm');
95
96 submitButtons = MochiKit.Base.filter(function(anInputElement) {
97 return ((anInputElement.tagName.toLowerCase() == 'input') && (anInputElement.getAttribute('type').toLowerCase() == 'submit'));
98 }, formElement.elements);
99
100 if (submitButtons.length == 0) {
101 if (typeof(formElement.submit) == 'function') {
102 formElement.submit();
103 } else {
104 aSubmitFunction.apply(formElement);
105 }
106/*
107 varformSubmitFunction;
108
109 formSubmitFunction = MochiKit.Base.method(formElement, 'submit');
110 if (Clipperz_IEisBroken == true) {
111 formElement.submit();
112 } else {
113 formSubmitFunction();
114 }
115*/
116 } else {
117 submitButtons[0].click();
118 }
119 }, this));
120 },
121
122 //-------------------------------------------------------------------------
123
124 'runSubmitFormDirectLogin': function (aWindow, someAttributes) {
125 var html;
126 var formElement;
127 var submitFunction;
128
129 formElement = MochiKit.DOM.FORM({
130 'id':'directLoginForm',
131 'method':someAttributes['formAttributes']['method'],
132 'action':someAttributes['formAttributes']['action']
133 });
134
135 submitFunction = formElement.submit;
136
137 MochiKit.DOM.appendChildNodes(formElement, MochiKit.Base.map(function (anInputAttributes) {
138 return MochiKit.DOM.INPUT({'type':'hidden', 'name':anInputAttributes[0], 'value':anInputAttributes[1]});
139 }, MochiKit.Base.items(someAttributes['inputValues'])));
140
141 html ='';
142 html += '<h3>Loading ' + someAttributes['label'] + ' ...</h3>';
143 html +=MochiKit.DOM.appendChildNodes(MochiKit.DOM.DIV(), MochiKit.DOM.appendChildNodes(MochiKit.DOM.DIV({style:'display:none; visibility:hidden;'}), formElement)).innerHTML;
144
145 this.updateWindowWithHTMLContent(aWindow, html);
146 this.submitLoginForm(aWindow, submitFunction);
147 },
148
149 //-------------------------------------------------------------------------
150
151 'runHttpAuthDirectLogin': function(aWindow, someAttributes) {
152 var completeUrl;
153 var url;
154
155 url = someAttributes['inputValues']['url'];
156
157 if (/^https?\:\/\//.test(url) == false) {
158 url = 'http://' + url;
159 }
160
161 if (Clipperz_IEisBroken === true) {
162 completeUrl = url;
163 } else {
164 var username;
165 var password;
166
167 username = someAttributes['inputValues']['username'];
168 password = someAttributes['inputValues']['password'];
169 /(^https?\:\/\/)?(.*)/.test(url);
170
171 completeUrl = RegExp.$1 + username + ':' + password + '@' + RegExp.$2;
172 }
173
174 window.open(completeUrl, this.target());
175 },
176
177 //=============================================================================
178
179 'runDirectLogin': function (aWindow) {
180 var deferredResult;
181
182 deferredResult = new Clipperz.Async.Deferred("DirectLoginRunner.openDirectLogin", {trace:false});
183 deferredResult.addMethod(this, 'initialWindowSetup', aWindow);
184 deferredResult.addMethod(this.directLogin(), 'label');
185 deferredResult.addMethod(this, 'updateWindowWithDirectLoginLabel', aWindow);
186 deferredResult.collectResults({
187 'type': MochiKit.Base.method(this.directLogin(), 'type'),
188 'label': MochiKit.Base.method(this.directLogin(), 'label'),
189 'formAttributes':MochiKit.Base.method(this.directLogin(), 'formAttributes'),
190 'inputValues': MochiKit.Base.method(this.directLogin(), 'inputValues')
191 });
192 deferredResult.addCallback(MochiKit.Base.bind(function (someAttributes) {
193 switch (someAttributes['type']) {
194 case 'http_auth':
195 this.runHttpAuthDirectLogin(aWindow, someAttributes);
196 break;
197 case 'simple_url':
198 this.runSimpleUrlDirectLogin(aWindow, someAttributes);
199 break;
200 default:
201 this.runSubmitFormDirectLogin(aWindow, someAttributes);
202 break;
203 }
204 }, this));
205 deferredResult.callback();
206
207 return deferredResult;
208 },
209
210 //=============================================================================
211
212 'run': function () {
213 var newWindow;
214
215 newWindow = window.open(Clipperz.PM.Strings.getValue('directLoginJumpPageUrl'), this.target());
216
217 return this.runDirectLogin(newWindow);
218 },
219
220 //=============================================================================
221
222 'test': function () {
223 var iFrame;
224 var newWindow;
225
226 iFrame = MochiKit.DOM.createDOM('iframe');
227 MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, iFrame);
228
229 newWindow = iFrame.contentWindow;
230
231 return this.runDirectLogin(newWindow);
232 },
233
234 //=============================================================================
235 __syntaxFix__: "syntax fix"
236});
237
238//-----------------------------------------------------------------------------
239
240Clipperz.PM.UI.DirectLoginRunner.openDirectLogin = function (aDirectLogin) {
241 varrunner;
242
243 runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin});
244 return runner.run();
245};
246
247//-----------------------------------------------------------------------------
248
249Clipperz.PM.UI.DirectLoginRunner.testDirectLogin = function (aDirectLogin) {
250 varrunner;
251
252 runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin});
253 return runner.test();
254};
255
256//-----------------------------------------------------------------------------
diff --git a/frontend/delta/js/Clipperz/PM/UI/MainController.js b/frontend/delta/js/Clipperz/PM/UI/MainController.js
new file mode 100644
index 0000000..da7540e
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/MainController.js
@@ -0,0 +1,491 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.UI');
25
26Clipperz.PM.UI.MainController = function() {
27 var pages;
28
29 this._proxy = null;
30 this._user = null;
31 this._filter= '';
32
33 //this._currentPage = 'loadingPage';
34
35 this._pageStack = ['loadingPage'];
36 this._overlay = new Clipperz.PM.UI.Components.Overlay();
37 pages = {
38 'loginPage': new Clipperz.PM.UI.Components.LoginForm(),
39 'registrationPage':new Clipperz.PM.UI.Components.RegistrationWizard(),
40 'cardListPage': new Clipperz.PM.UI.Components.CardList(),
41 'cardDetailPage':new Clipperz.PM.UI.Components.CardDetail({card: {}}),
42 'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''})
43 };
44
45 MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages));
46 this._pages = pages;
47 this.registerForNotificationCenterEvents();
48
49 return this;
50}
51
52MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
53
54 toString: function () {
55 return "Clipperz.PM.UI.MainController";
56 },
57
58 //=========================================================================
59
60 overlay: function () {
61 return this._overlay;
62 },
63
64 loginForm: function () {
65 return this._loginForm;
66 },
67
68 registrationWizard: function () {
69 return this._registrationWizard;
70 },
71
72 //=========================================================================
73
74 isOnline: function() {
75 return navigator.onLine;
76 },
77
78 hasLocalData: function() {
79 return false;
80 },
81
82 loginMode: function () {
83 //PIN is set using this command:
84 //Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'});
85
86 return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS';
87 },
88
89 //=========================================================================
90
91 pages: function () {
92 return this._pages;
93 },
94
95 pageStack: function () {
96 return this._pageStack;
97 },
98
99 //=========================================================================
100
101 selectInitialProxy: function () {
102 if (this.isOnline()) {
103 this._proxy = Clipperz.PM.Proxy.defaultProxy;
104 } else {
105 if (this.hasLocalData()) {
106 this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false});
107 } else {
108 this.showOfflineError();
109 }
110 }
111 },
112
113 proxy: function () {
114 return this._proxy;
115 },
116
117 //=========================================================================
118
119 registerForNotificationCenterEvents: function () {
120 var events= ['doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack', 'showRecord', 'searchCards', 'runDirectLogin'];
121 var self= this;
122
123 MochiKit.Base.map(function (anEvent) {
124 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent));
125 }, events);
126
127 // MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack'));
128 MochiKit.Signal.connect(window, 'onbeforeunload',MochiKit.Base.method(this, 'shouldExitApp'));
129 },
130
131 //-------------------------------------------------------------------------
132
133 run: function (parameters) {
134 var shouldShowRegistrationForm;
135
136 this.selectInitialProxy();
137 shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && this.proxy().canRegisterNewUsers();
138 this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()});
139
140 if (shouldShowRegistrationForm) {
141 this.showRegistrationForm();
142 } else {
143 this.showLoginForm();
144 }
145 this.overlay().done("", 0.5);
146 },
147
148 //-------------------------------------------------------------------------
149
150 showLoginForm: function () {
151 varloginFormPage;
152
153 loginFormPage = this.pages()['loginPage'];
154 loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()});
155 this.moveInPage(this.currentPage(), 'loginPage');
156 MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus'));
157 },
158
159 showRegistrationForm: function () {
160 var currentPage;
161 varregistrationPage;
162
163 currentPage = this.currentPage();
164 registrationPage = this.pages()['registrationPage'];
165 this.setCurrentPage('loginPage');
166 registrationPage.setProps({});
167 this.moveInPage(currentPage, 'registrationPage');
168 MochiKit.Async.callLater(0.5, MochiKit.Base.method(registrationPage, 'setInitialFocus'));
169 },
170
171 //=========================================================================
172
173 doLogin: function (event) {
174 varcredentials;
175 var getPassphraseDelegate;
176 varuser;
177
178 user = null;
179
180 this.overlay().show("logging in");
181 this.pages()['loginPage'].setProps({disabled:true});
182
183 if ('pin' in event) {
184 credentials = Clipperz.PM.PIN.credentialsWithPIN(event['pin']);
185 } else {
186 credentials = event;
187 }
188 getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase);
189 user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate});
190
191 deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false});
192 deferredResult.addCallback(MochiKit.Async.wait, 0.1);
193 deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection');
194 deferredResult.addMethod(user, 'login');
195 deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount');
196 deferredResult.addMethod(this, 'setUser', user);
197
198 // deferredResult.addMethod(this, 'setupApplication');
199 deferredResult.addMethod(this, 'runApplication');
200 deferredResult.addMethod(this.overlay(), 'done', "", 1);
201 deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
202 deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) {
203 if (anError['isPermanent'] != true) {
204 this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()});
205 this.pages()['loginPage'].setInitialFocus();
206 }
207 return anError;
208 }, this, event))
209 deferredResult.callback();
210
211 return deferredResult;
212 },
213
214 //-------------------------------------------------------------------------
215
216 registerNewUser: function (credentials) {
217 vardeferredResult;
218
219 this.overlay().show("creating user");
220
221 this.pages()['registrationPage'].setProps({disabled:true});
222 deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false});
223 deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount,
224 credentials['username'],
225 MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase'])
226 );
227 deferredResult.addMethod(this, 'doLogin', credentials);
228 deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
229 deferredResult.addErrback(MochiKit.Base.bind(function (anError) {
230 if (anError['isPermanent'] != true) {
231 this.pages()['registrationPage'].setProps({disabled:false});
232 this.pages()['registrationPage'].setInitialFocus();
233 }
234 return anError;
235 }, this));
236
237 deferredResult.callback();
238
239 return deferredResult;
240
241 },
242
243 //-------------------------------------------------------------------------
244
245 user: function () {
246 return this._user;
247 },
248
249 setUser: function (aUser) {
250 this._user = aUser;
251 return this._user;
252 },
253
254 //=========================================================================
255
256 allCardInfo: function () {
257 var deferredResult;
258 varcardInfo;
259
260 cardInfo = {
261 '_rowObject': MochiKit.Async.succeed,
262 '_reference': MochiKit.Base.methodcaller('reference'),
263 '_searchableContent':MochiKit.Base.methodcaller('searchableContent'),
264 'label': MochiKit.Base.methodcaller('label'),
265 'favicon': MochiKit.Base.methodcaller('favicon')
266 };
267
268 deferredResult = new Clipperz.Async.Deferred('MainController.allCardInfo', {trace:false});
269 deferredResult.addMethod(this.user(), 'getRecords');
270 deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false}));
271 deferredResult.addCallback(Clipperz.Async.collectAll);
272 deferredResult.callback();
273
274 return deferredResult;
275 },
276
277 filterCards: function (someCardInfo) {
278 var filter;
279 varfilterRegExp;
280 varresult;
281
282 filter = this.filter().replace(/[^A-Za-z0-9]/g, "\\$&");
283 filterRegExp = new RegExp(filter, "i");
284 result = MochiKit.Base.filter(function (aCardInfo) { return filterRegExp.test(aCardInfo['_searchableContent'])}, someCardInfo);
285
286 return result;
287 },
288
289 sortCards: function (someCardInfo) {
290 return someCardInfo.sort(Clipperz.Base.caseInsensitiveKeyComparator('label'));
291 },
292
293 showRecordList: function () {
294 var deferredResult;
295
296 deferredResult = new Clipperz.Async.Deferred('MainController.showRecordList', {trace:false});
297 deferredResult.addMethod(this, 'allCardInfo');
298 deferredResult.addMethod(this, 'filterCards');
299 deferredResult.addMethod(this, 'sortCards');
300 deferredResult.addCallback(MochiKit.Base.bind(function (someRecordInfo) {
301 this.pages()['cardListPage'].setProps({cardList: someRecordInfo});
302 }, this));
303 deferredResult.callback();
304
305 return deferredResult;
306 },
307
308 filter: function (){
309 return this._filter;
310 },
311
312 setFilter: function (aValue) {
313 this._filter = aValue;
314 },
315
316 searchCards: function (someParameters) {
317//console.log("SEARCH CARDS", someParameters);
318 this.setFilter(someParameters);
319 this.showRecordList();
320 },
321
322 //=========================================================================
323
324 runApplication: function () {
325 MochiKit.Signal.connect(window, 'onpopstate',MochiKit.Base.method(this, 'historyGoBack'));
326 this.moveInPage(this.currentPage(), 'cardListPage');
327 return this.showRecordList();
328 },
329
330 showRecord: function (aRecordReference) {
331//console.log("Show Record", aRecordReference);
332 vardeferredResult;
333
334 this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
335 deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false});
336 // deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']);
337 deferredResult.addMethod(this.user(), 'getRecord', aRecordReference);
338 deferredResult.addMethodcaller('content');
339 deferredResult.addCallback(MochiKit.Base.bind(function (aCard) {
340//console.log("CARD DETAILS", aCard);
341 this.pages()['cardDetailPage'].setProps({card: aCard});
342 this.pages()['cardListPage'].setProps({selectedCard: null});
343 }, this));
344 deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true);
345 deferredResult.callback();
346
347 return deferredResult;
348 },
349
350 runDirectLogin: function (someParameters) {
351console.log("RUN DIRECT LOGIN", someParameters);
352 vardeferredResult;
353
354 // this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
355 deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false});
356 // deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']);
357 deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']);
358 deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']);
359 deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin);
360 deferredResult.callback();
361
362 return deferredResult;
363 },
364
365 shouldExitApp: function (anEvent) {
366console.log("SHOULD EXIT APP");
367 anEvent.preventDefault();
368 anEvent.stopPropagation();
369 },
370
371 //=========================================================================
372
373 genericErrorHandler: function (anEvent, anError) {
374 var errorMessage;
375 varresult;
376
377 result = anError;
378 errorMessage = "login failed";
379
380 if (anError['isPermanent'] === true) {
381 this.pages()['errorPage'].setProps({message:anError.message});
382 this.moveInPage(this.currentPage(), 'errorPage');
383 errorMessage = "failure";
384 } else {
385 if ('pin' in anEvent) {
386 errorCount = Clipperz.PM.PIN.recordFailedAttempt();
387 if (errorCount == -1) {
388 errorMessage = "PIN resetted";
389 }
390 }
391 }
392 this.overlay().failed(errorMessage, 1);
393
394 return result;
395 },
396
397 //=========================================================================
398
399 slidePage: function (fromPage, toPage, direction) {
400 varfromPosition;
401 var toPosition;
402
403 if (direction == "LEFT") {
404 fromPosition = 'right';
405 toPosition = 'left'
406 } else {
407 fromPosition = 'left';
408 toPosition = 'right'
409 }
410
411 MochiKit.DOM.addElementClass(fromPage, toPosition + ' transition');
412
413 MochiKit.DOM.addElementClass(toPage, fromPosition);
414 MochiKit.DOM.removeElementClass(toPage, toPosition);
415 MochiKit.DOM.addElementClass(toPage, 'transition');
416 MochiKit.Async.callLater(0.1, function () {
417 MochiKit.DOM.removeElementClass(toPage, fromPosition);
418 })
419
420 MochiKit.Async.callLater(0.5, function () {
421 MochiKit.DOM.removeElementClass(fromPage, 'transition');
422 MochiKit.DOM.removeElementClass(toPage, 'transition');
423 })
424 },
425
426 rotateInPage: function (fromPage, toPage) {
427 //Broken! :(
428 MochiKit.DOM.addElementClass(MochiKit.DOM.getElement('mainDiv'), 'show-right');
429 },
430
431 //.........................................................................
432
433 goBack: function () {
434 varfromPage;
435 var toPage;
436
437 fromPage = this.pageStack().shift();
438 toPage = this.currentPage();
439 this.pages()[toPage].setProps({});
440 this.moveOutPage(fromPage, toPage);
441 },
442
443 historyGoBack: function (anEvent) {
444 anEvent.preventDefault();
445 anEvent.stopPropagation();
446 this.goBack();
447 },
448
449 currentPage: function () {
450 return this.pageStack()[0];
451 },
452
453 setCurrentPage: function (aPage) {
454 this.pageStack().unshift(aPage);
455 },
456
457 moveInPage: function (fromPage, toPage, addToHistory) {
458 varshouldAddItemToHistory;
459
460 shouldAddItemToHistory = typeof(addToHistory) == 'undefined' ? false : addToHistory;
461
462 this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'LEFT');
463 this.setCurrentPage(toPage);
464
465 if (shouldAddItemToHistory) {
466//console.log("ADD ITEM TO HISTORY");
467//console.log("ADD ITEM TO HISTORY - window", window);
468//console.log("ADD ITEM TO HISTORY - window.history", window.history);
469 window.history.pushState({'fromPage': fromPage, 'toPage': toPage});
470 //# window.history.pushState();
471//console.log("ADDED ITEM TO HISTORY");
472 } else {
473//console.log("Skip HISTORY");
474 }
475 },
476
477 moveOutPage: function (fromPage, toPage) {
478 this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT');
479 this.setCurrentPage(toPage);
480 },
481
482 //=========================================================================
483/*
484 wrongAppVersion: function (anError) {
485 // this.pages()['errorPage'].setProps({message:anError.message});
486 // this.moveInPage('errorPage', this.currentPage());
487 },
488*/
489 //=========================================================================
490 __syntaxFix__: "syntax fix"
491});
diff --git a/frontend/delta/js/Clipperz/Set.js b/frontend/delta/js/Clipperz/Set.js
new file mode 100644
index 0000000..b3831a4
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Set.js
@@ -0,0 +1,162 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24
25if (typeof(Clipperz) == 'undefined') {
26 Clipperz = {};
27}
28
29//#############################################################################
30
31Clipperz.Set = function(args) {
32 args = args || {};
33 //MochiKit.Base.bindMethods(this);
34
35 if (args.items != null) {
36 this._items = args.items.slice();
37 } else {
38 this._items = [];
39 }
40
41 return this;
42}
43
44//=============================================================================
45
46Clipperz.Set.prototype = MochiKit.Base.update(null, {
47
48 //-------------------------------------------------------------------------
49
50 'toString': function() {
51 return "Clipperz.Set";
52 },
53
54 //-------------------------------------------------------------------------
55
56 'items': function() {
57 return this._items;
58 },
59
60 //-------------------------------------------------------------------------
61
62 'popAnItem': function() {
63 var result;
64
65 if (this.size() > 0) {
66 result = this.items().pop();
67 } else {
68 result = null;
69 }
70
71 return result;
72 },
73
74 //-------------------------------------------------------------------------
75
76 'allItems': function() {
77 return this.items();
78 },
79
80 //-------------------------------------------------------------------------
81
82 'contains': function(anItem) {
83 return (this.indexOf(anItem) != -1);
84 },
85
86 //-------------------------------------------------------------------------
87
88 'indexOf': function(anItem) {
89 varresult;
90 vari, c;
91
92 result = -1;
93
94 c = this.items().length;
95 for (i=0; (i<c) && (result == -1); i++) {
96 if (this.items()[i] === anItem) {
97 result = i;
98 }
99 }
100
101 return result;
102 },
103
104 //-------------------------------------------------------------------------
105
106 'add': function(anItem) {
107 if (anItem.constructor == Array) {
108 MochiKit.Base.map(MochiKit.Base.bind(this,add, this), anItem);
109 } else {
110 if (! this.contains(anItem)) {
111 this.items().push(anItem);
112 }
113 }
114 },
115
116 //-------------------------------------------------------------------------
117
118 'debug': function() {
119 vari, c;
120
121 result = -1;
122
123 c = this.items().length;
124 for (i=0; i<c; i++) {
125 alert("[" + i + "] " + this.items()[i].label);
126 }
127 },
128
129 //-------------------------------------------------------------------------
130
131 'remove': function(anItem) {
132 if (anItem.constructor == Array) {
133 MochiKit.Base.map(MochiKit.Base.bind(this.remove, this), anItem);
134 } else {
135 varitemIndex;
136
137 itemIndex = this.indexOf(anItem);
138 if (itemIndex != -1) {
139 this.items().splice(itemIndex, 1);
140 }
141 }
142 },
143
144 //-------------------------------------------------------------------------
145
146 'size': function() {
147 return this.items().length;
148 },
149
150 //-------------------------------------------------------------------------
151
152 'empty': function() {
153 this.items().splice(0, this.items().length);
154 },
155
156 //-------------------------------------------------------------------------
157
158 __syntaxFix__: "syntax fix"
159
160 //-------------------------------------------------------------------------
161});
162
diff --git a/frontend/delta/js/Clipperz/Signal.js b/frontend/delta/js/Clipperz/Signal.js
new file mode 100644
index 0000000..f9b74c9
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Signal.js
@@ -0,0 +1,66 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Signal) == 'undefined') { Clipperz.Signal = {}; }
26
27Clipperz.Signal.VERSION = "0.1";
28Clipperz.Signal.NAME = "Clipperz.Signal";
29
30MochiKit.Base.update(Clipperz.Signal, {
31
32 //-------------------------------------------------------------------------
33
34 '__repr__': function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36 },
37
38 //-------------------------------------------------------------------------
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-------------------------------------------------------------------------
45
46 'fireNativeEvent': function(element, eventName) {
47 if (element.fireEvent) {
48 // MSIE
49 element.fireEvent(eventName);
50 } else {
51 // W3C
52 var event;
53
54 event = document.createEvent("HTMLEvents");
55 event.initEvent(eventName.replace(/^on/, ""), true, true);
56 element.dispatchEvent(event);
57 }
58 },
59
60 //-------------------------------------------------------------------------
61 __syntaxFix__: "syntax fix"
62
63});
64
65Clipperz.Signal.NotificationCenter = {};
66
diff --git a/frontend/delta/js/Clipperz/Style.js b/frontend/delta/js/Clipperz/Style.js
new file mode 100644
index 0000000..acbe71b
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Style.js
@@ -0,0 +1,89 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Style) == 'undefined') { Clipperz.Style = {}; }
26
27Clipperz.Style.VERSION = "0.1";
28Clipperz.Style.NAME = "Clipperz.DOM";
29
30MochiKit.Base.update(Clipperz.Style, {
31
32 //-------------------------------------------------------------------------
33
34 '__repr__': function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36 },
37
38 //-------------------------------------------------------------------------
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-------------------------------------------------------------------------
45
46 'applyZebraStylesToTable': function(aTable) {
47 var tbody;
48 var tbodyRows;
49 var i,c;
50
51 tbody = MochiKit.DOM.getFirstElementByTagAndClassName('tbody', null, aTable);
52 tbodyRows = tbody.childNodes;
53 // tbodyRows = MochiKit.DOM.getElementsByTagAndClassName('tr', null, tbody)
54 c = tbodyRows.length;
55 for (i=0; i<c; i++) {
56 var element;
57
58 element = YAHOO.Element.get(tbodyRows[i]);
59 element.addClass(((i%2 == 0) ? "zebra_odd": "zebra_even"));
60 element.removeClass(((i%2 == 1) ? "zebra_odd": "zebra_even"));
61 }
62 },
63
64 //-------------------------------------------------------------------------
65
66 'getSizeAndPosition': function (anElement) {
67 var result;
68
69 if (anElement != null) {
70 result ={ dimensions:MochiKit.Style.getElementDimensions(anElement), position:MochiKit.Style.getElementPosition(anElement)};
71 } else {
72 result ={ dimensions:MochiKit.Style.getViewportDimensions(), position:MochiKit.Style.getViewportPosition()};
73 }
74
75 return result;
76 },
77
78 'setBackgroundGradient': function (anElement, someParameters) {
79 // background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ff9955), to(#ff6622), color-stop(1,#333333));
80 // background: -moz-linear-gradient(0% 100% 90deg,#ff6622, #ff9955);
81 MochiKit.Style.setStyle(anElement, {'background': '-webkit-gradient(linear, 0% 0%, 0% 100%, from(' + someParameters['from'] + '), to(' + someParameters['to'] + '), color-stop(1,#333333))'});
82 MochiKit.Style.setStyle(anElement, {'background': '-moz-linear-gradient(0% 100% 90deg,' + someParameters['to'] + ', ' + someParameters['from'] + ')'});
83 },
84
85 //-------------------------------------------------------------------------
86 __syntaxFix__: "syntax fix"
87
88});
89
diff --git a/frontend/delta/js/Clipperz/Visual.js b/frontend/delta/js/Clipperz/Visual.js
new file mode 100644
index 0000000..93ed725
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Visual.js
@@ -0,0 +1,363 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.Visual) == 'undefined') { Clipperz.Visual = {}; }
26
27Clipperz.Visual.VERSION = "0.1";
28Clipperz.Visual.NAME = "Clipperz.Visual";
29
30MochiKit.Base.update(Clipperz.Visual, {
31
32 //-------------------------------------------------------------------------
33
34 '__repr__': function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36 },
37
38 //-------------------------------------------------------------------------
39
40 'toString': function () {
41 return this.__repr__();
42 },
43
44 //-------------------------------------------------------------------------
45
46 'deferredResize': function (anElement, someOptions) {
47 var deferredResult;
48 var moveTransition;
49 var scaleTransition;
50 var duration;
51
52 duration = someOptions.duration || 0.5;
53
54 deferredResult = new Clipperz.Async.Deferred("Visual.deferredResize", {trace:false});
55 deferredResult.addCallback(MochiKit.Async.succeed, arguments[arguments.length - 1]);
56
57 moveTransition = MochiKit.Visual.Transitions.linear;//MochiKit.Visual.Transitions.sinoidal;
58 scaleTransition = MochiKit.Visual.Transitions.linear;//MochiKit.Visual.Transitions.sinoidal;
59
60 MochiKit.Style.setElementPosition(anElement, {x:someOptions.from.position.x, y:someOptions.from.position.y }, 'px');
61
62 new MochiKit.Visual.Parallel([
63 new MochiKit.Visual.Move(anElement, {x:someOptions.to.position.x, y:someOptions.to.position.y, mode:'absolute', transition:moveTransition, sync:true}),
64 new Clipperz.Visual.Resize(anElement, {fromSize:{h:someOptions.from.dimensions.h, w:someOptions.from.dimensions.w}, toSize:{h:someOptions.to.dimensions.h, w:someOptions.to.dimensions.w}, transition:scaleTransition, scaleContent:false, scaleFromCenter:false, restoreAfterFinish:true, sync:true})
65 ], {duration:duration, afterFinish:MochiKit.Base.method(deferredResult, 'callback')})
66
67 return deferredResult;
68 },
69
70 //-------------------------------------------------------------------------
71
72 'deferredAnimation': function (anAnimation, someParameters, someOptions) {
73 vardeferredResult;
74 var afterFinishCallback;
75 var options;
76
77 deferredResult = new Clipperz.Async.Deferred("Clipperz.Visual.deferredAnimation", {trace:false});
78 deferredResult.addCallback(MochiKit.Async.succeed, arguments[arguments.length - 1]);
79
80 if (MochiKit.Base.isUndefinedOrNull(someOptions)) {
81 options = {}
82 } else {
83 options = someOptions;
84 }
85
86 if (MochiKit.Base.isUndefinedOrNull(someOptions['afterFinish'])) {
87 options['afterFinish'] = MochiKit.Base.noop;
88 }
89
90 MochiKit.Base.update(options, {
91 'afterFinish': MochiKit.Base.compose(options['afterFinish'], MochiKit.Base.method(deferredResult, 'callback'))
92 });
93
94 new anAnimation(someParameters, options);
95
96 return deferredResult;
97 },
98
99 //-------------------------------------------------------------------------
100
101 'deferredAnimations': function (aSinchronizationType, someAnimations, someOptions) {
102 var deferredResult;
103 varoptions;
104
105 deferredResult = new Clipperz.Async.Deferred("Visual.deferredParallelAnimations", {trace:false});
106 deferredResult.addCallback(MochiKit.Async.succeed, arguments[arguments.length - 1]);
107
108 options = someOptions;
109 if (MochiKit.Base.isUndefinedOrNull(someOptions['afterFinish'])) {
110 options['afterFinish'] = MochiKit.Base.noop;
111 }
112 MochiKit.Base.update(options, {
113 'afterFinish': MochiKit.Base.compose(options['afterFinish'], MochiKit.Base.method(deferredResult, 'callback'))
114 });
115
116 new aSinchronizationType(someAnimations, options)
117
118 return deferredResult;
119 },
120
121 //-------------------------------------------------------------------------
122 __syntaxFix__: "syntax fix"
123
124});
125
126//#############################################################################
127
128/** @id Clipperz.Visual.Resize */
129Clipperz.Visual.Resize = function (element, percent, options) {
130 var cls = arguments.callee;
131 if (!(this instanceof cls)) {
132 return new cls(element, percent, options);
133 }
134 this.__init__(element, percent, options);
135};
136
137Clipperz.Visual.Resize.prototype = new MochiKit.Visual.Base();
138
139MochiKit.Base.update(Clipperz.Visual.Resize.prototype, {
140 __class__ : Clipperz.Visual.Resize,
141
142 __init__: function (element, options) {
143 this.element = MochiKit.DOM.getElement(element);
144 options = MochiKit.Base.update({
145 scaleX: true,
146 scaleY: true,
147 scaleContent: true,
148 scaleFromCenter: false,
149 scaleMode: 'box', // 'box' or 'contents' or {} with provided values
150 syntax_fix: 'syntax fix'
151 }, options);
152
153 this.start(options);
154 },
155
156 setup: function () {
157 this.restoreAfterFinish = this.options.restoreAfterFinish || false;
158 this.elementPositioning = MochiKit.Style.getStyle(this.element, 'position');
159
160 var ma = MochiKit.Base.map;
161 var b = MochiKit.Base.bind;
162 this.originalStyle = {};
163 ma(b(function (k) { this.originalStyle[k] = this.element.style[k]; }, this), ['top', 'left', 'width', 'height', 'fontSize']);
164
165 this.originalTop = this.element.offsetTop;
166 this.originalLeft = this.element.offsetLeft;
167
168 var fontSize = MochiKit.Style.getStyle(this.element, 'font-size') || '100%';
169 ma(b(function (fontSizeType) {
170 if (fontSize.indexOf(fontSizeType) > 0) {
171 this.fontSize = parseFloat(fontSize);
172 this.fontSizeType = fontSizeType;
173 }
174 }, this), ['em', 'px', '%']);
175
176 this.factor = 1;
177
178 this.dims = [this.options.fromSize.h, this.options.fromSize.w];
179 },
180
181 update: function (position) {
182 this.setDimensions((this.options.toSize.h - this.options.fromSize.h) * position + this.options.fromSize.h,
183 (this.options.toSize.w - this.options.fromSize.w) * position + this.options.fromSize.w);
184 },
185
186 finish: function () {
187 if (this.restoreAfterFinish) {
188 MochiKit.Style.setStyle(this.element, this.originalStyle);
189 }
190 },
191
192 setDimensions: function (height, width) {
193 var d = {};
194 var r = Math.round;
195 if (/MSIE/.test(navigator.userAgent)) {
196 r = Math.ceil;
197 }
198 if (this.options.scaleX) {
199 d.width = r(width) + 'px';
200 }
201 if (this.options.scaleY) {
202 d.height = r(height) + 'px';
203 }
204 if (this.options.scaleFromCenter) {
205 var topd = (height - this.dims[0])/2;
206 var leftd = (width - this.dims[1])/2;
207 if (this.elementPositioning == 'absolute') {
208 if (this.options.scaleY) {
209 d.top = this.originalTop - topd + 'px';
210 }
211 if (this.options.scaleX) {
212 d.left = this.originalLeft - leftd + 'px';
213 }
214 } else {
215 if (this.options.scaleY) {
216 d.top = -topd + 'px';
217 }
218 if (this.options.scaleX) {
219 d.left = -leftd + 'px';
220 }
221 }
222 }
223 MochiKit.Style.setStyle(this.element, d);
224 }
225});
226
227//=============================================================================
228
229Clipperz.Visual.squize = function (element, /* optional */ options) {
230 var d = MochiKit.DOM;
231 var v = MochiKit.Visual;
232 var s = MochiKit.Style;
233
234 element = d.getElement(element);
235 options = MochiKit.Base.update({
236 moveTransition: v.Transitions.sinoidal,
237 scaleTransition: v.Transitions.sinoidal,
238 opacityTransition: v.Transitions.none,
239 scaleContent: true,
240 scaleFromCenter: false,
241 scaleX: true,
242 scaleY: true
243 }, options);
244 var oldStyle = {
245 top: element.style.top,
246 left: element.style.left,
247 height: element.style.height,
248 width: element.style.width,
249 opacity: s.getStyle(element, 'opacity')
250 };
251
252 var dims = s.getElementDimensions(element, true);
253 var moveX, moveY;
254
255 moveX = options.scaleX ? dims.w/2 : 0;
256 moveY = options.scaleY ? dims.h/2 : 0;
257
258 var elemClip;
259
260 var optionsParallel = MochiKit.Base.update({
261 beforeStartInternal: function (effect) {
262 s.makePositioned(effect.effects[0].element);
263 elemClip = s.makeClipping(effect.effects[0].element);
264 },
265 afterFinishInternal: function (effect) {
266 s.hideElement(effect.effects[0].element);
267 s.undoClipping(effect.effects[0].element, elemClip);
268 s.undoPositioned(effect.effects[0].element);
269 s.setStyle(effect.effects[0].element, oldStyle);
270 }
271 }, options);
272
273 return new v.Parallel(
274 [new v.Opacity(element, {
275 sync: true, to: 0.0, from: 1.0,
276 transition: options.opacityTransition
277 }),
278 new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
279 scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
280 sync: true, transition: options.scaleTransition,
281 scaleContent: options.scaleContent,
282 scaleFromCenter: options.scaleFromCenter,
283 restoreAfterFinish: true,
284 scaleX: options.scaleX,
285 scaleY: options.scaleY
286 }),
287 new v.Move(element, {
288 x: moveX, y: moveY, sync: true, transition: options.moveTransition
289 })
290 ], optionsParallel
291 );
292};
293
294//-----------------------------------------------------------------------------
295
296Clipperz.Visual.expand = function (element, /* optional */ options) {
297 var d = MochiKit.DOM;
298 var v = MochiKit.Visual;
299 var s = MochiKit.Style;
300
301 element = d.getElement(element);
302 options = MochiKit.Base.update({
303 // direction: 'center',
304 moveTransition: v.Transitions.sinoidal,
305 scaleTransition: v.Transitions.sinoidal,
306 opacityTransition: v.Transitions.none,
307 scaleContent: true,
308 scaleFromCenter: false,
309 scaleX: true,
310 scaleY: true
311 }, options);
312 var oldStyle = {
313 top: element.style.top,
314 left: element.style.left,
315 height: element.style.height,
316 width: element.style.width,
317 opacity: s.getStyle(element, 'opacity')
318 };
319
320 var dims = s.getElementDimensions(element, true);
321 var moveX, moveY;
322
323 moveX = options.scaleX ? dims.w/2 : 0;
324 moveY = options.scaleY ? dims.h/2 : 0;
325
326 var elemClip;
327
328 var optionsParallel = MochiKit.Base.update({
329 beforeStartInternal: function (effect) {
330 s.makePositioned(effect.effects[0].element);
331 elemClip = s.makeClipping(effect.effects[0].element);
332 },
333 afterFinishInternal: function (effect) {
334 s.hideElement(effect.effects[0].element);
335 s.undoClipping(effect.effects[0].element, elemClip);
336 s.undoPositioned(effect.effects[0].element);
337 s.setStyle(effect.effects[0].element, oldStyle);
338 }
339 }, options);
340
341 return new v.Parallel(
342 [new v.Opacity(element, {
343 sync: true, to: 0.0, from: 1.0,
344 transition: options.opacityTransition
345 }),
346 new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
347 scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
348 sync: true, transition: options.scaleTransition,
349 scaleContent: options.scaleContent,
350 scaleFromCenter: options.scaleFromCenter,
351 restoreAfterFinish: true,
352 scaleX: options.scaleX,
353 scaleY: options.scaleY
354 }),
355 new v.Move(element, {
356 x: moveX, y: moveY, sync: true, transition: options.moveTransition
357 })
358 ], optionsParallel
359 );
360};
361
362//=============================================================================
363
diff --git a/frontend/delta/js/Clipperz/YUI/DomHelper.js b/frontend/delta/js/Clipperz/YUI/DomHelper.js
new file mode 100644
index 0000000..0a1f9fe
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/YUI/DomHelper.js
@@ -0,0 +1,471 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
26
27
28/**
29 * @class Clipperz.ext.DomHelper
30 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
31 * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
32 * @singleton
33 */
34Clipperz.YUI.DomHelper = new function(){
35 /**@private*/
36 var d = document;
37 var tempTableEl = null;
38 /** True to force the use of DOM instead of html fragments @type Boolean */
39 this.useDom = false;
40 var emptyTags = /^(?:base|basefont|br|frame|hr|img|input|isindex|link|meta|nextid|range|spacer|wbr|audioscope|area|param|keygen|col|limittext|spot|tab|over|right|left|choose|atop|of)$/i;
41 /**
42 * Applies a style specification to an element
43 * @param {String/HTMLElement} el The element to apply styles to
44 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
45 * a function which returns such a specification.
46 */
47 this.applyStyles = function(el, styles){
48 if(styles){
49 var D = YAHOO.util.Dom;
50 if (typeof styles == "string"){
51 var re = /\s?([a-z\-]*)\:([^;]*);?/gi;
52 var matches;
53 while ((matches = re.exec(styles)) != null){
54 D.setStyle(el, matches[1], matches[2]);
55 }
56 }else if (typeof styles == "object"){
57 for (var style in styles){
58 D.setStyle(el, style, styles[style]);
59 }
60 }else if (typeof styles == "function"){
61 Clipperz.YUI.DomHelper.applyStyles(el, styles.call());
62 }
63 }
64 };
65
66 // build as innerHTML where available
67 /** @ignore */
68 var createHtml = function(o){
69 var b = '';
70
71 if(typeof(o['html']) != 'undefined') {
72 o['html'] = Clipperz.Base.sanitizeString(o['html']);
73 } else if (typeof(o['htmlString']) != 'undefined') {
74 o['html'] = o['htmlString'];
75 delete o.htmlString;
76 }
77
78 if (MochiKit.Base.isArrayLike(o)) {
79 for (var i = 0, l = o.length; i < l; i++) {
80 b += createHtml(o[i]);
81 }
82 return b;
83 }
84
85 b += '<' + o.tag;
86 for(var attr in o){
87 if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue;
88 if(attr == 'style'){
89 var s = o['style'];
90 if(typeof s == 'function'){
91 s = s.call();
92 }
93 if(typeof s == 'string'){
94 b += ' style="' + s + '"';
95 }else if(typeof s == 'object'){
96 b += ' style="';
97 for(var key in s){
98 if(typeof s[key] != 'function'){
99 b += key + ':' + s[key] + ';';
100 }
101 }
102 b += '"';
103 }
104 }else{
105 if(attr == 'cls'){
106 b += ' class="' + o['cls'] + '"';
107 }else if(attr == 'htmlFor'){
108 b += ' for="' + o['htmlFor'] + '"';
109 }else{
110 b += ' ' + attr + '="' + o[attr] + '"';
111 }
112 }
113 }
114 if(emptyTags.test(o.tag)){
115 b += ' />';
116 }else{
117 b += '>';
118 if(o.children){
119 for(var i = 0, len = o.children.length; i < len; i++) {
120 b += createHtml(o.children[i], b);
121 }
122 }
123 if(o.html){
124 b += o.html;
125 }
126 b += '</' + o.tag + '>';
127 }
128 return b;
129 }
130
131 // build as dom
132 /** @ignore */
133 var createDom = function(o, parentNode){
134 var el = d.createElement(o.tag);
135 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
136 for(var attr in o){
137 if(attr == 'tag' || attr == 'children' || attr == 'html' || attr == 'style' || typeof o[attr] == 'function') continue;
138 if(attr=='cls'){
139 el.className = o['cls'];
140 }else{
141 if(useSet) el.setAttribute(attr, o[attr]);
142 else el[attr] = o[attr];
143 }
144 }
145 Clipperz.YUI.DomHelper.applyStyles(el, o.style);
146 if(o.children){
147 for(var i = 0, len = o.children.length; i < len; i++) {
148 createDom(o.children[i], el);
149 }
150 }
151 if(o.html){
152 el.innerHTML = o.html;
153 }
154 if(parentNode){
155 parentNode.appendChild(el);
156 }
157 return el;
158 };
159
160 /**
161 * @ignore
162 * Nasty code for IE's broken table implementation
163 */
164 var insertIntoTable = function(tag, where, el, html){
165 if(!tempTableEl){
166 tempTableEl = document.createElement('div');
167 }
168 var nodes;
169 if(tag == 'table' || tag == 'tbody'){
170 tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>';
171 nodes = tempTableEl.firstChild.firstChild.childNodes;
172 }else{
173 tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>';
174 nodes = tempTableEl.firstChild.firstChild.firstChild.childNodes;
175 }
176 if (where == 'beforebegin') {
177 nodes.reverse();
178 // el.parentNode.insertBefore(node, el);
179 MochiKit.Base.map(function(aNode) {el.parentNode.insertBefore(aNode, el)}, nodes);
180 } else if (where == 'afterbegin') {
181 nodes.reverse();
182 // el.insertBefore(node, el.firstChild);
183 MochiKit.Base.map(function(aNode) {el.insertBefore(aNode, el.firstChild)}, nodes);
184 } else if (where == 'beforeend') {
185 // el.appendChild(node);
186 MochiKit.Base.map(function(aNode) {el.appendChild(aNode)}, nodes);
187 } else if (where == 'afterend') {
188 // el.parentNode.insertBefore(node, el.nextSibling);
189 MochiKit.Base.map(function(aNode) {el.parentNode.insertBefore(aNode, el.nextSibling)}, nodes);
190 }
191
192 return nodes;
193 }
194
195 /**
196 * Inserts an HTML fragment into the Dom
197 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
198 * @param {HTMLElement} el The context element
199 * @param {String} html The HTML fragmenet
200 * @return {HTMLElement} The new node
201 */
202 this.insertHtml = function(where, el, html){
203 where = where.toLowerCase();
204 // if(el.insertAdjacentHTML){
205 if(Clipperz_IEisBroken){
206 var tag = el.tagName.toLowerCase();
207 if(tag == 'table' || tag == 'tbody' || tag == 'tr'){
208 return insertIntoTable(tag, where, el, html);
209 }
210 switch(where){
211 case 'beforebegin':
212 el.insertAdjacentHTML(where, html);
213 return el.previousSibling;
214 case 'afterbegin':
215 el.insertAdjacentHTML(where, html);
216 return el.firstChild;
217 case 'beforeend':
218 el.insertAdjacentHTML(where, html);
219 return el.lastChild;
220 case 'afterend':
221 el.insertAdjacentHTML(where, html);
222 return el.nextSibling;
223 }
224 throw 'Illegal insertion point -> "' + where + '"';
225 }
226 var range = el.ownerDocument.createRange();
227 var frag;
228 switch(where){
229 case 'beforebegin':
230 range.setStartBefore(el);
231 frag = range.createContextualFragment(html);
232 el.parentNode.insertBefore(frag, el);
233 return el.previousSibling;
234 case 'afterbegin':
235 if(el.firstChild){ // faster
236 range.setStartBefore(el.firstChild);
237 }else{
238 range.selectNodeContents(el);
239 range.collapse(true);
240 }
241 frag = range.createContextualFragment(html);
242 el.insertBefore(frag, el.firstChild);
243 return el.firstChild;
244 case 'beforeend':
245 if(el.lastChild){
246 range.setStartAfter(el.lastChild); // faster
247 }else{
248 range.selectNodeContents(el);
249 range.collapse(false);
250 }
251 frag = range.createContextualFragment(html);
252 el.appendChild(frag);
253 return el.lastChild;
254 case 'afterend':
255 range.setStartAfter(el);
256 frag = range.createContextualFragment(html);
257 el.parentNode.insertBefore(frag, el.nextSibling);
258 return el.nextSibling;
259 }
260 throw 'Illegal insertion point -> "' + where + '"';
261 };
262
263 /**
264 * Creates new Dom element(s) and inserts them before el
265 * @param {String/HTMLElement/Element} el The context element
266 * @param {Object} o The Dom object spec (and children)
267 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
268 * @return {HTMLElement} The new node
269 */
270 this.insertBefore = function(el, o, returnElement){
271 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
272 var newNode;
273 if(this.useDom){
274 newNode = createDom(o, null);
275 el.parentNode.insertBefore(newNode, el);
276 }else{
277 var html = createHtml(o);
278 newNode = this.insertHtml('beforeBegin', el, html);
279 }
280 return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
281 };
282
283 /**
284 * Creates new Dom element(s) and inserts them after el
285 * @param {String/HTMLElement/Element} el The context element
286 * @param {Object} o The Dom object spec (and children)
287 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
288 * @return {HTMLElement} The new node
289 */
290 this.insertAfter = function(el, o, returnElement){
291 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
292 var newNode;
293 if(this.useDom){
294 newNode = createDom(o, null);
295 el.parentNode.insertBefore(newNode, el.nextSibling);
296 }else{
297 var html = createHtml(o);
298 newNode = this.insertHtml('afterEnd', el, html);
299 }
300 return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
301 };
302
303 /**
304 * Creates new Dom element(s) and appends them to el
305 * @param {String/HTMLElement/Element} el The context element
306 * @param {Object} o The Dom object spec (and children)
307 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
308 * @return {HTMLElement} The new node
309 */
310 this.append = function(el, o, returnElement){
311 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
312 var newNode;
313 if(this.useDom){
314 newNode = createDom(o, null);
315 el.appendChild(newNode);
316 }else{
317 var html = createHtml(o);
318 newNode = this.insertHtml('beforeEnd', el, html);
319 }
320 return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
321 };
322
323 /**
324 * Creates new Dom element(s) and overwrites the contents of el with them
325 * @param {String/HTMLElement/Element} el The context element
326 * @param {Object} o The Dom object spec (and children)
327 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
328 * @return {HTMLElement} The new node
329 */
330 this.overwrite = function(el, o, returnElement){
331 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
332 el.innerHTML = createHtml(o);
333 return returnElement ? YAHOO.Element.get(el.firstChild, true) : el.firstChild;
334 };
335
336 /**
337 * Creates a new Clipperz.YUI.DomHelper.Template from the Dom object spec
338 * @param {Object} o The Dom object spec (and children)
339 * @return {Clipperz.YUI.DomHelper.Template} The new template
340 */
341 this.createTemplate = function(o){
342 var html = createHtml(o);
343 return new Clipperz.YUI.DomHelper.Template(html);
344 };
345}();
346
347/**
348* @class Clipperz.YUI.DomHelper.Template
349* Represents an HTML fragment template.
350* For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
351* <br>
352* <b>This class is also available as Clipperz.YUI.Template</b>.
353* @constructor
354* @param {String/Array} html The HTML fragment or an array of fragments to join('') or multiple arguments to join('')
355*/
356Clipperz.YUI.DomHelper.Template = function(html){
357 if(html instanceof Array){
358 html = html.join('');
359 }else if(arguments.length > 1){
360 html = Array.prototype.join.call(arguments, '');
361 }
362 /**@private*/
363 this.html = html;
364};
365Clipperz.YUI.DomHelper.Template.prototype = {
366 /**
367 * Returns an HTML fragment of this template with the specified values applied
368 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
369 * @return {String}
370 */
371 applyTemplate : function(values){
372 if(this.compiled){
373 return this.compiled(values);
374 }
375 var empty = '';
376 var fn = function(match, index){
377 if(typeof values[index] != 'undefined'){
378 return values[index];
379 }else{
380 return empty;
381 }
382 }
383 return this.html.replace(this.re, fn);
384 },
385
386 /**
387 * The regular expression used to match template variables
388 * @type RegExp
389 * @property
390 */
391 re : /\{([\w|-]+)\}/g,
392
393 /**
394 * Compiles the template into an internal function, eliminating the RegEx overhead
395 */
396 compile : function(){
397 var body = ["this.compiled = function(values){ return ['"];
398 body.push(this.html.replace(this.re, "', values['$1'], '"));
399 body.push("'].join('');};");
400 eval(body.join(''));
401 return this;
402 },
403
404 /**
405 * Applies the supplied values to the template and inserts the new node(s) before el
406 * @param {String/HTMLElement/Element} el The context element
407 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
408 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
409 * @return {HTMLElement} The new node
410 */
411 insertBefore: function(el, values, returnElement){
412 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
413 var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeBegin', el, this.applyTemplate(values));
414 return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
415 },
416
417 /**
418 * Applies the supplied values to the template and inserts the new node(s) after el
419 * @param {String/HTMLElement/Element} el The context element
420 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
421 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
422 * @return {HTMLElement} The new node
423 */
424 insertAfter : function(el, values, returnElement){
425 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
426 var newNode = Clipperz.YUI.DomHelper.insertHtml('afterEnd', el, this.applyTemplate(values));
427 return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
428 },
429
430 /**
431 * Applies the supplied values to the template and append the new node(s) to el
432 * @param {String/HTMLElement/Element} el The context element
433 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
434 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
435 * @return {HTMLElement} The new node
436 */
437 append : function(el, values, returnElement){
438 var sanitizedValues;
439 var key;
440
441 sanitizedValues = {};
442 for (key in values) {
443 sanitizedValues[key] = Clipperz.Base.sanitizeString(values[key]);
444 }
445 el = (typeof el == 'string') ? YAHOO.util.Dom.get(el) : el;
446 var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(sanitizedValues));
447
448 return newNode;
449 },
450
451 /**
452 * Applies the supplied values to the template and overwrites the content of el with the new node(s)
453 * @param {String/HTMLElement/Element} el The context element
454 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
455 * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
456 * @return {HTMLElement} The new node
457 */
458 overwrite : function(el, values, returnElement){
459 el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
460 el.innerHTML = '';
461 var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values));
462 return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
463 }
464};
465/**
466 * Alias for applyTemplate
467 * @method
468 */
469Clipperz.YUI.DomHelper.Template.prototype.apply = Clipperz.YUI.DomHelper.Template.prototype.applyTemplate;
470
471Clipperz.YUI.Template = Clipperz.YUI.DomHelper.Template;
diff --git a/frontend/delta/js/Clipperz/YUI/DomQuery.js b/frontend/delta/js/Clipperz/YUI/DomQuery.js
new file mode 100644
index 0000000..c1af0ca
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/YUI/DomQuery.js
@@ -0,0 +1,709 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
26
27
28/*
29 * yui-ext 0.40
30 * Copyright(c) 2006, Jack Slocum.
31 */
32
33/**
34 * @class Clipperz.YUI.DomQuery
35 * Provides high performance selector/xpath processing by compiling queries into reusable functions.
36 * New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
37 * @singleton
38 */
39Clipperz.YUI.DomQuery = function(){
40 var cache = {}, simpleCache = {}, valueCache = {};
41 var nonSpace = /\S/;
42 var trimRe = /^\s*(.*?)\s*$/;
43 var tplRe = /\{(\d+)\}/g;
44 var modeRe = /^(\s?[\/>]\s?|\s|$)/;
45 var clsRes = {};
46
47 function child(p, index){
48 var i = 0;
49 var n = p.firstChild;
50 while(n){
51 if(n.nodeType == 1){
52 i++;
53 if(i == index){
54 return n;
55 }
56 }
57 n = n.nextSibling;
58 }
59 return null;
60 };
61
62 function next(d){
63 var n = d.nextSibling;
64 while(n && n.nodeType != 1){
65 n = n.nextSibling;
66 }
67 return n;
68 };
69
70 function prev(d){
71 var n = d.previousSibling;
72 while(n && n.nodeType != 1){
73 n = n.previousSibling;
74 }
75 return n;
76 };
77
78 function clean(d){
79 var n = d.firstChild, ni = -1;
80 while(n){
81 var nx = n.nextSibling;
82 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
83 d.removeChild(n);
84 }else{
85 n.nodeIndex = ++ni;
86 }
87 n = nx;
88 }
89 return this;
90 };
91
92 function byClassName(c, a, v){
93 if(!v){
94 return c;
95 }
96 var re = clsRes[v];
97 if(!re){
98 re = new RegExp('(?:^|\\s)(?:' + v + ')(?:\\s|$)');
99 clsRes[v] = re;
100 }
101 var r = [];
102 for(var i = 0, ci; ci = c[i]; i++){
103 if(re.test(ci.className)){
104 r[r.length] = ci;
105 }
106 }
107 return r;
108 };
109
110 function convert(c){
111 if(c.slice){
112 return c;
113 }
114 var r = [];
115 for(var i = 0, l = c.length; i < l; i++){
116 r[r.length] = c[i];
117 }
118 return r;
119 };
120
121 function attrValue(n, attr){
122 if(!n.tagName && typeof n.length != 'undefined'){
123 n = n[0];
124 }
125 if(!n){
126 return null;
127 }
128 if(attr == 'for'){
129 return n.htmlFor;
130 }
131 if(attr == 'class' || attr == 'className'){
132 return n.className;
133 }
134 return n.getAttribute(attr) || n[attr];
135
136 };
137
138 function getNodes(ns, mode, tagName){
139 var result = [], cs;
140 if(!ns){
141 return result;
142 }
143 mode = mode ? mode.replace(trimRe, '$1') : '';
144 tagName = tagName || '*';
145 if(ns.tagName || ns == document){
146 ns = [ns];
147 }
148 if(mode != '/' && mode != '>'){
149 for(var i = 0, ni; ni = ns[i]; i++){
150 cs = ni.getElementsByTagName(tagName);
151 result = concat(result, cs);
152 }
153 }else{
154 for(var i = 0, ni; ni = ns[i]; i++){
155 var cn = ni.getElementsByTagName(tagName);
156 for(var j = 0, cj; cj = cn[j]; j++){
157 if(cj.parentNode == ni){
158 result[result.length] = cj;
159 }
160 }
161 }
162
163 }
164 return result;
165 };
166
167 function concat(a, b){
168 if(b.slice){
169 return a.concat(b);
170 }
171 for(var i = 0, l = b.length; i < l; i++){
172 a[a.length] = b[i];
173 }
174 return a;
175 }
176
177 function byTag(cs, tagName){
178 if(cs.tagName || cs == document){
179 cs = [cs];
180 }
181 if(!tagName){
182 return cs;
183 }
184 var r = []; tagName = tagName.toLowerCase();
185 for(var i = 0, ci; ci = cs[i]; i++){
186 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
187 r[r.length] = ci;
188 }
189 }
190 return r;
191 };
192
193 function byId(cs, attr, id){
194 if(cs.tagName || cs == document){
195 cs = [cs];
196 }
197 if(!id){
198 return cs;
199 }
200 var r = [];
201 for(var i = 0, l = cs.length; i < l; i++){
202 var ci = cs[i];
203 if(ci && ci.id == id){
204 r[r.length] = ci;
205 }
206 }
207 return r;
208 };
209
210 function byAttribute(cs, attr, value, op, custom){
211 var r = [], st = custom=='{';
212 var f = Clipperz.YUI.DomQuery.operators[op];
213 for(var i = 0, l = cs.length; i < l; i++){
214 var a;
215 if(st){
216 a = Clipperz.YUI.DomQuery.getStyle(cs[i], attr);
217 }
218 else if(attr == 'class' || attr == 'className'){
219 a = cs[i].className;
220 }else if(attr == 'for'){
221 a = cs[i].htmlFor;
222 }else{
223 a = cs[i].getAttribute(attr);
224 }
225 if((f && f(a, value)) || (!f && a)){
226 r[r.length] = cs[i];
227 }
228 }
229 return r;
230 };
231
232 function byPseudo(cs, name, value){
233 return Clipperz.YUI.DomQuery.pseudos[name](cs, value);
234 };
235
236 // This is for IE MSXML which does not support expandos.
237 // IE runs the same speed using setAttribute, however FF slows way down
238 // and Safari completely fails so they need to continue to use expandos.
239 // Branched at load time for faster execution.
240 var isIE = window.ActiveXObject;
241 var addAttr = isIE ?
242 function(n, a, v){
243 n.setAttribute(a, v);
244 } :
245 function(n, a, v){
246 n[a] = v;
247 };
248 var getAttr = isIE ?
249 function(n, a){
250 return n.getAttribute(a);
251 } :
252 function(n, a){
253 return n[a];
254 };
255 var clearAttr = isIE ?
256 function(n, a){
257 n.removeAttribute(a);
258 } :
259 function(n, a, v){
260 delete n[a];
261 };
262
263 function nodup(cs){
264 if(!cs.length){
265 return cs;
266 }
267 addAttr(cs[0], '_nodup', true);
268 var r = [cs[0]];
269 for(var i = 1, len = cs.length; i < len; i++){
270 var c = cs[i];
271 if(!getAttr(c, '_nodup')){
272 addAttr(c, '_nodup', true);
273 r[r.length] = c;
274 }
275 }
276 for(var i = 0, len = cs.length; i < len; i++){
277 clearAttr(cs[i], '_nodup');
278 }
279 return r;
280 }
281
282 function quickDiff(c1, c2){
283 if(!c1.length){
284 return c2;
285 }
286 for(var i = 0, len = c1.length; i < len; i++){
287 addAttr(c1[i], '_qdiff', true);
288 }
289 var r = [];
290 for(var i = 0, len = c2.length; i < len; i++){
291 if(!getAttr(c2[i], '_qdiff')){
292 r[r.length] = c2[i];
293 }
294 }
295 for(var i = 0, len = c1.length; i < len; i++){
296 clearAttr(c1[i], '_qdiff');
297 }
298 return r;
299 }
300
301 function quickId(ns, mode, root, id){
302 if(ns == root){
303 var d = root.ownerDocument || root;
304 return d.getElementById(id);
305 }
306 ns = getNodes(ns, mode, '*');
307 return byId(ns, null, id);
308 }
309
310 return {
311 getStyle : function(el, name){
312 return YAHOO.util.Dom.getStyle(el, name);
313 },
314 /**
315 * Compiles a selector/xpath query into a reusable function. The returned function
316 * takes one parameter "root" (optional), which is the context node from where the query should start.
317 * @param {String} selector The selector/xpath query
318 * @param {String} type (optional) Either 'select' (the default) or 'simple' for a simple selector match
319 * @return {Function}
320 */
321 compile : function(path, type){
322 // strip leading slashes
323 while(path.substr(0, 1)=='/'){
324 path = path.substr(1);
325 }
326 type = type || 'select';
327
328 var fn = ['var f = function(root){\n var mode; var n = root || document;\n'];
329 var q = path, mode, lq;
330 var tk = Clipperz.YUI.DomQuery.matchers;
331 var tklen = tk.length;
332 var mm;
333 while(q && lq != q){
334 lq = q;
335 var tm = q.match(/^(#)?([\w-\*]+)/);
336 if(type == 'select'){
337 if(tm){
338 if(tm[1] == '#'){
339 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
340 }else{
341 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
342 }
343 q = q.replace(tm[0], '');
344 }else{
345 fn[fn.length] = 'n = getNodes(n, mode, "*");';
346 }
347 }else{
348 if(tm){
349 if(tm[1] == '#'){
350 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
351 }else{
352 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
353 }
354 q = q.replace(tm[0], '');
355 }
356 }
357 while(!(mm = q.match(modeRe))){
358 var matched = false;
359 for(var j = 0; j < tklen; j++){
360 var t = tk[j];
361 var m = q.match(t.re);
362 if(m){
363 fn[fn.length] = t.select.replace(tplRe, function(x, i){
364 return m[i];
365 });
366 q = q.replace(m[0], '');
367 matched = true;
368 break;
369 }
370 }
371 // prevent infinite loop on bad selector
372 if(!matched){
373 throw 'Error parsing selector, parsing failed at "' + q + '"';
374 }
375 }
376 if(mm[1]){
377 fn[fn.length] = 'mode="'+mm[1]+'";';
378 q = q.replace(mm[1], '');
379 }
380 }
381 fn[fn.length] = 'return nodup(n);\n}';
382 eval(fn.join(''));
383 return f;
384 },
385
386 /**
387 * Selects a group of elements.
388 * @param {String} selector The selector/xpath query
389 * @param {Node} root (optional) The start of the query (defaults to document).
390 * @return {Array}
391 */
392 select : function(path, root, type){
393 if(!root || root == document){
394 root = document;
395 }
396 if(typeof root == 'string'){
397 root = document.getElementById(root);
398 }
399 var paths = path.split(',');
400 var results = [];
401 for(var i = 0, len = paths.length; i < len; i++){
402 var p = paths[i].replace(trimRe, '$1');
403 if(!cache[p]){
404 cache[p] = Clipperz.YUI.DomQuery.compile(p);
405 if(!cache[p]){
406 throw p + ' is not a valid selector';
407 }
408 }
409 var result = cache[p](root);
410 if(result && result != document){
411 results = results.concat(result);
412 }
413 }
414 return results;
415 },
416
417 /**
418 * Selects a single element.
419 * @param {String} selector The selector/xpath query
420 * @param {Node} root (optional) The start of the query (defaults to document).
421 * @return {Element}
422 */
423 selectNode : function(path, root){
424 return Clipperz.YUI.DomQuery.select(path, root)[0];
425 },
426
427 /**
428 * Selects the value of a node, optionally replacing null with the defaultValue.
429 * @param {String} selector The selector/xpath query
430 * @param {Node} root (optional) The start of the query (defaults to document).
431 * @param {String} defaultValue
432 */
433 selectValue : function(path, root, defaultValue){
434 path = path.replace(trimRe, '$1');
435 if(!valueCache[path]){
436 valueCache[path] = Clipperz.YUI.DomQuery.compile(path, 'simple');
437 }
438 var n = valueCache[path](root);
439 n = n[0] ? n[0] : n;
440 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
441 return (v === null ? defaultValue : v);
442 },
443
444 /**
445 * Selects the value of a node, parsing integers and floats.
446 * @param {String} selector The selector/xpath query
447 * @param {Node} root (optional) The start of the query (defaults to document).
448 * @param {Number} defaultValue
449 * @return {Number}
450 */
451 selectNumber : function(path, root, defaultValue){
452 var v = Clipperz.YUI.DomQuery.selectValue(path, root, defaultValue || 0);
453 return parseFloat(v);
454 },
455
456 /**
457 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
458 * @param {String/HTMLElement/Array} el An element id, element or array of elements
459 * @param {String} selector The simple selector to test
460 * @return {Boolean}
461 */
462 is : function(el, ss){
463 if(typeof el == 'string'){
464 el = document.getElementById(el);
465 }
466 var isArray = (el instanceof Array);
467 var result = Clipperz.YUI.DomQuery.filter(isArray ? el : [el], ss);
468 return isArray ? (result.length == el.length) : (result.length > 0);
469 },
470
471 /**
472 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
473 * @param {Array} el An array of elements to filter
474 * @param {String} selector The simple selector to test
475 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
476 * the selector instead of the ones that match
477 * @return {Array}
478 */
479 filter : function(els, ss, nonMatches){
480 ss = ss.replace(trimRe, '$1');
481 if(!simpleCache[ss]){
482 simpleCache[ss] = Clipperz.YUI.DomQuery.compile(ss, 'simple');
483 }
484 var result = simpleCache[ss](els);
485 return nonMatches ? quickDiff(result, els) : result;
486 },
487
488 /**
489 * Collection of matching regular expressions and code snippets.
490 */
491 matchers : [{
492 re: /^\.([\w-]+)/,
493 select: 'n = byClassName(n, null, "{1}");'
494 }, {
495 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
496 select: 'n = byPseudo(n, "{1}", "{2}");'
497 },{
498 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
499 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
500 }, {
501 re: /^#([\w-]+)/,
502 select: 'n = byId(n, null, "{1}");'
503 },{
504 re: /^@([\w-]+)/,
505 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
506 }
507 ],
508
509 /**
510 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *= and %=.
511 * New operators can be added as long as the match the format <i>c</i>= where <i>c<i> is any character other than space, &gt; &lt;.
512 */
513 operators : {
514 '=' : function(a, v){
515 return a == v;
516 },
517 '!=' : function(a, v){
518 return a != v;
519 },
520 '^=' : function(a, v){
521 return a && a.substr(0, v.length) == v;
522 },
523 '$=' : function(a, v){
524 return a && a.substr(a.length-v.length) == v;
525 },
526 '*=' : function(a, v){
527 return a && a.indexOf(v) !== -1;
528 },
529 '%=' : function(a, v){
530 return (a % v) == 0;
531 }
532 },
533
534 /**
535 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
536 * and the argument (if any) supplied in the selector.
537 */
538 pseudos : {
539 'first-child' : function(c){
540 var r = [];
541 for(var i = 0, l = c.length; i < l; i++){
542 var ci = c[i];
543 if(!prev(ci)){
544 r[r.length] = ci;
545 }
546 }
547 return r;
548 },
549
550 'last-child' : function(c){
551 var r = [];
552 for(var i = 0, l = c.length; i < l; i++){
553 var ci = c[i];
554 if(!next(ci)){
555 r[r.length] = ci;
556 }
557 }
558 return r;
559 },
560
561 'nth-child' : function(c, a){
562 var r = [];
563 if(a != 'odd' && a != 'even'){
564 for(var i = 0, ci; ci = c[i]; i++){
565 var m = child(ci.parentNode, a);
566 if(m == ci){
567 r[r.length] = m;
568 }
569 }
570 return r;
571 }
572 var p;
573 // first let's clean up the parent nodes
574 for(var i = 0, l = c.length; i < l; i++){
575 var cp = c[i].parentNode;
576 if(cp != p){
577 clean(cp);
578 p = cp;
579 }
580 }
581 // then lets see if we match
582 for(var i = 0, l = c.length; i < l; i++){
583 var ci = c[i], m = false;
584 if(a == 'odd'){
585 m = ((ci.nodeIndex+1) % 2 == 1);
586 }else if(a == 'even'){
587 m = ((ci.nodeIndex+1) % 2 == 0);
588 }
589 if(m){
590 r[r.length] = ci;
591 }
592 }
593 return r;
594 },
595
596 'only-child' : function(c){
597 var r = [];
598 for(var i = 0, l = c.length; i < l; i++){
599 var ci = c[i];
600 if(!prev(ci) && !next(ci)){
601 r[r.length] = ci;
602 }
603 }
604 return r;
605 },
606
607 'empty' : function(c){
608 var r = [];
609 for(var i = 0, l = c.length; i < l; i++){
610 var ci = c[i];
611 if(!ci.firstChild){
612 r[r.length] = ci;
613 }
614 }
615 return r;
616 },
617
618 'contains' : function(c, v){
619 var r = [];
620 for(var i = 0, l = c.length; i < l; i++){
621 var ci = c[i];
622 if(ci.innerHTML.indexOf(v) !== -1){
623 r[r.length] = ci;
624 }
625 }
626 return r;
627 },
628
629 'checked' : function(c){
630 var r = [];
631 for(var i = 0, l = c.length; i < l; i++){
632 if(c[i].checked == 'checked'){
633 r[r.length] = c[i];
634 }
635 }
636 return r;
637 },
638
639 'not' : function(c, ss){
640 return Clipperz.YUI.DomQuery.filter(c, ss, true);
641 },
642
643 'odd' : function(c){
644 return this['nth-child'](c, 'odd');
645 },
646
647 'even' : function(c){
648 return this['nth-child'](c, 'even');
649 },
650
651 'nth' : function(c, a){
652 return c[a-1];
653 },
654
655 'first' : function(c){
656 return c[0];
657 },
658
659 'last' : function(c){
660 return c[c.length-1];
661 },
662
663 'has' : function(c, ss){
664 var s = Clipperz.YUI.DomQuery.select;
665 var r = [];
666 for(var i = 0, ci; ci = c[i]; i++){
667 if(s(ss, ci).length > 0){
668 r[r.length] = ci;
669 }
670 }
671 return r;
672 },
673
674 'next' : function(c, ss){
675 var is = Clipperz.YUI.DomQuery.is;
676 var r = [];
677 for(var i = 0, ci; ci = c[i]; i++){
678 var n = next(ci);
679 if(n && is(n, ss)){
680 r[r.length] = ci;
681 }
682 }
683 return r;
684 },
685
686 'prev' : function(c, ss){
687 var is = Clipperz.YUI.DomQuery.is;
688 var r = [];
689 for(var i = 0, ci; ci = c[i]; i++){
690 var n = prev(ci);
691 if(n && is(n, ss)){
692 r[r.length] = ci;
693 }
694 }
695 return r;
696 }
697 }
698 };
699}();
700
701/**
702 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Clipperz.YUI.DomQuery#select}
703 * @param {String} path The selector/xpath query
704 * @param {Node} root (optional) The start of the query (defaults to document).
705 * @return {Array}
706 * @member Ext
707 * @method query
708 */
709Clipperz.YUI.query = Clipperz.YUI.DomQuery.select;
diff --git a/frontend/delta/js/Clipperz/YUI/Utils.js b/frontend/delta/js/Clipperz/YUI/Utils.js
new file mode 100644
index 0000000..4def842
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/YUI/Utils.js
@@ -0,0 +1,93 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof YAHOO == 'undefined') { YAHOO = {}; };
25if (typeof YAHOO.util == 'undefined') { YAHOO.util = {}; };
26if (typeof YAHOO.util.Dom == 'undefined') { YAHOO.util.Dom = {}; };
27
28YAHOO.extend = function(subc, superc, overrides) {
29 var F = function() {};
30 F.prototype=superc.prototype;
31 subc.prototype=new F();
32 subc.prototype.constructor=subc;
33 subc.superclass=superc.prototype;
34 if (superc.prototype.constructor == Object.prototype.constructor) {
35 superc.prototype.constructor=superc;
36 }
37
38 if (overrides) {
39 for (var i in overrides) {
40 subc.prototype[i]=overrides[i];
41 }
42 }
43};
44
45YAHOO.override = function(origclass, overrides){
46 if(overrides){
47 var p = origclass.prototype;
48 for(var method in overrides){
49 p[method] = overrides[method];
50 }
51 }
52};
53
54YAHOO.extendX = function(subclass, superclass, overrides){
55 YAHOO.extend(subclass, superclass);
56 subclass.override = function(o){
57 YAHOO.override(subclass, o);
58 };
59 if(!subclass.prototype.override){
60 subclass.prototype.override = function(o){
61 for(var method in o){
62 this[method] = o[method];
63 }
64 };
65 }
66 if(overrides){
67 subclass.override(overrides);
68 };
69
70};
71
72YAHOO.util.Dom.get = function(el) {
73 if (!el) { return null; } // nothing to work with
74
75 if (typeof el != 'string' && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is
76 return el;
77 }
78
79 if (typeof el == 'string') { // ID
80 return document.getElementById(el);
81 }
82 else { // array of ID's and/or elements
83 var collection = [];
84 for (var i = 0, len = el.length; i < len; ++i) {
85 collection[collection.length] = YAHOO.util.Dom.get(el[i]);
86 }
87
88 return collection;
89 }
90
91 return null; // safety, should never happen
92};
93