aotrautils 0.0.53 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- /*utils CLIENT library associated with aotra version : «1.0.0.000 (11/07/2022-23:49:31)»*/
3
+ /*utils CLIENT library associated with aotra version : «1.0.0.000 (12/07/2022-01:26:50)»*/
4
4
  /*-----------------------------------------------------------------------------*/
5
5
  /* ## Utility global methods in a browser (htmljs) client environment.
6
6
  *
@@ -55,433 +55,160 @@ if(typeof monitorProgression === "undefined"){
55
55
 
56
56
 
57
57
 
58
+
59
+
60
+
58
61
  // NOT AOTESTABLE !
59
- //TODO : develop :
60
- //getHashedString=monitorProgression(100000,
61
- window.getHashedString=function(str,/*OPTIONAL*/isHeavyTreatment){
62
-
63
- //CAUTION : YOU MUST *NOT* CHANGE THIS VALUE, UNLESS THE HASH HEAVY TREATMENT VALUE IN YOUR AOTRA SERVER-SIDE CODEIS THE SAME !
64
- const HEAVY_TREATMENT_LOOP_COUNT=100000;
65
-
66
- if(isHeavyTreatment){
67
62
 
68
- // If needed, we make sure the hashing will take a long time, so that
69
- // if the private salt key is leaked, it will be fairly difficult to crack
70
- // password write protection and content encryption :
71
-
72
- let result=str;
73
- for(var i=0;i<HEAVY_TREATMENT_LOOP_COUNT;i++){
74
- result=getHashedString(result,false);
75
- }
63
+ //Works, but doesn't compile under PhoneGap...:
64
+ //function getURLParameter(nameParam){
65
+ //var name=encodeURIComponent(nameParam);
66
+ //return decodeURIComponent(
67
+ //(
68
+ //new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)' )
69
+ //.exec(window.location.search)
70
+ //|| [,""]
71
+ //)[1]
72
+ //.replace(/\+/g, '%20')
73
+ //)||null;
74
+ //}
76
75
 
77
-
78
- return result;
79
-
80
- }else{
81
-
82
-
83
- // SHA-256 hash (sucks less) :
84
- // DEPENDENCY : SJCL JS libray (Stanford Javascript Crypto Library)
85
- if(typeof(sjcl)!="undefined"){
86
- let result=sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(str));
87
-
88
- // TODO : develop :
89
- // hash.progressionMonitor.progress(1);
90
-
91
-
92
- return result;
93
- }
94
-
95
- // if not found : MD5 hash (sucks) :
96
- //TRACE
97
- log("WARN : Could not find SHA hashing, using MD5. This sucks, and this very likely will prevent your aotra client to be able to write data to aotra server.");
98
-
99
- return hex_md5(str);
100
- }
76
+ //...so we replace it with another function that is supposed to do the same
77
+ //thing :
78
+ function getURLParameter(nameParam){
79
+ var name=nameParam;
80
+ if (name=new RegExp("[?&]" + encodeURIComponent(name) + "=([^&]*)").exec(location.search))
81
+ return decodeURIComponent(name[1]);
82
+ return null;
101
83
  }
102
- //);
103
84
 
