Skip to content

Commit 795cb75

Browse files
committed
Add TypeScript configuration and convert initial library files
- Add tsconfig.json with strict TypeScript settings - Convert 6 utility library files to TypeScript: - AtobBtoa.ts: Base64 encoding/decoding utilities - globalObject.ts: Global object detection for cross-platform support - console.ts: Console logging wrapper with proper typing - pdfname.ts: PDF name object conversion with type safety - rc4.ts: RC4 encryption algorithm with typed parameters - md5.ts: MD5 hashing implementation with number array types All conversions maintain original functionality while adding proper TypeScript types, replacing var with const/let, and using modern array parameter syntax.
1 parent e080935 commit 795cb75

File tree

7 files changed

+433
-0
lines changed

7 files changed

+433
-0
lines changed

src/libs/AtobBtoa.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { globalObject } from "./globalObject.js";
2+
3+
const atob = globalObject.atob.bind(globalObject);
4+
const btoa = globalObject.btoa.bind(globalObject);
5+
6+
export { atob, btoa };

src/libs/console.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { globalObject } from "./globalObject.js";
2+
3+
function consoleLog(...args: any[]): void {
4+
if (globalObject.console && typeof globalObject.console.log === "function") {
5+
globalObject.console.log.apply(globalObject.console, args);
6+
}
7+
}
8+
9+
function consoleWarn(...args: any[]): void {
10+
if (globalObject.console) {
11+
if (typeof globalObject.console.warn === "function") {
12+
globalObject.console.warn.apply(globalObject.console, args);
13+
} else {
14+
consoleLog.call(null, ...args);
15+
}
16+
}
17+
}
18+
19+
function consoleError(...args: any[]): void {
20+
if (globalObject.console) {
21+
if (typeof globalObject.console.error === "function") {
22+
globalObject.console.error.apply(globalObject.console, args);
23+
} else {
24+
consoleLog(...args);
25+
}
26+
}
27+
}
28+
29+
export const console = {
30+
log: consoleLog,
31+
warn: consoleWarn,
32+
error: consoleError
33+
};

src/libs/globalObject.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const globalObject: any = (function(): any {
2+
return typeof window !== "undefined"
3+
? window
4+
: typeof global !== "undefined"
5+
? global
6+
: typeof self !== "undefined"
7+
? self
8+
: this;
9+
})();

