js-confuser 1.5.8 → 1.6.0

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.
Files changed (139) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +69 -0
  3. package/README.md +143 -7
  4. package/dist/index.js +33 -4
  5. package/dist/obfuscator.js +30 -31
  6. package/dist/options.js +4 -5
  7. package/dist/order.js +4 -6
  8. package/dist/probability.js +2 -4
  9. package/dist/templates/bufferToString.js +13 -0
  10. package/dist/templates/crash.js +2 -2
  11. package/dist/templates/es5.js +18 -0
  12. package/dist/transforms/antiTooling.js +1 -1
  13. package/dist/transforms/calculator.js +77 -21
  14. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  15. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
  16. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  17. package/dist/transforms/deadCode.js +33 -25
  18. package/dist/transforms/dispatcher.js +7 -6
  19. package/dist/transforms/es5/antiClass.js +6 -2
  20. package/dist/transforms/es5/antiDestructuring.js +3 -1
  21. package/dist/transforms/es5/es5.js +31 -34
  22. package/dist/transforms/eval.js +11 -0
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
  24. package/dist/transforms/extraction/objectExtraction.js +6 -1
  25. package/dist/transforms/finalizer.js +82 -0
  26. package/dist/transforms/flatten.js +82 -55
  27. package/dist/transforms/hexadecimalNumbers.js +34 -9
  28. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  29. package/dist/transforms/identifier/globalConcealing.js +10 -83
  30. package/dist/transforms/identifier/movedDeclarations.js +2 -8
  31. package/dist/transforms/identifier/renameVariables.js +39 -27
  32. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  33. package/dist/transforms/minify.js +80 -61
  34. package/dist/transforms/opaquePredicates.js +1 -1
  35. package/dist/transforms/preparation/preparation.js +2 -2
  36. package/dist/transforms/preparation.js +231 -0
  37. package/dist/transforms/renameLabels.js +1 -1
  38. package/dist/transforms/rgf.js +4 -5
  39. package/dist/transforms/stack.js +87 -26
  40. package/dist/transforms/string/encoding.js +150 -179
  41. package/dist/transforms/string/stringCompression.js +14 -15
  42. package/dist/transforms/string/stringConcealing.js +25 -8
  43. package/dist/transforms/string/stringEncoding.js +13 -24
  44. package/dist/transforms/transform.js +11 -18
  45. package/dist/traverse.js +24 -18
  46. package/dist/util/compare.js +2 -2
  47. package/dist/util/gen.js +15 -0
  48. package/dist/util/insert.js +31 -7
  49. package/dist/util/random.js +15 -0
  50. package/package.json +5 -5
  51. package/src/index.ts +57 -19
  52. package/src/obfuscator.ts +26 -29
  53. package/src/options.ts +17 -21
  54. package/src/order.ts +4 -8
  55. package/src/probability.ts +2 -3
  56. package/src/templates/bufferToString.ts +68 -0
  57. package/src/templates/crash.ts +5 -9
  58. package/src/templates/es5.ts +131 -0
  59. package/src/transforms/antiTooling.ts +1 -1
  60. package/src/transforms/calculator.ts +122 -59
  61. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  62. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
  63. package/src/transforms/deadCode.ts +383 -26
  64. package/src/transforms/dispatcher.ts +8 -6
  65. package/src/transforms/es5/antiClass.ts +10 -1
  66. package/src/transforms/es5/antiDestructuring.ts +3 -1
  67. package/src/transforms/es5/es5.ts +32 -77
  68. package/src/transforms/eval.ts +18 -0
  69. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
  70. package/src/transforms/extraction/objectExtraction.ts +12 -5
  71. package/src/transforms/finalizer.ts +75 -0
  72. package/src/transforms/flatten.ts +194 -151
  73. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  74. package/src/transforms/identifier/globalConcealing.ts +14 -103
  75. package/src/transforms/identifier/movedDeclarations.ts +4 -11
  76. package/src/transforms/identifier/renameVariables.ts +37 -30
  77. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  78. package/src/transforms/minify.ts +116 -77
  79. package/src/transforms/opaquePredicates.ts +2 -2
  80. package/src/transforms/preparation.ts +238 -0
  81. package/src/transforms/renameLabels.ts +2 -2
  82. package/src/transforms/rgf.ts +6 -7
  83. package/src/transforms/stack.ts +97 -37
  84. package/src/transforms/string/encoding.ts +115 -212
  85. package/src/transforms/string/stringCompression.ts +27 -18
  86. package/src/transforms/string/stringConcealing.ts +41 -11
  87. package/src/transforms/string/stringEncoding.ts +18 -18
  88. package/src/transforms/transform.ts +15 -21
  89. package/src/traverse.ts +24 -12
  90. package/src/types.ts +11 -2
  91. package/src/util/compare.ts +2 -2
  92. package/src/util/gen.ts +21 -1
  93. package/src/util/insert.ts +49 -9
  94. package/src/util/random.ts +13 -0
  95. package/test/code/Cash.test.ts +1 -1
  96. package/test/code/Dynamic.test.ts +12 -10
  97. package/test/code/ES6.src.js +136 -0
  98. package/test/code/ES6.test.ts +28 -2
  99. package/test/code/NewFeatures.test.ts +19 -0
  100. package/test/index.test.ts +15 -2
  101. package/test/probability.test.ts +44 -0
  102. package/test/templates/template.test.ts +1 -1
  103. package/test/transforms/antiTooling.test.ts +52 -0
  104. package/test/transforms/calculator.test.ts +40 -0
  105. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
  106. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  107. package/test/transforms/deadCode.test.ts +66 -15
  108. package/test/transforms/dispatcher.test.ts +44 -1
  109. package/test/transforms/es5/antiClass.test.ts +33 -0
  110. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  111. package/test/transforms/eval.test.ts +53 -0
  112. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  113. package/test/transforms/flatten.test.ts +195 -3
  114. package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
  115. package/test/transforms/identifier/renameVariables.test.ts +108 -0
  116. package/test/transforms/lock/antiDebug.test.ts +2 -2
  117. package/test/transforms/minify.test.ts +151 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +56 -29
  120. package/test/transforms/stack.test.ts +91 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +115 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/compare.test.ts +23 -1
  127. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  128. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  129. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  130. package/src/transforms/hexadecimalNumbers.ts +0 -31
  131. package/src/transforms/hideInitializingCode.ts +0 -432
  132. package/src/transforms/label.ts +0 -64
  133. package/src/transforms/preparation/nameConflicts.ts +0 -102
  134. package/src/transforms/preparation/preparation.ts +0 -176
  135. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  136. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  137. package/test/transforms/hideInitializingCode.test.ts +0 -336
  138. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  139. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -1,6 +1,4 @@