104
- function encrypt(strToEncrypt,key,/*OPTIONAL*/mode){
105
- if(!mode || typeof(sjcl)=="undefined") mode="xor";
106
- mode=mode.trim();
107
85
 
108
- if(contains(mode,"aes") && contains(mode,"xor")){
109
86
 
110
- // XOR :
111
- var xorStr=btoa(encodeXORNoPattern(strToEncrypt,key));
112
-
113
- var aesStr=
114
- // AES
115
- sjcl.encrypt(key,xorStr);
116
87
 
117
- return aesStr;
118
- }
88
+ // A little method to help i18ning aotra user interface :
89
+ const I18N_REPOSITORY_VARIABLE_NAME="I18N_KEYS";
90
+ function i18n(languagesAndStrings, langParam=null){
119
91
 
120
- // DEPENDENCY : SJCL JS libray (Stanford Javascript Crypto Library)
121
- if(mode==="aes")
122
- return sjcl.encrypt(key,strToEncrypt);
123
- return btoa(encodeXORNoPattern(strToEncrypt,key));
124
-
125
- }
126
-
127
- function decrypt(strToDecrypt,key,/*OPTIONAL*/mode){
128
- if(!mode || typeof(sjcl)=="undefined") mode="xor";
129
- mode=mode.trim();
92
+ // ******************* CONFIG *******************
93
+ const PREFERED_LANGUAGE="fr"; // My Quebecer wife (love on her for ever and beyond) forced me to set this...(I'm French.)
94
+
95
+ const NO_TRANSLATION_LABEL="NO TRANSLATION FOUND";
96
+
97
+ const ADD_SYSTEMATICALLY_TO_REPOSITORY=true;
98
+ const MAX_CHARACTERS_FOR_TRANSLATION_KEY=64; // Really if you have more than 64 characters in commons, then it really should be the same string !
130
99
 
131
- if(contains(mode,"aes") && contains(mode,"xor")){
132
-
133
- // AES
134
- var aesStr=sjcl.decrypt(key,strToDecrypt);
135
-
136
- var xorStr=
137
- // XOR :
138
- encodeXORNoPattern(atob(aesStr),key);
100
+ // ***************** END CONFIG *****************
139
101
 
140
- return xorStr;
141
-
102
+
103
+ if(!languagesAndStrings){
104
+ // TRACE
105
+ console.log("ERROR : No parameter for i18n provided!",languagesAndStrings);
106
+ return NO_TRANSLATION_LABEL;
142
107
  }
143
108
 
144
- // DEPENDENCY : SJCL JS libray (Stanford Javascript Crypto Library)
145
- if(mode==="aes")
146
- return sjcl.decrypt(key,strToDecrypt);
147
- return encodeXORNoPattern(atob(strToDecrypt),key);
109
+ let lang=null;
110
+ if(langParam){
111
+ lang=langParam;
112
+ }else{
113
+ // Parameters priority :
114
+ if(window){
115
+ if(window.getURLParameter){
116
+ lang=nonull(window.getURLParameter("language"), window.getURLParameter("lang"));
117
+ }
118
+ if(!lang && (window.language || window.lang)){
119
+ lang=nonull(window.language, window.lang);
120
+ }
121
+ }else if(global){ // (NodeJS compatibility)
122
+ if(global.getURLParameter){
123
+ lang=nonull(global.getURLParameter("language"), global.getURLParameter("lang"));
124
+ }
125
+ if(!lang && (global.language || global.lang)){
126
+ lang=nonull(global.language, global.lang);
127
+ }
128
+ }
129
+ lang=nonull(lang, PREFERED_LANGUAGE);
130
+ }
148
131
 
132
+ if(contains(["capitalize","append"],lang)){
133
+ // TRACE
134
+ console.log("WARN : Language parameter has for value a reserved attribute keyword, using default language «"+PREFERED_LANGUAGE+"»");
135
+ lang=PREFERED_LANGUAGE;
136
+ }
149
137
 
150
- }
151
-
152
- function encodeXORNoPattern(strToEncode,key){
153
- let result="";
154
- let keyChunk=key;
155
- let keyLength=keyChunk.length;
156
- let previousChars="";
157
- let cnt=0;
158
- for(let i=0;i<strToEncode.length;i++){
159
- let char=strToEncode.charAt(i);
160
- let keyByte=keyChunk.charAt(cnt);
138
+
139
+ let result=null;
140
+
141
+
142
+ if(!isString(languagesAndStrings)){ // Case direct i18n translation, with no translation keys :
161
143
 
162
- result+=String.fromCharCode(char.charCodeAt(0)^keyByte.charCodeAt(0));
144
+ result=languagesAndStrings[lang];
145
+
146
+ if (!result){
147
+ // TRACE
148
+ console.log("ERROR : No label found for language «"+lang+"»!",languagesAndStrings);
149
+ }
150
+
151
+ if (!result){
152
+ for(key in languagesAndStrings){
153
+ if (!languagesAndStrings.hasOwnProperty(key))
154
+ continue;
155
+ // We take the first that we find, in the other languages:
156
+ result=languagesAndStrings[key];
157
+ break;
158
+ }
159
+ }
160
+
161
+ if (!result) return NO_TRANSLATION_LABEL;
163
162
 
164
- if(cnt%keyLength===(keyLength-1)){
165
- cnt=0;
166
- // NO : TOO LONG TREATMENT !: We hash with all the previous blocks too :
167
- // We hash with a character of the previous chunk (they add up at each new chunk):
168
- keyChunk=getHashedString(previousChars+keyChunk);
169
163
 
170
- previousChars+=keyChunk.charAt(keyChunk.length-1);
171
- }else{
172
- cnt++;
164
+ // We add this «rogue» usage of i18n to the whole repository at all useful ends :
165
+ if(ADD_SYSTEMATICALLY_TO_REPOSITORY){
166
+ // let declarable={};
167
+ let maxLength=Math.min(result.length, MAX_CHARACTERS_FOR_TRANSLATION_KEY);
168
+ let key=toConvention("camel", result.substring(0,maxLength).toLowerCase() );
169
+ // let calculatedKey=radicalKey+"_"+getUUID("short");
170
+ // declarable[calculatedKey]=languagesAndStrings;
171
+ i18n.declareSingleEntry(key, languagesAndStrings);
173
172
  }
173
+
174
+ // Eventual post-treatments :
175
+ if(languagesAndStrings.capitalize) result=capitalize(result);
176
+ if(languagesAndStrings.append) result+=languagesAndStrings.append;
177
+
178
+ return result;
174
179
  }
175
- return result;
176
- }
180
+ // else // Case we use translation keys : (here, languagesAndStrings parameter holds just the wished translation key)
177
181
 
178
- function generateRandomString(length,/*NULLABLE*/mode){
179
182
 
180
- // This list must be very conservative, because we want to be able to pass it through GET URLs !
181
- // OLD (not enough conservative ?) : const ALLOWED_CHARS="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0912346789_-£¢¤¬²³¼½¾";
182
- const ALLOWED_CHARS="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0912346789!-:;";
183
+ let repository=(window?window:global)[I18N_REPOSITORY_VARIABLE_NAME];
184
+ if(!repository){
185
+ // TRACE
186
+ console.log("ERROR : No repository variable found for repository «"+I18N_REPOSITORY_VARIABLE_NAME+"»!");
187
+ return NO_TRANSLATION_LABEL;
188
+ }
183
189
 
190
+ // OLD (ie. splitted format :)
191
+ // let repositoryForLang=repository[lang];
192
+ // if (!repositoryForLang){
193
+ // // TRACE
194
+ // console.log("ERROR : No translation found for language «"+lang+"»!",languagesAndStrings);
195
+ // return NO_TRANSLATION_LABEL;
196
+ // }
197
+ // result=repositoryForLang[languagesAndStrings]; // Here, languagesAndStrings is just a bundle key.
198
+ // if (!result) return NO_TRANSLATION_LABEL+" (for key «"+languagesAndStrings+"»)";
184
199
 
185
- if(typeof(length)==="string"){
186
- if(contains(length,"->")){
187
- length=Math.getRandomInRange(length);
188
- }else{
189
- length=64;
190
- }
200
+ let languagesAndStringsForTranslationKey=repository[languagesAndStrings];
201
+ if (!languagesAndStringsForTranslationKey){
202
+ // SILENT ERROR :
203
+ // // TRACE
204
+ // console.log("ERROR : No translation found for key «"+languagesAndStrings+"» for language «"+lang+"»!");
205
+ // NO, OLD : return NO_TRANSLATION_LABEL;
206
+ return languagesAndStrings;
191
207
  }
208
+ result=i18n(languagesAndStringsForTranslationKey, lang); // Since we use the same format !
192
209
 
193
- var result="";
194
-
195
- if(mode==="simple"){
196
-
197
- for(var i=0;i<length;i++){
198
- var value=Math.getRandomInArray(ALLOWED_CHARS);
199
- result+=value;
200
- }
201
-
202
- return result;
203
- }else if(mode==="human"){
204
-
205
- const markovGraph={
206
- // For simplicity sakes, we ignore the consonants and vowels doubling possibilities:
207
- consonants:{// They always accept vowels at their following
208
- // Indicate ^ to specify wich of the other group letter to exclude as direct follower of the given letter :
209
- "b":["r","l"],
210
- "c":["h","t","k","l","r"],
211
- "d":["r"],
212
- "f":["r","l"],
213
- "g":["r","l"],
214
- "h":[],
215
- "j":["r"],
216
- "k":["r","l","t","h"],
217
- "l":["t"],
218
- "m":["b","p"],
219
- "n":["t","d"],
220
- "p":["h","r","s","t","l"],
221
- "q":["r","l"],
222
- "r":["t","c","d","k","q","h"],
223
- "s":["t","c","d","k","q","h"],
224
- "t":["r","h"],
225
- "v":["r","l"],
226
- "w":["r"],
227
- "x":["p"],
228
- "z":["r","h"],
229
- },
230
- vowels:{// They always accept consonants at their following
231
- "a":["i","u","y"],
232
- "e":["i","u","y"],
233
- "i":["e","o"],
234
- "o":["i","u"],
235
- "u":["i"],
236
- "y":[],
237
- },
238
- };
239
-
240
- const LETTERS_TYPES=Object.keys(markovGraph);
241
-
242
- const CURR_LETTER_MODE=Math.getRandomInArray(LETTERS_TYPES);
243
- const POSSIBLE_LETTERS=Object.keys(markovGraph[CURR_LETTER_MODE]);
244
- const CURR_LETTER=Math.getRandomInArray(POSSIBLE_LETTERS);
245
-
246
- var automataState={
247
- currentLetterMode:CURR_LETTER_MODE,
248
- possibleLetters:POSSIBLE_LETTERS,
249
- currentLetter:CURR_LETTER,
250
-
251
- calculateLetter:function(){
252
-
253
- this.currentLetter=Math.getRandomInArray(this.possibleLetters);
254
-
255
- var sameLetters=Object.keys( markovGraph[this.currentLetterMode] );
256
- if(!contains(sameLetters,this.currentLetter)){
257
- // If we picked from the same group : we don't change of group to pick
258
- // If we picked from the other group : we do change of group to pick
259
-
260
- var otherLetterMode=foreach(LETTERS_TYPES,(item)=>{
261
- if(item!==this.currentLetterMode) return item;
262
- });
263
-
264
- this.currentLetterMode=otherLetterMode;
265
- }
266
-
267
- },
268
-
269
- updatePossibleLettersForLetter:function(){
270
-
271
- var nextPossibleLetters=[];
272
- var nextNotPossibleLetters=[];
273
-
274
- // We store those of the other group marked «^»
275
- foreach(markovGraph[this.currentLetterMode][this.currentLetter],(letter)=>{
276
- if(letter.charAt(0)==="^"){
277
- nextNotPossibleLetters.push(letter.charAt(1));
278
- }else{
279
- nextPossibleLetters.push(letter);
280
- }
281
- });
282
-
283
- var otherLetterMode=foreach(LETTERS_TYPES,(item)=>{
284
- if(item!==this.currentLetterMode) return item;
285
- });
286
- var otherLetters=Object.keys(markovGraph[otherLetterMode]);
287
-
288
- // We exclude those marked «^»
289
- foreach( otherLetters ,(letter)=>{
290
- if(!contains(nextNotPossibleLetters,letter)){
291
- nextPossibleLetters.push(letter);
292
- }
293
- });
294
-
295
- this.possibleLetters=nextPossibleLetters;
296
- }
297
- };
298
-
299
- var i=0;
300
- do{
301
-
302
- result+=automataState.currentLetter;
303
-
304
- automataState.updatePossibleLettersForLetter();
305
- automataState.calculateLetter();
306
-
307
- i++;
308
- }while(i<length);
309
-
310
- return result;
311
- }
312
-
313
- for(var i=0;i<length;i++){
314
- var value=Math.getRandomInt(255,0);
315
- result+=String.fromCharCode(value);
316
- }
317
-
318
- if(mode==="base64"){
319
- return btoa(result);
320
- }
321
-
322
- return result;
323
- }
324
-
325
-
326
-
327
- // NOT AOTESTABLE !
328
- function getUniqueIdWithDate(){
329
- return getHashedString(getNow() + "");
330
- }
331
-
332
-
333
-
334
- // NOT AOTESTABLE !
335
-
336
- //Works, but doesn't compile under PhoneGap...:
337
- //function getURLParameter(nameParam){
338
- //var name=encodeURIComponent(nameParam);
339
- //return decodeURIComponent(
340
- //(
341
- //new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)' )
342
- //.exec(window.location.search)
343
- //|| [,""]
344
- //)[1]
345
- //.replace(/\+/g, '%20')
346
- //)||null;
347
- //}
348
-
349
- //...so we replace it with another function that is supposed to do the same
350
- //thing :
351
- function getURLParameter(nameParam){
352
- var name=nameParam;
353
- if (name=new RegExp("[?&]" + encodeURIComponent(name) + "=([^&]*)").exec(location.search))
354
- return decodeURIComponent(name[1]);
355
- return null;
356
- }
357
-
358
-
359
-
360
-
361
- // A little method to help i18ning aotra user interface :
362
- const I18N_REPOSITORY_VARIABLE_NAME="I18N_KEYS";
363
- function i18n(languagesAndStrings, langParam=null){
364
-
365
- // ******************* CONFIG *******************
366
- const PREFERED_LANGUAGE="fr"; // My Quebecer wife (love on her for ever and beyond) forced me to set this...(I'm French.)
367
-
368
- const NO_TRANSLATION_LABEL="NO TRANSLATION FOUND";
369
-
370
- const ADD_SYSTEMATICALLY_TO_REPOSITORY=true;
371
- const MAX_CHARACTERS_FOR_TRANSLATION_KEY=64; // Really if you have more than 64 characters in commons, then it really should be the same string !
372
-
373
- // ***************** END CONFIG *****************
374
-
375
-
376
- if(!languagesAndStrings){
377
- // TRACE
378
- console.log("ERROR : No parameter for i18n provided!",languagesAndStrings);
379
- return NO_TRANSLATION_LABEL;
380
- }
381
-
382
- let lang=null;
383
- if(langParam){
384
- lang=langParam;
385
- }else{
386
- // Parameters priority :
387
- if(window){
388
- if(window.getURLParameter){
389
- lang=nonull(window.getURLParameter("language"), window.getURLParameter("lang"));
390
- }
391
- if(!lang && (window.language || window.lang)){
392
- lang=nonull(window.language, window.lang);
393
- }
394
- }else if(global){ // (NodeJS compatibility)
395
- if(global.getURLParameter){
396
- lang=nonull(global.getURLParameter("language"), global.getURLParameter("lang"));
397
- }
398
- if(!lang && (global.language || global.lang)){
399
- lang=nonull(global.language, global.lang);
400
- }
401
- }
402
- lang=nonull(lang, PREFERED_LANGUAGE);
403
- }
404
-
405
- if(contains(["capitalize","append"],lang)){
406
- // TRACE
407
- console.log("WARN : Language parameter has for value a reserved attribute keyword, using default language «"+PREFERED_LANGUAGE+"»");
408
- lang=PREFERED_LANGUAGE;
409
- }
410
-
411
-
412
- let result=null;
413
-
414
-
415
- if(!isString(languagesAndStrings)){ // Case direct i18n translation, with no translation keys :
416
-
417
- result=languagesAndStrings[lang];
418
-
419
- if (!result){
420
- // TRACE
421
- console.log("ERROR : No label found for language «"+lang+"»!",languagesAndStrings);
422
- }
423
-
424
- if (!result){
425
- for(key in languagesAndStrings){
426
- if (!languagesAndStrings.hasOwnProperty(key))
427
- continue;
428
- // We take the first that we find, in the other languages:
429
- result=languagesAndStrings[key];
430
- break;
431
- }
432
- }
433
-
434
- if (!result) return NO_TRANSLATION_LABEL;
435
-
436
-
437
- // We add this «rogue» usage of i18n to the whole repository at all useful ends :
438
- if(ADD_SYSTEMATICALLY_TO_REPOSITORY){
439
- // let declarable={};
440
- let maxLength=Math.min(result.length, MAX_CHARACTERS_FOR_TRANSLATION_KEY);
441
- let key=toConvention("camel", result.substring(0,maxLength).toLowerCase() );
442
- // let calculatedKey=radicalKey+"_"+getUUID("short");
443
- // declarable[calculatedKey]=languagesAndStrings;
444
- i18n.declareSingleEntry(key, languagesAndStrings);
445
- }
446
-
447
- // Eventual post-treatments :
448
- if(languagesAndStrings.capitalize) result=capitalize(result);
449
- if(languagesAndStrings.append) result+=languagesAndStrings.append;
450
-
451
- return result;
452
- }
453
- // else // Case we use translation keys : (here, languagesAndStrings parameter holds just the wished translation key)
454
-
455
-
456
- let repository=(window?window:global)[I18N_REPOSITORY_VARIABLE_NAME];
457
- if(!repository){
458
- // TRACE
459
- console.log("ERROR : No repository variable found for repository «"+I18N_REPOSITORY_VARIABLE_NAME+"»!");
460
- return NO_TRANSLATION_LABEL;
461
- }
462
-
463
- // OLD (ie. splitted format :)
464
- // let repositoryForLang=repository[lang];
465
- // if (!repositoryForLang){
466
- // // TRACE
467
- // console.log("ERROR : No translation found for language «"+lang+"»!",languagesAndStrings);
468
- // return NO_TRANSLATION_LABEL;
469
- // }
470
- // result=repositoryForLang[languagesAndStrings]; // Here, languagesAndStrings is just a bundle key.
471
- // if (!result) return NO_TRANSLATION_LABEL+" (for key «"+languagesAndStrings+"»)";
472
-
473
- let languagesAndStringsForTranslationKey=repository[languagesAndStrings];
474
- if (!languagesAndStringsForTranslationKey){
475
- // SILENT ERROR :
476
- // // TRACE
477
- // console.log("ERROR : No translation found for key «"+languagesAndStrings+"» for language «"+lang+"»!");
478
- // NO, OLD : return NO_TRANSLATION_LABEL;
479
- return languagesAndStrings;
480
- }
481
- result=i18n(languagesAndStringsForTranslationKey, lang); // Since we use the same format !
482
-
483
- return result;
484
- };
210
+ return result;
211
+ };
485
212
 
486
213
 
487
214
  i18n.declareSingleEntry=function(key, languagesAndStringsEntry){
@@ -7121,7 +6848,7 @@ createFusrodaClient=function(doOnClientReady, doOnDataReception, urlParam=null,
7121
6848
 
7122
6849
 
7123
6850
 
7124
- /*utils GEOMETRY library associated with aotra version : «1.0.0.000 (11/07/2022-23:49:31)»*/
6851
+ /*utils GEOMETRY library associated with aotra version : «1.0.0.000 (12/07/2022-01:26:50)»*/
7125
6852
  /*-----------------------------------------------------------------------------*/
7126
6853
 
7127
6854
 
@@ -8327,7 +8054,7 @@ function rayVsUnitSphereClosestPoint(p, r) {
8327
8054
  // MUST REMAIN AT THE END OF THIS LIBRARY FILE !
8328
8055
 
8329
8056
  AOTRAUTILS_GEOMETRY_LIB_IS_LOADED=true;
8330
- /*utils COMMONS library associated with aotra version : «1.0.0.000 (11/07/2022-23:49:31)»*/
8057
+ /*utils COMMONS library associated with aotra version : «1.0.0.000 (12/07/2022-01:26:50)»*/
8331
8058
  /*-----------------------------------------------------------------------------*/
8332
8059
 
8333
8060
 
@@ -9668,105 +9395,398 @@ aotest.run=function(testName=null,scenarioName=null){
9668
9395
 
9669
9396
  var buildHRReport=function(resultObj){
9670
9397
 
9671
- let str="";
9672
-
9673
- let resultsFailed=getCumulatedInt(resultObj,"childrenFailed");
9674
- let resultsRunned=getCumulatedInt(resultObj,"childrenRunned");
9675
-
9398
+ let str="";
9399
+
9400
+ let resultsFailed=getCumulatedInt(resultObj,"childrenFailed");
9401
+ let resultsRunned=getCumulatedInt(resultObj,"childrenRunned");
9402
+
9403
+
9404
+ // TRACE
9405
+ str+="@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n";
9406
+ str+=" AOTEST REPORT \n";
9407
+ str+="REPORT: "+resultsFailed + "/" + resultsRunned + " scenarii failed.\n";
9408
+ str+="REPORT: "+(resultsRunned - resultsFailed) + "/" + resultsRunned + " scenarii succeeded.\n";
9409
+ str+="REPORT: "+resultsRunned + " scenarii runned.\n";
9410
+ str+="@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n";
9411
+
9412
+ if(0<resultsRunned){
9413
+ if(!resultObj.global.isFailed){
9414
+ // TRACE
9415
+ str+="LOG: RESULT :>>>>>> All tests SUCCEEDED ! :D\n";
9416
+ } else {
9417
+ // TRACE
9418
+ str+="LOG: RESULT :>>>>>> Some tests FAILED... :(\n";
9419
+ }
9420
+ } else {
9421
+ // TRACE
9422
+ str+="LOG: RESULT :>>>>>> No tests runned... :|\n";
9423
+ }
9424
+
9425
+ return str;
9426
+ };
9427
+
9428
+
9429
+ var getCumulatedInt=function(resultObj, attrName){
9430
+
9431
+ let result=0;
9432
+
9433
+ result+=resultObj.global[attrName];
9434
+
9435
+ foreach(resultObj.children,(child)=>{
9436
+ result+=getCumulatedInt(child, attrName);
9437
+ });
9438
+
9439
+ return result;
9440
+ };
9441
+
9442
+
9443
+
9444
+
9445
+ // TRACE
9446
+ console.log( buildHRReport(allTestsResultObj));
9447
+
9448
+
9449
+ // DBG
9450
+ console.log("TOTAL RESULT :",allTestsResultObj);
9451
+
9452
+
9453
+ aotest.isRunning=false;
9454
+
9455
+ return allTestsResultObj;
9456
+ };
9457
+
9458
+
9459
+
9460
+ aotest.profile=function(rootObject,methodName,visited=[]){
9461
+
9462
+
9463
+ //if(!rootObject || !isObject(rootObject) || contains(visited,rootObject)) return;
9464
+ if( !rootObject || isPrimitive(rootObject) || isFunction(rootObject)
9465
+ || contains(visited,rootObject)) return;
9466
+
9467
+ const THRESHOLD_MILLIS=10;
9468
+
9469
+ visited.push(rootObject);
9470
+
9471
+ let method=rootObject[methodName];
9472
+ if(method && isFunction(method)){
9473
+ rootObject[methodName]=function(){
9474
+
9475
+ let time=getNow();
9476
+
9477
+ method.apply(rootObject, arguments);
9478
+
9479
+ let deltaMillis=(getNow()-time);
9480
+
9481
+ // TRACE
9482
+ if(THRESHOLD_MILLIS<=deltaMillis) lognow("Duration ["+deltaMillis+"ms] of «"+methodName+"» on object:"+getClassName(rootObject),rootObject);
9483
+ };
9484
+ }
9485
+
9486
+ foreach(rootObject,(attr,attrName)=>{
9487
+
9488
+ // DBG
9489
+ if(attrName==="currentContainer") lognow("currentContainer:",attr);
9490
+
9491
+ aotest.profile(attr,methodName,visited);
9492
+
9493
+ });
9494
+
9495
+
9496
+ };
9497
+
9498
+
9499
+
9500
+
9501
+
9502
+ //================================================================
9503
+ //================= Cryptography utility methods =================
9504
+ //================================================================
9505
+
9506
+
9507
+ // NOT AOTESTABLE !
9508
+ //TODO : develop :
9509
+ //getHashedString=monitorProgression(100000,
9510
+ window.getHashedString=function(str,/*OPTIONAL*/isHeavyTreatment){
9511
+
9512
+ //CAUTION : YOU MUST *NOT* CHANGE THIS VALUE, UNLESS THE HASH HEAVY TREATMENT VALUE IN YOUR AOTRA SERVER-SIDE CODEIS THE SAME !
9513
+ const HEAVY_TREATMENT_LOOP_COUNT=100000;
9514
+
9515
+ if(isHeavyTreatment){
9516
+
9517
+ // If needed, we make sure the hashing will take a long time, so that
9518
+ // if the private salt key is leaked, it will be fairly difficult to crack
9519
+ // password write protection and content encryption :
9520
+
9521
+ let result=str;
9522
+ for(var i=0;i<HEAVY_TREATMENT_LOOP_COUNT;i++){
9523
+ result=getHashedString(result,false);
9524
+ }
9525
+
9526
+
9527
+ return result;
9528
+
9529
+ }else{
9530
+
9531
+
9532
+ // SHA-256 hash (sucks less) :
9533
+ // DEPENDENCY : SJCL JS libray (Stanford Javascript Crypto Library)
9534
+ if(typeof(sjcl)!="undefined"){
9535
+ let result=sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(str));
9536
+
9537
+ // TODO : develop :
9538
+ // hash.progressionMonitor.progress(1);
9539
+
9540
+
9541
+ return result;
9542
+ }
9543
+
9544
+ // if not found : MD5 hash (sucks) :
9545
+ //TRACE
9546
+ log("WARN : Could not find SHA hashing, using MD5. This sucks, and this very likely will prevent your aotra client to be able to write data to aotra server.");
9547
+
9548
+ return hex_md5(str);
9549
+ }
9550
+ }
9551
+ //);
9552
+
9553
+ function encrypt(strToEncrypt,key,/*OPTIONAL*/mode){
9554
+ if(!mode || typeof(sjcl)=="undefined") mode="xor";
9555
+ mode=mode.trim();
9556
+
9557
+ if(contains(mode,"aes") && contains(mode,"xor")){
9558
+
9559
+ // XOR :
9560
+ var xorStr=btoa(encodeXORNoPattern(strToEncrypt,key));
9561
+
9562
+ var aesStr=
9563
+ // AES
9564
+ sjcl.encrypt(key,xorStr);
9565
+
9566
+ return aesStr;
9567
+ }
9568
+
9569
+ // DEPENDENCY : SJCL JS libray (Stanford Javascript Crypto Library)
9570
+ if(mode==="aes")
9571
+ return sjcl.encrypt(key,strToEncrypt);
9572
+ return btoa(encodeXORNoPattern(strToEncrypt,key));
9573
+
9574
+ }
9575
+
9576
+ function decrypt(strToDecrypt,key,/*OPTIONAL*/mode){
9577
+ if(!mode || typeof(sjcl)=="undefined") mode="xor";
9578
+ mode=mode.trim();
9579
+
9580
+ if(contains(mode,"aes") && contains(mode,"xor")){
9676
9581
 
9677
- // TRACE
9678
- str+="@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n";
9679
- str+=" AOTEST REPORT \n";
9680
- str+="REPORT: "+resultsFailed + "/" + resultsRunned + " scenarii failed.\n";
9681
- str+="REPORT: "+(resultsRunned - resultsFailed) + "/" + resultsRunned + " scenarii succeeded.\n";
9682
- str+="REPORT: "+resultsRunned + " scenarii runned.\n";
9683
- str+="@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n";
9582
+ // AES
9583
+ var aesStr=sjcl.decrypt(key,strToDecrypt);
9684
9584
 
9685
- if(0<resultsRunned){
9686
- if(!resultObj.global.isFailed){
9687
- // TRACE
9688
- str+="LOG: RESULT :>>>>>> All tests SUCCEEDED ! :D\n";
9689
- } else {
9690
- // TRACE
9691
- str+="LOG: RESULT :>>>>>> Some tests FAILED... :(\n";
9692
- }
9693
- } else {
9694
- // TRACE
9695
- str+="LOG: RESULT :>>>>>> No tests runned... :|\n";
9696
- }
9585
+ var xorStr=
9586
+ // XOR :
9587
+ encodeXORNoPattern(atob(aesStr),key);
9588
+
9589
+ return xorStr;
9697
9590
 
9698
- return str;
9699
- };
9591
+ }
9700
9592
 
9593
+ // DEPENDENCY : SJCL JS libray (Stanford Javascript Crypto Library)
9594
+ if(mode==="aes")
9595
+ return sjcl.decrypt(key,strToDecrypt);
9596
+ return encodeXORNoPattern(atob(strToDecrypt),key);
9597
+
9598
+
9599
+ }
9701
9600
 
9702
- var getCumulatedInt=function(resultObj, attrName){
9703
-
9704
- let result=0;
9601
+ function encodeXORNoPattern(strToEncode,key){
9602
+ let result="";
9603
+ let keyChunk=key;
9604
+ let keyLength=keyChunk.length;
9605
+ let previousChars="";
9606
+ let cnt=0;
9607
+ for(let i=0;i<strToEncode.length;i++){
9608
+ let char=strToEncode.charAt(i);
9609
+ let keyByte=keyChunk.charAt(cnt);
9705
9610
 
9706
- result+=resultObj.global[attrName];
9611
+ result+=String.fromCharCode(char.charCodeAt(0)^keyByte.charCodeAt(0));
9707
9612
 
9708
- foreach(resultObj.children,(child)=>{
9709
- result+=getCumulatedInt(child, attrName);
9710
- });
9613
+ if(cnt%keyLength===(keyLength-1)){
9614
+ cnt=0;
9615
+ // NO : TOO LONG TREATMENT !: We hash with all the previous blocks too :
9616
+ // We hash with a character of the previous chunk (they add up at each new chunk):
9617
+ keyChunk=getHashedString(previousChars+keyChunk);
9711
9618
 
9712
- return result;
9713
- };
9619
+ previousChars+=keyChunk.charAt(keyChunk.length-1);
9620
+ }else{
9621
+ cnt++;
9622
+ }
9623
+ }
9624
+ return result;
9625
+ }
9714
9626
 
9627
+ function generateRandomString(length,/*NULLABLE*/mode){
9715
9628
 
9629
+ // This list must be very conservative, because we want to be able to pass it through GET URLs !
9630
+ // OLD (not enough conservative ?) : const ALLOWED_CHARS="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0912346789_-£¢¤¬²³¼½¾";
9631
+ const ALLOWED_CHARS="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0912346789!-:;";
9716
9632
 
9717
9633
 
9718
- // TRACE
9719
- console.log( buildHRReport(allTestsResultObj));
9720
-
9634
+ if(typeof(length)==="string"){
9635
+ if(contains(length,"->")){
9636
+ length=Math.getRandomInRange(length);
9637
+ }else{
9638
+ length=64;
9639
+ }
9640
+ }
9721
9641
 
9722
- // DBG
9723
- console.log("TOTAL RESULT :",allTestsResultObj);
9642
+ var result="";
9724
9643
 
9725
-
9726
- aotest.isRunning=false;
9727
-
9728
- return allTestsResultObj;
9729
- };
9644
+ if(mode==="simple"){
9645
+
9646
+ for(var i=0;i<length;i++){
9647
+ var value=Math.getRandomInArray(ALLOWED_CHARS);
9648
+ result+=value;
9649
+ }
9650
+
9651
+ return result;
9652
+ }else if(mode==="human"){
9653
+
9654
+ const markovGraph={
9655
+ // For simplicity sakes, we ignore the consonants and vowels doubling possibilities:
9656
+ consonants:{// They always accept vowels at their following
9657
+ // Indicate ^ to specify wich of the other group letter to exclude as direct follower of the given letter :
9658
+ "b":["r","l"],
9659
+ "c":["h","t","k","l","r"],
9660
+ "d":["r"],
9661
+ "f":["r","l"],
9662
+ "g":["r","l"],
9663
+ "h":[],
9664
+ "j":["r"],
9665
+ "k":["r","l","t","h"],
9666
+ "l":["t"],
9667
+ "m":["b","p"],
9668
+ "n":["t","d"],
9669
+ "p":["h","r","s","t","l"],
9670
+ "q":["r","l"],
9671
+ "r":["t","c","d","k","q","h"],
9672
+ "s":["t","c","d","k","q","h"],
9673
+ "t":["r","h"],
9674
+ "v":["r","l"],
9675
+ "w":["r"],
9676
+ "x":["p"],
9677
+ "z":["r","h"],
9678
+ },
9679
+ vowels:{// They always accept consonants at their following
9680
+ "a":["i","u","y"],
9681
+ "e":["i","u","y"],
9682
+ "i":["e","o"],
9683
+ "o":["i","u"],
9684
+ "u":["i"],
9685
+ "y":[],
9686
+ },
9687
+ };
9688
+
9689
+ const LETTERS_TYPES=Object.keys(markovGraph);
9730
9690
 
9691
+ const CURR_LETTER_MODE=Math.getRandomInArray(LETTERS_TYPES);
9692
+ const POSSIBLE_LETTERS=Object.keys(markovGraph[CURR_LETTER_MODE]);
9693
+ const CURR_LETTER=Math.getRandomInArray(POSSIBLE_LETTERS);
9694
+
9695
+ var automataState={
9696
+ currentLetterMode:CURR_LETTER_MODE,
9697
+ possibleLetters:POSSIBLE_LETTERS,
9698
+ currentLetter:CURR_LETTER,
9699
+
9700
+ calculateLetter:function(){
9701
+
9702
+ this.currentLetter=Math.getRandomInArray(this.possibleLetters);
9703
+
9704
+ var sameLetters=Object.keys( markovGraph[this.currentLetterMode] );
9705
+ if(!contains(sameLetters,this.currentLetter)){
9706
+ // If we picked from the same group : we don't change of group to pick
9707
+ // If we picked from the other group : we do change of group to pick
9708
+
9709
+ var otherLetterMode=foreach(LETTERS_TYPES,(item)=>{
9710
+ if(item!==this.currentLetterMode) return item;
9711
+ });
9712
+
9713
+ this.currentLetterMode=otherLetterMode;
9714
+ }
9731
9715
 
9716
+ },
9717
+
9718
+ updatePossibleLettersForLetter:function(){
9719
+
9720
+ var nextPossibleLetters=[];
9721
+ var nextNotPossibleLetters=[];
9732
9722
 
9733
- aotest.profile=function(rootObject,methodName,visited=[]){
9734
-
9735
-
9736
- //if(!rootObject || !isObject(rootObject) || contains(visited,rootObject)) return;
9737
- if( !rootObject || isPrimitive(rootObject) || isFunction(rootObject)
9738
- || contains(visited,rootObject)) return;
9723
+ // We store those of the other group marked «^»
9724
+ foreach(markovGraph[this.currentLetterMode][this.currentLetter],(letter)=>{
9725
+ if(letter.charAt(0)==="^"){
9726
+ nextNotPossibleLetters.push(letter.charAt(1));
9727
+ }else{
9728
+ nextPossibleLetters.push(letter);
9729
+ }
9730
+ });
9731
+
9732
+ var otherLetterMode=foreach(LETTERS_TYPES,(item)=>{
9733
+ if(item!==this.currentLetterMode) return item;
9734
+ });
9735
+ var otherLetters=Object.keys(markovGraph[otherLetterMode]);
9736
+
9737
+ // We exclude those marked «^»
9738
+ foreach( otherLetters ,(letter)=>{
9739
+ if(!contains(nextNotPossibleLetters,letter)){
9740
+ nextPossibleLetters.push(letter);
9741
+ }
9742
+ });
9739
9743
 
9740
- const THRESHOLD_MILLIS=10;
9744
+ this.possibleLetters=nextPossibleLetters;
9745
+ }
9746
+ };
9747
+
9748
+ var i=0;
9749
+ do{
9741
9750
 
9742
- visited.push(rootObject);
9743
-
9744
- let method=rootObject[methodName];
9745
- if(method && isFunction(method)){
9746
- rootObject[methodName]=function(){
9747
-
9748
- let time=getNow();
9749
-
9750
- method.apply(rootObject, arguments);
9751
+ result+=automataState.currentLetter;
9751
9752
 
9752
- let deltaMillis=(getNow()-time);
9753
+ automataState.updatePossibleLettersForLetter();
9754
+ automataState.calculateLetter();
9753
9755
 
9754
- // TRACE
9755
- if(THRESHOLD_MILLIS<=deltaMillis) lognow("Duration ["+deltaMillis+"ms] of «"+methodName+"» on object:"+getClassName(rootObject),rootObject);
9756
- };
9756
+ i++;
9757
+ }while(i<length);
9758
+
9759
+ return result;
9757
9760
  }
9758
9761
 
9759
- foreach(rootObject,(attr,attrName)=>{
9760
-
9761
- // DBG
9762
- if(attrName==="currentContainer") lognow("currentContainer:",attr);
9763
-
9764
- aotest.profile(attr,methodName,visited);
9765
-
9766
- });
9762
+ for(var i=0;i<length;i++){
9763
+ var value=Math.getRandomInt(255,0);
9764
+ result+=String.fromCharCode(value);
9765
+ }
9767
9766
 
9767
+ if(mode==="base64"){
9768
+ return btoa(result);
9769
+ }
9768
9770
 
9769
- };
9771
+ return result;
9772
+ }
9773
+
9774
+
9775
+
9776
+ // NOT AOTESTABLE !
9777
+ function getUniqueIdWithDate(){
9778
+ return getHashedString(getNow() + "");
9779
+ }
9780
+
9781
+
9782
+
9783
+
9784
+
9785
+
9786
+ //================================================================
9787
+ //================= Miscelanneous utility methods =================
9788
+ //================================================================
9789
+
9770
9790
 
9771
9791
 
9772
9792
 
aotrautils/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aotrautils",
3
- "version": "0.0.53",
3
+ "version": "0.0.54",
4
4
  "main": "aotrautils.build.js",
5
5
  "description": "A library for vanilla javascript utils (client-side) used in aotra javascript CMS",
6
6
  "author": "Jeremie Ratomposon <info@alqemia.com> (https://alqemia.com)",