src/libs/md5.ts

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**
2+
* @license
3+
* Joseph Myers does not specify a particular license for his work.
4+
*
5+
* Author: Joseph Myers
6+
* Accessed from: http://www.myersdaily.org/joseph/javascript/md5.js
7+
*
8+
* Modified by: Owen Leong
9+
*/
10+
11+
function md5cycle(x: number[], k: number[]): void {
12+
let a = x[0],
13+
b = x[1],
14+
c = x[2],
15+
d = x[3];
16+
17+
a = ff(a, b, c, d, k[0], 7, -680876936);
18+
d = ff(d, a, b, c, k[1], 12, -389564586);
19+
c = ff(c, d, a, b, k[2], 17, 606105819);
20+
b = ff(b, c, d, a, k[3], 22, -1044525330);
21+
a = ff(a, b, c, d, k[4], 7, -176418897);
22+
d = ff(d, a, b, c, k[5], 12, 1200080426);
23+
c = ff(c, d, a, b, k[6], 17, -1473231341);
24+
b = ff(b, c, d, a, k[7], 22, -45705983);
25+
a = ff(a, b, c, d, k[8], 7, 1770035416);
26+
d = ff(d, a, b, c, k[9], 12, -1958414417);
27+
c = ff(c, d, a, b, k[10], 17, -42063);
28+
b = ff(b, c, d, a, k[11], 22, -1990404162);
29+
a = ff(a, b, c, d, k[12], 7, 1804603682);
30+
d = ff(d, a, b, c, k[13], 12, -40341101);
31+
c = ff(c, d, a, b, k[14], 17, -1502002290);
32+
b = ff(b, c, d, a, k[15], 22, 1236535329);
33+
34+
a = gg(a, b, c, d, k[1], 5, -165796510);
35+
d = gg(d, a, b, c, k[6], 9, -1069501632);
36+
c = gg(c, d, a, b, k[11], 14, 643717713);
37+
b = gg(b, c, d, a, k[0], 20, -373897302);
38+
a = gg(a, b, c, d, k[5], 5, -701558691);
39+
d = gg(d, a, b, c, k[10], 9, 38016083);
40+
c = gg(c, d, a, b, k[15], 14, -660478335);
41+
b = gg(b, c, d, a, k[4], 20, -405537848);
42+
a = gg(a, b, c, d, k[9], 5, 568446438);
43+
d = gg(d, a, b, c, k[14], 9, -1019803690);
44+
c = gg(c, d, a, b, k[3], 14, -187363961);
45+
b = gg(b, c, d, a, k[8], 20, 1163531501);
46+
a = gg(a, b, c, d, k[13], 5, -1444681467);
47+
d = gg(d, a, b, c, k[2], 9, -51403784);
48+
c = gg(c, d, a, b, k[7], 14, 1735328473);
49+
b = gg(b, c, d, a, k[12], 20, -1926607734);
50+
51+
a = hh(a, b, c, d, k[5], 4, -378558);
52+
d = hh(d, a, b, c, k[8], 11, -2022574463);
53+
c = hh(c, d, a, b, k[11], 16, 1839030562);
54+
b = hh(b, c, d, a, k[14], 23, -35309556);
55+
a = hh(a, b, c, d, k[1], 4, -1530992060);
56+
d = hh(d, a, b, c, k[4], 11, 1272893353);
57+
c = hh(c, d, a, b, k[7], 16, -155497632);
58+
b = hh(b, c, d, a, k[10], 23, -1094730640);
59+
a = hh(a, b, c, d, k[13], 4, 681279174);
60+
d = hh(d, a, b, c, k[0], 11, -358537222);
61+
c = hh(c, d, a, b, k[3], 16, -722521979);
62+
b = hh(b, c, d, a, k[6], 23, 76029189);
63+
a = hh(a, b, c, d, k[9], 4, -640364487);
64+
d = hh(d, a, b, c, k[12], 11, -421815835);
65+
c = hh(c, d, a, b, k[15], 16, 530742520);
66+
b = hh(b, c, d, a, k[2], 23, -995338651);
67+
68+
a = ii(a, b, c, d, k[0], 6, -198630844);
69+
d = ii(d, a, b, c, k[7], 10, 1126891415);
70+
c = ii(c, d, a, b, k[14], 15, -1416354905);
71+
b = ii(b, c, d, a, k[5], 21, -57434055);
72+
a = ii(a, b, c, d, k[12], 6, 1700485571);
73+
d = ii(d, a, b, c, k[3], 10, -1894986606);
74+
c = ii(c, d, a, b, k[10], 15, -1051523);
75+
b = ii(b, c, d, a, k[1], 21, -2054922799);
76+
a = ii(a, b, c, d, k[8], 6, 1873313359);
77+
d = ii(d, a, b, c, k[15], 10, -30611744);
78+
c = ii(c, d, a, b, k[6], 15, -1560198380);
79+
b = ii(b, c, d, a, k[13], 21, 1309151649);
80+
a = ii(a, b, c, d, k[4], 6, -145523070);
81+
d = ii(d, a, b, c, k[11], 10, -1120210379);
82+
c = ii(c, d, a, b, k[2], 15, 718787259);
83+
b = ii(b, c, d, a, k[9], 21, -343485551);
84+
85+
x[0] = add32(a, x[0]);
86+
x[1] = add32(b, x[1]);
87+
x[2] = add32(c, x[2]);
88+
x[3] = add32(d, x[3]);
89+
}
90+
91+
function cmn(q: number, a: number, b: number, x: number, s: number, t: number): number {
92+
a = add32(add32(a, q), add32(x, t));
93+
return add32((a << s) | (a >>> (32 - s)), b);
94+
}
95+
96+
function ff(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {
97+
return cmn((b & c) | (~b & d), a, b, x, s, t);
98+
}
99+
100+
function gg(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {
101+
return cmn((b & d) | (c & ~d), a, b, x, s, t);
102+
}
103+
104+
function hh(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {
105+
return cmn(b ^ c ^ d, a, b, x, s, t);
106+
}
107+
108+
function ii(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {
109+
return cmn(c ^ (b | ~d), a, b, x, s, t);
110+
}
111+
112+
function md51(s: string): number[] {
113+
// txt = '';
114+
const n = s.length;
115+
const state: number[] = [1732584193, -271733879, -1732584194, 271733878];
116+
let i: number;
117+
for (i = 64; i <= s.length; i += 64) {
118+
md5cycle(state, md5blk(s.substring(i - 64, i)));
119+
}
120+
s = s.substring(i - 64);
121+
const tail: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
122+
for (i = 0; i < s.length; i++)
123+
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
124+
tail[i >> 2] |= 0x80 << (i % 4 << 3);
125+
if (i > 55) {
126+
md5cycle(state, tail);
127+
for (i = 0; i < 16; i++) tail[i] = 0;
128+
}
129+
tail[14] = n * 8;
130+
md5cycle(state, tail);
131+
return state;
132+
}
133+
134+
/* there needs to be support for Unicode here,
135+
* unless we pretend that we can redefine the MD-5
136+
* algorithm for multi-byte characters (perhaps
137+
* by adding every four 16-bit characters and
138+
* shortening the sum to 32 bits). Otherwise
139+
* I suggest performing MD-5 as if every character
140+
* was two bytes--e.g., 0040 0025 = @%--but then
141+
* how will an ordinary MD-5 sum be matched?
142+
* There is no way to standardize text to something
143+
* like UTF-8 before transformation; speed cost is
144+
* utterly prohibitive. The JavaScript standard
145+
* itself needs to look at this: it should start
146+
* providing access to strings as preformed UTF-8
147+
* 8-bit unsigned value arrays.
148+
*/
149+
function md5blk(s: string): number[] {
150+
/* I figured global was faster. */
151+
const md5blks: number[] = [];
152+
let i: number; /* Andy King said do it this way. */
153+
for (i = 0; i < 64; i += 4) {
154+
md5blks[i >> 2] =
155+
s.charCodeAt(i) +
156+
(s.charCodeAt(i + 1) << 8) +
157+
(s.charCodeAt(i + 2) << 16) +
158+
(s.charCodeAt(i + 3) << 24);
159+
}
160+
return md5blks;
161+
}
162+
163+
const hex_chr = "0123456789abcdef".split("");
164+
165+
function rhex(n: number): string {
166+
let s = "";
167+
let j = 0;
168+
for (; j < 4; j++)
169+
s += hex_chr[(n >> (j * 8 + 4)) & 0x0f] + hex_chr[(n >> (j * 8)) & 0x0f];
170+
return s;
171+
}
172+
173+
function hex(x: number[]): string {
174+
for (let i = 0; i < x.length; i++) x[i] = rhex(x[i]) as any;
175+
return x.join("");
176+
}
177+
178+
// Converts a 4-byte number to byte string
179+
function singleToByteString(n: number): string {
180+
return String.fromCharCode(
181+
(n & 0xff) >> 0,
182+
(n & 0xff00) >> 8,
183+
(n & 0xff0000) >> 16,
184+
(n & 0xff000000) >> 24
185+
);
186+
}
187+
188+
// Converts an array of numbers to a byte string
189+
function toByteString(x: number[]): string {
190+
return x.map(singleToByteString).join("");
191+
}
192+
193+
// Returns the MD5 hash as a byte string
194+
function md5Bin(s: string): string {
195+
return toByteString(md51(s));
196+
}
197+
198+
// Returns MD5 hash as a hex string
199+
function md5(s: string): string {
200+
return hex(md51(s));
201+
}
202+
203+
const md5Check = md5("hello") != "5d41402abc4b2a76b9719d911017c592";
204+
205+
function add32(a: number, b: number): number {
206+
if (md5Check) {
207+
/* if the md5Check does not match
208+
the expected value, we're dealing
209+
with an old browser and need
210+
this function. */
211+
const lsw = (a & 0xffff) + (b & 0xffff);
212+
const msw = (a >> 16) + (b >> 16) + (lsw >> 16);
213+
return (msw << 16) | (lsw & 0xffff);
214+
} else {
215+
/* this function is much faster,
216+
so if possible we use it. Some IEs
217+
are the only ones I know of that
218+
need the idiotic second function,
219+
generated by an if clause. */
220+
return (a + b) & 0xffffffff;
221+
}
222+
}
223+
224+
export { md5, md5Bin };

src/libs/pdfname.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Convert string to `PDF Name Object`.
3+
* Detail: PDF Reference 1.3 - Chapter 3.2.4 Name Object
4+
* @param str
5+
*/
6+
function toPDFName(str: string): string {
7+
// eslint-disable-next-line no-control-regex
8+
if (/[^\u0000-\u00ff]/.test(str)) {
9+
// non ascii string
10+
throw new Error(
11+
"Invalid PDF Name Object: " + str + ", Only accept ASCII characters."
12+
);
13+
}
14+
let result = "";
15+
const strLength = str.length;
16+
for (let i = 0; i < strLength; i++) {
17+
const charCode = str.charCodeAt(i);
18+
if (
19+
charCode < 0x21 ||
20+
charCode === 0x23 /* # */ ||
21+
charCode === 0x25 /* % */ ||
22+
charCode === 0x28 /* ( */ ||
23+
charCode === 0x29 /* ) */ ||
24+
charCode === 0x2f /* / */ ||
25+
charCode === 0x3c /* < */ ||
26+
charCode === 0x3e /* > */ ||
27+
charCode === 0x5b /* [ */ ||
28+
charCode === 0x5d /* ] */ ||
29+
charCode === 0x7b /* { */ ||
30+
charCode === 0x7d /* } */ ||
31+
charCode > 0x7e
32+
) {
33+
// Char CharCode hexStr paddingHexStr Result
34+
// "\t" 9 9 09 #09
35+
// " " 32 20 20 #20
36+
// "©" 169 a9 a9 #a9
37+
const hexStr = charCode.toString(16);
38+
const paddingHexStr = ("0" + hexStr).slice(-2);
39+
40+
result += "#" + paddingHexStr;
41+
} else {
42+
// Other ASCII printable characters between 0x21 <= X <= 0x7e
43+
result += str[i];
44+
}
45+
}
46+
return result;
47+
}
48+
49+
export { toPDFName };

src/libs/rc4.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* @license
3+
* FPDF is released under a permissive license: there is no usage restriction.
4+
* You may embed it freely in your application (commercial or not), with or
5+
* without modifications.
6+
*
7+
* Reference: http://www.fpdf.org/en/script/script37.php
8+
*/
9+
10+
function repeat(str: string, num: number): string {
11+
return new Array(num + 1).join(str);
12+
}
13+
14+
let lastKey: string | undefined;
15+
let lastState: number[] | undefined;
16+
17+
/**
18+
* Converts a byte string to a hex string
19+
*
20+
* @name rc4
21+
* @function
22+
* @param {string} key Byte string of encryption key
23+
* @param {string} data Byte string of data to be encrypted
24+
* @returns {string} Encrypted string
25+
*/
26+
function rc4(key: string, data: string): string {
27+
let state: number[];
28+
if (key !== lastKey) {
29+
const k = repeat(key, ((256 / key.length) >> 0) + 1);
30+
state = [];
31+
for (let i = 0; i < 256; i++) {
32+
state[i] = i;
33+
}
34+
let j = 0;
35+
for (let i = 0; i < 256; i++) {
36+
const t = state[i];
37+
j = (j + t + k.charCodeAt(i)) % 256;
38+
state[i] = state[j];
39+
state[j] = t;
40+
}
41+
lastKey = key;
42+
lastState = state;
43+
} else {
44+
state = lastState!;
45+
}
46+
const length = data.length;
47+
let a = 0;
48+
let b = 0;
49+
let out = "";
50+
for (let i = 0; i < length; i++) {
51+
a = (a + 1) % 256;
52+
const t = state[a];
53+
b = (b + t) % 256;
54+
state[a] = state[b];
55+
state[b] = t;
56+
const k = state[(state[a] + state[b]) % 256];
57+
out += String.fromCharCode(data.charCodeAt(i) ^ k);
58+
}
59+
return out;
60+
}
61+
62+
export { rc4 };

0 commit comments

Comments
 (0)