summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz/PM/Proxy
Unidiff
Diffstat (limited to 'frontend/delta/js/Clipperz/PM/Proxy') (more/less context) (ignore whitespace changes)
-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
6 files changed, 2175 insertions, 0 deletions
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