1
1
  import { ok } from "assert";
2
- import { stringify } from "querystring";
3
- import { reservedIdentifiers } from "../constants";
4
2
  import { ObfuscateOrder } from "../order";
5
3
  import { ComputeProbabilityMap } from "../probability";
6
4
  import Template from "../templates/template";
@@ -12,7 +10,6 @@ import {
12
10
  Identifier,
13
11
  IfStatement,
14
12
  Literal,
15
- Location,
16
13
  MemberExpression,
17
14
  Node,
18
15
  RestElement,
@@ -21,24 +18,24 @@ import {
21
18
  } from "../util/gen";
22
19
  import { getIdentifierInfo } from "../util/identifiers";
23
20
  import {
21
+ getBlockBody,
24
22
  getDefiningContext,
25
23
  getReferencingContexts,
26
- getVarContext,
27
24
  isForInitialize,
28
25
  isFunction,
29
26
  isVarContext,
30
27
  prepend,
31
28
  } from "../util/insert";
32
- import { choice, getRandomInteger, getRandomString } from "../util/random";
29
+ import { chance, choice, getRandomInteger } from "../util/random";
33
30
  import Transform from "./transform";
34
31
 
35
32
  export default class Stack extends Transform {
36
- made: number;
33
+ mangledExpressionsMade: number;
37
34
 
38
35
  constructor(o) {
39
36
  super(o, ObfuscateOrder.Stack);
40
37
 
41
- this.made = 0;
38
+ this.mangledExpressionsMade = 0;
42
39
  }
43
40
 
44
41
  match(object: Node, parents: Node[]) {
@@ -55,7 +52,9 @@ export default class Stack extends Transform {
55
52
  return () => {
56
53
  // Uncaught SyntaxError: Getter must not have any formal parameters.
57
54
  // Uncaught SyntaxError: Setter must have exactly one formal parameter
58
- var propIndex = parents.findIndex((x) => x.type == "Property");
55
+ var propIndex = parents.findIndex(
56
+ (x) => x.type === "Property" || x.type === "MethodDefinition"
57
+ );
59
58
  if (propIndex !== -1) {
60
59
  if (parents[propIndex].value === (parents[propIndex - 1] || object)) {
61
60
  if (parents[propIndex].kind !== "init" || parents[propIndex].method) {
@@ -64,13 +63,42 @@ export default class Stack extends Transform {
64
63
  }
65
64
  }
66
65
 
66
+ // Don't apply to functions with 'use strict' directive
67
+ if (getBlockBody(object.body)[0]?.directive) {
68
+ return;
69
+ }
70
+
71
+ if (!ComputeProbabilityMap(this.options.stack)) {
72
+ return;
73
+ }
74
+
67
75
  var defined = new Set<string>();
68
76
  var referenced = new Set<string>();
69
77
  var illegal = new Set<string>();
70
78
 
79
+ /**
80
+ * Maps old names to new indices
81
+ */
71
82
  var subscripts = new Map<string, string>();
72
83
  var deadValues = Object.create(null);
73
84
 
85
+ var propertyGen = this.getGenerator();
86
+
87
+ function isTransformableFunction(functionNode: Node) {
88
+ if (functionNode.$requiresEval) return false;
89
+
90
+ // Check for 'this'
91
+ var isIllegal = false;
92
+ walk(functionNode.body, [], (o, p) => {
93
+ if (o.type === "ThisExpression") {
94
+ isIllegal = true;
95
+ return "EXIT";
96
+ }
97
+ });
98
+
99
+ return !isIllegal;
100
+ }
101
+
74
102
  function setSubscript(string, index) {
75
103
  subscripts.set(string, index + "");
76
104
  }
@@ -87,15 +115,16 @@ export default class Stack extends Transform {
87
115
  walk(object.body, [object, ...parents], (o, p) => {
88
116
  if (o.type == "Identifier") {
89
117
  var info = getIdentifierInfo(o, p);
90
- if (!info.spec.isReferenced) {
118
+ if (!info.spec.isReferenced || info.spec.isExported) {
91
119
  return;
92
120
  }
121
+
93
122
  var c = info.spec.isDefined
94
123
  ? getDefiningContext(o, p)
95
124
  : getReferencingContexts(o, p).find((x) => isVarContext(x));
96
125
 
97
126
  if (c !== object) {
98
- this.log(o.name + " is illegal due to different context");
127
+ // this.log(o.name + " is illegal due to different context");
99
128
  illegal.add(o.name);
100
129
  }
101
130
 
@@ -104,9 +133,9 @@ export default class Stack extends Transform {
104
133
  info.isFunctionParameter ||
105
134
  isForInitialize(o, p)
106
135
  ) {
107
- this.log(
108
- o.name + " is illegal due to clause parameter/function parameter"
109
- );
136
+ // this.log(
137
+ // o.name + " is illegal due to clause parameter/function parameter"
138
+ // );
110
139
  illegal.add(o.name);
111
140
  }
112
141
  if (o.hidden) {
@@ -119,22 +148,53 @@ export default class Stack extends Transform {
119
148
  }
120
149
 
121
150
  if (info.isFunctionDeclaration) {
122
- if (p[0] !== object.body.body[0]) {
151
+ ok(p[0].type === "FunctionDeclaration");
152
+ if (
153
+ p[0] !== object.body.body[0] ||
154
+ !isTransformableFunction(p[0])
155
+ ) {
123
156
  illegal.add(o.name);
124
157
  }
125
158
  }
126
159
 
127
- setSubscript(o.name, subscripts.size);
160
+ // The new accessors will either be numbered: [index] or as a string .string
161
+ var newSubscript = choice([
162
+ subscripts.size,
163
+ propertyGen.generate(),
164
+ ]);
165
+
166
+ setSubscript(o.name, newSubscript);
128
167
  defined.add(o.name);
129
168
 
169
+ // Stack can only process single VariableDeclarations
130
170
  var varIndex = p.findIndex((x) => x.type == "VariableDeclaration");
131
- if (
132
- varIndex !== -1 &&
133
- (varIndex !== 2 || p[varIndex].declarations.length > 1)
134
- ) {
135
- illegal.add(o.name);
171
+
172
+ if (varIndex !== -1) {
173
+ // Invalid 'id' property (must be Identifier)
174
+ if (varIndex !== 2) {
175
+ illegal.add(o.name);
176
+ } else if (p[varIndex].declarations.length > 1) {
177
+ illegal.add(o.name);
178
+ } else {
179
+ var value = p[varIndex].declarations[0].init;
180
+ if (value && !isTransformableFunction(value)) {
181
+ illegal.add(o.name);
182
+ }
183
+ }
136
184
  }
137
185
  } else if (info.spec.isReferenced) {
186
+ if (info.spec.isModified) {
187
+ var assignmentIndex = p.findIndex(
188
+ (x) => x.type === "AssignmentExpression"
189
+ );
190
+ if (assignmentIndex !== -1) {
191
+ var value = p[assignmentIndex].right;
192
+ if (value && !isTransformableFunction(value)) {
193
+ illegal.add(o.name);
194
+ }
195
+ }
196
+ }
197
+
138
198
  referenced.add(o.name);
139
199
  }
140
200
  }
@@ -160,16 +220,17 @@ export default class Stack extends Transform {
160
220
  return;
161
221
  }
162
222
 
163
- function numberLiteral(number, depth = 0) {
223
+ const numberLiteral = (number: number | string, depth = 0): Node => {
164
224
  ok(number === number);
165
225
  if (
166
226
  typeof number !== "number" ||
167
227
  !Object.keys(deadValues).length ||
168
- depth > 5 ||
169
- Math.random() > (depth == 0 ? 0.9 : 0.8 / (depth * 2))
228
+ depth > 4 ||
229
+ chance(75 + depth * 15 + this.mangledExpressionsMade / 25)
170
230
  ) {
171
231
  return Literal(number);
172
232
  }
233
+ this.mangledExpressionsMade++;
173
234
 
174
235
  var opposingIndex = choice(Object.keys(deadValues));
175
236
  if (typeof opposingIndex === "undefined") {
@@ -193,7 +254,7 @@ export default class Stack extends Transform {
193
254
  ),
194
255
  numberLiteral(actualValue - number, depth + 1)
195
256
  );
196
- }
257
+ };
197
258
 
198
259
  function getMemberExpression(index) {
199
260
  ok(typeof index === "string", typeof index);
@@ -204,8 +265,7 @@ export default class Stack extends Transform {
204
265
  );
205
266
  }
206
267
 
207
- var stackName = this.getPlaceholder();
208
- var made = 1;
268
+ var stackName = this.getPlaceholder() + "_stack";
209
269
 
210
270
  const scan = (o, p) => {
211
271
  if (o.type == "Identifier") {
@@ -287,10 +347,9 @@ export default class Stack extends Transform {
287
347
  typeof o.value === "number" &&
288
348
  Math.floor(o.value) === o.value &&
289
349
  Math.abs(o.value) < 100_000 &&
290
- Math.random() < 4 / made &&
291
- p.find((x) => isFunction(x)) === object
350
+ p.find((x) => isFunction(x)) === object &&
351
+ chance(50)
292
352
  ) {
293
- made++;
294
353
  return () => {
295
354
  this.replaceIdentifierOrLiteral(o, numberLiteral(o.value, 0), p);
296
355
  };
@@ -302,10 +361,10 @@ export default class Stack extends Transform {
302
361
  object.body.body.forEach((stmt, index) => {
303
362
  var isFirst = index == 0;
304
363
 
305
- if (isFirst || Math.random() < 0.9 / index) {
364
+ if (isFirst || chance(50 - index * 10)) {
306
365
  var exprs = [];
307
366
 
308
- var changes = getRandomInteger(isFirst ? 2 : 1, isFirst ? 3 : 2);
367
+ var changes = getRandomInteger(1, 3);
309
368
 
310
369
  for (var i = 0; i < changes; i++) {
311
370
  var expr;
@@ -318,8 +377,10 @@ export default class Stack extends Transform {
318
377
  var newIndex;
319
378
  var i = 0;
320
379
  do {
321
- newIndex =
322
- getRandomInteger(0, 250 + subscripts.size + i * 1000) + "";
380
+ newIndex = choice([
381
+ propertyGen.generate(),
382
+ getRandomInteger(0, 250 + subscripts.size + i * 1000) + "",
383
+ ]);
323
384
  i++;
324
385
  } while (valueSet.has(newIndex));
325
386
 
@@ -342,10 +403,10 @@ export default class Stack extends Transform {
342
403
  break;
343
404
 
344
405
  case "deadValue":
345
- var rand = getRandomInteger(-250, 250);
406
+ var rand = getRandomInteger(-150, 150);
346
407
 
347
408
  // modify an already existing dead value index
348
- if (Math.random() > 0.5) {
409
+ if (chance(50)) {
349
410
  var alreadyExisting = choice(Object.keys(deadValues));
350
411
 
351
412
  if (typeof alreadyExisting === "string") {
@@ -359,7 +420,6 @@ export default class Stack extends Transform {
359
420
  numberLiteral(rand)
360
421
  );
361
422
 
362
- ok(!subscripts.has(newIndex));
363
423
  deadValues[newIndex] = rand;
364
424
  break;
365
425
  }
@@ -413,7 +473,7 @@ export default class Stack extends Transform {
413
473
  // Ensure the array is correct length
414
474
  prepend(
415
475
  object.body,
416
- Template(`${stackName}.length = ${startingSize}`).single()
476
+ Template(`${stackName}["length"] = ${startingSize}`).single()
417
477
  );
418
478
  };
419
479
  }
@@ -7,7 +7,120 @@ const Encoding: {
7
7
  template: ReturnType<typeof Template>;
8
8
  };
9
9
  } = {
10
- ascii85: {
10
+ base91: {
11
+ encode(str) {
12
+ const table =
13
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"';
14
+
15
+ const raw = Buffer.from(str, "utf-8");
16
+ const len = raw.length;
17
+ let ret = "";
18
+
19
+ let n = 0;
20
+ let b = 0;
21
+
22
+ for (let i = 0; i < len; i++) {
23
+ b |= raw[i] << n;
24
+ n += 8;
25
+
26
+ if (n > 13) {
27
+ let v = b & 8191;
28
+ if (v > 88) {
29
+ b >>= 13;
30
+ n -= 13;
31
+ } else {
32
+ v = b & 16383;
33
+ b >>= 14;
34
+ n -= 14;
35
+ }
36
+ ret += table[v % 91] + table[(v / 91) | 0];
37
+ }
38
+ }
39
+
40
+ if (n) {
41
+ ret += table[b % 91];
42
+ if (n > 7 || b > 90) ret += table[(b / 91) | 0];
43
+ }
44
+
45
+ return ret;
46
+ },
47
+ decode(str) {
48
+ const table =
49
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"';
50
+
51
+ const raw = "" + (str || "");
52
+ const len = raw.length;
53
+ const ret = [];
54
+
55
+ let b = 0;
56
+ let n = 0;
57
+ let v = -1;
58
+
59
+ for (let i = 0; i < len; i++) {
60
+ const p = table.indexOf(raw[i]);
61
+ if (p === -1) continue;
62
+ if (v < 0) {
63
+ v = p;
64
+ } else {
65
+ v += p * 91;
66
+ b |= v << n;
67
+ n += (v & 8191) > 88 ? 13 : 14;
68
+ do {
69
+ ret.push(b & 0xff);
70
+ b >>= 8;
71
+ n -= 8;
72
+ } while (n > 7);
73
+ v = -1;
74
+ }
75
+ }
76
+
77
+ if (v > -1) {
78
+ ret.push((b | (v << n)) & 0xff);
79
+ }
80
+
81
+ return Buffer.from(ret).toString("utf-8");
82
+ },
83
+ template: Template(`
84
+ function {name}(str){
85
+ const table =
86
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_\`{|}~"';
87
+
88
+ const raw = "" + (str || "");
89
+ const len = raw.length;
90
+ const ret = [];
91
+
92
+ let b = 0;
93
+ let n = 0;
94
+ let v = -1;
95
+
96
+ for (let i = 0; i < len; i++) {
97
+ const p = table.indexOf(raw[i]);
98
+ if (p === -1) continue;
99
+ if (v < 0) {
100
+ v = p;
101
+ } else {
102
+ v += p * 91;
103
+ b |= v << n;
104
+ n += (v & 8191) > 88 ? 13 : 14;
105
+ do {
106
+ ret.push(b & 0xff);
107
+ b >>= 8;
108
+ n -= 8;
109
+ } while (n > 7);
110
+ v = -1;
111
+ }
112
+ }
113
+
114
+ if (v > -1) {
115
+ ret.push((b | (v << n)) & 0xff);
116
+ }
117
+
118
+ return {bufferToString}(ret);
119
+ }
120
+ `),
121
+ },
122
+
123
+ /* ascii85: { This implementation is flaky and causes decoding errors
11
124
  encode(a) {
12
125
  var b, c, d, e, f, g, h, i, j, k;
13
126
  // @ts-ignore
@@ -94,217 +207,7 @@ const Encoding: {
94
207
  }(e, c[l]), h[LL[0]][LL[1]](h, e);
95
208
  }
96
209
  `),
97
- },
98
-
99
- base32: {
100
- encode: function (s) {
101
- var a = "!\"#$%&'()*+,-./0123456789:;<=>?@";
102
- var len = s.length;
103
- var o = "";
104
- var w,
105
- c,
106
- r = 0,
107
- sh = 0,
108
- i;
109
- for (i = 0; i < len; i += 5) {
110
- // mask top 5 bits
111
- c = s.charCodeAt(i);
112
- w = 0xf8 & c;
113
- o += a.charAt(w >> 3);
114
- r = 0x07 & c;
115
- sh = 2;
116
-
117
- if (i + 1 < len) {
118
- c = s.charCodeAt(i + 1);
119
- // mask top 2 bits
120
- w = 0xc0 & c;
121
- o += a.charAt((r << 2) + (w >> 6));
122
- o += a.charAt((0x3e & c) >> 1);
123
- r = c & 0x01;
124
- sh = 4;
125
- }
126
-
127
- if (i + 2 < len) {
128
- c = s.charCodeAt(i + 2);
129
- // mask top 4 bits
130
- w = 0xf0 & c;
131
- o += a.charAt((r << 4) + (w >> 4));
132
- r = 0x0f & c;
133
- sh = 1;
134
- }
135
-
136
- if (i + 3 < len) {
137
- c = s.charCodeAt(i + 3);
138
- // mask top 1 bit
139
- w = 0x80 & c;
140
- o += a.charAt((r << 1) + (w >> 7));
141
- o += a.charAt((0x7c & c) >> 2);
142
- r = 0x03 & c;
143
- sh = 3;
144
- }
145
-
146
- if (i + 4 < len) {
147
- c = s.charCodeAt(i + 4);
148
- // mask top 3 bits
149
- w = 0xe0 & c;
150
- o += a.charAt((r << 3) + (w >> 5));
151
- o += a.charAt(0x1f & c);
152
- r = 0;
153
- sh = 0;
154
- }
155
- }
156
- // Calculate length of pad by getting the
157
- // number of words to reach an 8th octet.
158
- if (r != 0) {
159
- o += a.charAt(r << sh);
160
- }
161
- return o;
162
- },
163
- decode: function (s) {
164
- var v,
165
- x,
166
- bits = 0,
167
- o = "",
168
- len = s.length,
169
- d = String,
170
- e = "charCodeAt",
171
- f = "fromCharCode",
172
- i;
173
-
174
- for (i = 0; i < len; i += 1) {
175
- (v = s[e](i) - 33),
176
- v >= 0 && v < 32
177
- ? ((bits += ((x = (x << 5) | v), 5)),
178
- bits >= 8
179
- ? (bits -= ((o += d[f]((x >> (bits - 8)) & 0xff)), 8))
180
- : 0)
181
- : 0;
182
- }
183
- return o;
184
- },
185
- template: Template(`
186
- function {name}(s) {
187
- var v,
188
- x,
189
- b = 0,
190
- o = "",
191
- len = s.length,
192
- d = String,
193
- e = "charCodeAt",
194
- f = "fromCharCode", i;
195
-
196
- for (i = 0; i < len; i += 1) {
197
- (v = s[e](i) - 33),
198
- v >= 0 && v < 32
199
- ? ((b += ((x = (x << 5) | v), 5)),
200
- b >= 8
201
- ? (b -= ((o += d[f]((x >> (b - 8)) & 0xff)), 8))
202
- : 0)
203
- : 0;
204
- }
205
- return o;
206
- }
207
- `),
208
- },
209
-
210
- hexTable: {
211
- encode: function (str) {
212
- var output = "";
213
-
214
- for (var j = 0; j < str.length; j += 3) {
215
- var chunk = str.substring(j, j + 3);
216
- if (!chunk) {
217
- continue;
218
- }
219
-
220
- chunk = chunk + "~";
221
-
222
- var uniqueChars = new Set([]);
223
- for (var char of chunk) {
224
- uniqueChars.add(char);
225
- }
226
-
227
- var keys = Array.from(uniqueChars).sort();
228
- var table = {},
229
- i = 0;
230
- for (var key of keys) {
231
- table[key] = i++;
232
- }
233
-
234
- var idx = [];
235
- for (var char of chunk) {
236
- idx.push(table[char]);
237
- }
238
-
239
- var table64 = "0x";
240
- for (var i = keys.length - 1; i >= 0; i--) {
241
- table64 += keys[i].charCodeAt(0).toString(16).toUpperCase();
242
- }
243
-
244
- var idxInt = 0;
245
- for (var i = idx.length - 1; i >= 0; i--) {
246
- idxInt = (idxInt << 3) | idx[i];
247
- }
248
-
249
- var idx64 = "0x" + idxInt.toString(16).toUpperCase();
250
-
251
- // console.log(chunk, table, idx, table64, idx64);
252
-
253
- output += table64 + "," + idx64 + ",";
254
- }
255
-
256
- if (output.endsWith(",")) {
257
- output = output.substring(0, output.length - 1);
258
- }
259
-
260
- return "{" + output + "}";
261
- },
262
-
263
- decode: function (str) {
264
- var output = "";
265
-
266
- str = str.substring(1, str.length - 1);
267
- var chunks = str.split(",");
268
-
269
- for (var i = 0; i < chunks.length; i += 2) {
270
- var arr = [chunks[i], chunks[i + 1]];
271
-
272
- var [table, idx] = arr.map(Number);
273
-
274
- // console.log(table, idx);
275
- while (idx) {
276
- output += String.fromCharCode((table >> (8 * (idx & 7))) & 0xff);
277
- idx >>= 3;
278
- }
279
- }
280
-
281
- return output.replace(/~/g, "");
282
- },
283
-
284
- template: Template(`
285
- function {name}(str){
286
- var output = "";
287
-
288
- str = str.substring(1, str.length - 1);
289
- var chunks = str.split(",");
290
-
291
- for (var i = 0; i < chunks.length; i += 2) {
292
- var arr = [chunks[i], chunks[i + 1]];
293
-
294
- var [table, idx] = arr.map(Number);
295
-
296
- // console.log(table, idx);
297
- while (idx) {
298
- output += String.fromCharCode((table >> (8 * (idx & 7))) & 0xff);
299
- idx >>= 3;
300
- }
301
- }
302
-
303
- return output.replace(/~/g, "");
304
- }
305
-
306
- `),
307
- },
210
+ }, */
308
211
  };
309
212
 
310
213
  export default Encoding;