dsh-remote-tunnel-easy 1.4.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.
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/assets/logo.svg +81 -0
- package/cordis.patch.yml +12 -0
- package/index.js +792 -0
- package/lib/client.js +617 -0
- package/lib/cloudflared.js +196 -0
- package/lib/qrcode.js +591 -0
- package/lib/update.js +221 -0
- package/package.json +51 -0
package/lib/qrcode.js
ADDED
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored QR encoder, self-contained ESM with no runtime dependencies.
|
|
3
|
+
*
|
|
4
|
+
* This is the QR code generator from `qrcode-terminal` (Kazuhiko Arase's
|
|
5
|
+
* `qrcode-generator`, MIT), collapsed from its original CJS file layout
|
|
6
|
+
* (vendor/QRCode/{QRCode,QR8bitByte,QRUtil,QRPolynomial,QRRSBlock,QRBitBuffer,
|
|
7
|
+
* QRErrorCorrectLevel,QRMode,QRMath,QRMaskPattern}) into this one module.
|
|
8
|
+
*
|
|
9
|
+
* Vendoring (rather than depending on `qrcode-terminal`) is deliberate: when
|
|
10
|
+
* this bundle is installed as a `link:`/`file:` spec, a dependency's package
|
|
11
|
+
* cannot be required from inside the checkout, so the QR step failed with
|
|
12
|
+
* "Cannot find module 'qrcode-terminal/vendor/QRCode'". Encoding a QR matrix
|
|
13
|
+
* needs no network, no native code, and no terminal output, so carrying the
|
|
14
|
+
* ~11 KB MIT encoder in-tree deletes the only remaining runtime dependency and
|
|
15
|
+
* makes `dsh plugin add/remove dsh-remote-tunnel-easy` dependency-free.
|
|
16
|
+
*
|
|
17
|
+
* Original header:
|
|
18
|
+
* QRCode for JavaScript — Copyright (c) 2009 Kazuhiko Arase
|
|
19
|
+
* URL: http://www.d-project.com/
|
|
20
|
+
* Licensed under the MIT license:
|
|
21
|
+
* http://www.opensource.org/licenses/mit-license.php
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const QRMode = {
|
|
25
|
+
MODE_NUMBER: 1 << 0,
|
|
26
|
+
MODE_ALPHA_NUM: 1 << 1,
|
|
27
|
+
MODE_8BIT_BYTE: 1 << 2,
|
|
28
|
+
MODE_KANJI: 1 << 3,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const QRMaskPattern = {
|
|
32
|
+
PATTERN000: 0,
|
|
33
|
+
PATTERN001: 1,
|
|
34
|
+
PATTERN010: 2,
|
|
35
|
+
PATTERN011: 3,
|
|
36
|
+
PATTERN100: 4,
|
|
37
|
+
PATTERN101: 5,
|
|
38
|
+
PATTERN110: 6,
|
|
39
|
+
PATTERN111: 7,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 }
|
|
43
|
+
|
|
44
|
+
const QRMath = {
|
|
45
|
+
glog(n) {
|
|
46
|
+
if (n < 1) throw new Error(`glog(${n})`)
|
|
47
|
+
return QRMath.LOG_TABLE[n]
|
|
48
|
+
},
|
|
49
|
+
gexp(n) {
|
|
50
|
+
while (n < 0) n += 255
|
|
51
|
+
while (n >= 256) n -= 255
|
|
52
|
+
return QRMath.EXP_TABLE[n]
|
|
53
|
+
},
|
|
54
|
+
EXP_TABLE: new Array(256),
|
|
55
|
+
LOG_TABLE: new Array(256),
|
|
56
|
+
}
|
|
57
|
+
for (let i = 0; i < 8; i++) QRMath.EXP_TABLE[i] = 1 << i
|
|
58
|
+
for (let i = 8; i < 256; i++) {
|
|
59
|
+
QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8]
|
|
60
|
+
}
|
|
61
|
+
for (let i = 0; i < 255; i++) QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i
|
|
62
|
+
|
|
63
|
+
function QRPolynomial(num, shift) {
|
|
64
|
+
if (num.length === undefined) throw new Error(`${num.length}/${shift}`)
|
|
65
|
+
let offset = 0
|
|
66
|
+
while (offset < num.length && num[offset] === 0) offset++
|
|
67
|
+
this.num = new Array(num.length - offset + shift)
|
|
68
|
+
for (let i = 0; i < num.length - offset; i++) this.num[i] = num[i + offset]
|
|
69
|
+
}
|
|
70
|
+
QRPolynomial.prototype = {
|
|
71
|
+
get(index) { return this.num[index] },
|
|
72
|
+
getLength() { return this.num.length },
|
|
73
|
+
multiply(e) {
|
|
74
|
+
const num = new Array(this.getLength() + e.getLength() - 1)
|
|
75
|
+
for (let i = 0; i < this.getLength(); i++) {
|
|
76
|
+
for (let j = 0; j < e.getLength(); j++) {
|
|
77
|
+
num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return new QRPolynomial(num, 0)
|
|
81
|
+
},
|
|
82
|
+
mod(e) {
|
|
83
|
+
if (this.getLength() - e.getLength() < 0) return this
|
|
84
|
+
const ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0))
|
|
85
|
+
const num = new Array(this.getLength())
|
|
86
|
+
for (let i = 0; i < this.getLength(); i++) num[i] = this.get(i)
|
|
87
|
+
for (let x = 0; x < e.getLength(); x++) num[x] ^= QRMath.gexp(QRMath.glog(e.get(x)) + ratio)
|
|
88
|
+
return new QRPolynomial(num, 0).mod(e)
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function QR8bitByte(data) {
|
|
93
|
+
this.mode = QRMode.MODE_8BIT_BYTE
|
|
94
|
+
this.data = data
|
|
95
|
+
}
|
|
96
|
+
QR8bitByte.prototype = {
|
|
97
|
+
getLength() { return this.data.length },
|
|
98
|
+
write(buffer) {
|
|
99
|
+
for (let i = 0; i < this.data.length; i++) buffer.put(this.data.charCodeAt(i), 8)
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function QRBitBuffer() {
|
|
104
|
+
this.buffer = []
|
|
105
|
+
this.length = 0
|
|
106
|
+
}
|
|
107
|
+
QRBitBuffer.prototype = {
|
|
108
|
+
get(index) {
|
|
109
|
+
const bufIndex = Math.floor(index / 8)
|
|
110
|
+
return ((this.buffer[bufIndex] >>> (7 - (index % 8))) & 1) === 1
|
|
111
|
+
},
|
|
112
|
+
put(num, length) {
|
|
113
|
+
for (let i = 0; i < length; i++) this.putBit(((num >>> (length - i - 1)) & 1) === 1)
|
|
114
|
+
},
|
|
115
|
+
getLengthInBits() { return this.length },
|
|
116
|
+
putBit(bit) {
|
|
117
|
+
const bufIndex = Math.floor(this.length / 8)
|
|
118
|
+
if (this.buffer.length <= bufIndex) this.buffer.push(0)
|
|
119
|
+
if (bit) this.buffer[bufIndex] |= 0x80 >>> (this.length % 8)
|
|
120
|
+
this.length++
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function QRRSBlock(totalCount, dataCount) {
|
|
125
|
+
this.totalCount = totalCount
|
|
126
|
+
this.dataCount = dataCount
|
|
127
|
+
}
|
|
128
|
+
QRRSBlock.RS_BLOCK_TABLE = [
|
|
129
|
+
[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9],
|
|
130
|
+
[1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16],
|
|
131
|
+
[1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13],
|
|
132
|
+
[1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9],
|
|
133
|
+
[1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12],
|
|
134
|
+
[2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15],
|
|
135
|
+
[2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14],
|
|
136
|
+
[2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15],
|
|
137
|
+
[2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13],
|
|
138
|
+
[2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16],
|
|
139
|
+
[4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13],
|
|
140
|
+
[2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15],
|
|
141
|
+
[4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12],
|
|
142
|
+
[3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13],
|
|
143
|
+
[5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12],
|
|
144
|
+
[5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16],
|
|
145
|
+
[1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15],
|
|
146
|
+
[5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15],
|
|
147
|
+
[3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14],
|
|
148
|
+
[3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16],
|
|
149
|
+
[4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17],
|
|
150
|
+
[2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13],
|
|
151
|
+
[4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16],
|
|
152
|
+
[6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17],
|
|
153
|
+
[8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16],
|
|
154
|
+
[10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17],
|
|
155
|
+
[8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16],
|
|
156
|
+
[3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16],
|
|
157
|
+
[7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16],
|
|
158
|
+
[5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16],
|
|
159
|
+
[13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16],
|
|
160
|
+
[17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16],
|
|
161
|
+
[17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16],
|
|
162
|
+
[13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17],
|
|
163
|
+
[12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16],
|
|
164
|
+
[6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16],
|
|
165
|
+
[17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16],
|
|
166
|
+
[4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16],
|
|
167
|
+
[20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16],
|
|
168
|
+
[19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16],
|
|
169
|
+
]
|
|
170
|
+
QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
|
|
171
|
+
const rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel)
|
|
172
|
+
if (rsBlock === undefined) throw new Error(`bad rs block @ typeNumber:${typeNumber}/errorCorrectLevel:${errorCorrectLevel}`)
|
|
173
|
+
const length = rsBlock.length / 3
|
|
174
|
+
const list = []
|
|
175
|
+
for (let i = 0; i < length; i++) {
|
|
176
|
+
const count = rsBlock[i * 3 + 0]
|
|
177
|
+
const totalCount = rsBlock[i * 3 + 1]
|
|
178
|
+
const dataCount = rsBlock[i * 3 + 2]
|
|
179
|
+
for (let j = 0; j < count; j++) list.push(new QRRSBlock(totalCount, dataCount))
|
|
180
|
+
}
|
|
181
|
+
return list
|
|
182
|
+
}
|
|
183
|
+
QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) {
|
|
184
|
+
switch (errorCorrectLevel) {
|
|
185
|
+
case QRErrorCorrectLevel.L: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]
|
|
186
|
+
case QRErrorCorrectLevel.M: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]
|
|
187
|
+
case QRErrorCorrectLevel.Q: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]
|
|
188
|
+
case QRErrorCorrectLevel.H: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]
|
|
189
|
+
default: return undefined
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const QRUtil = {
|
|
194
|
+
PATTERN_POSITION_TABLE: [
|
|
195
|
+
[], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50],
|
|
196
|
+
[6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78],
|
|
197
|
+
[6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102],
|
|
198
|
+
[6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122],
|
|
199
|
+
[6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138],
|
|
200
|
+
[6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154],
|
|
201
|
+
[6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170],
|
|
202
|
+
],
|
|
203
|
+
G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
|
|
204
|
+
G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
|
|
205
|
+
G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
|
|
206
|
+
getBCHTypeInfo(data) {
|
|
207
|
+
let d = data << 10
|
|
208
|
+
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
|
|
209
|
+
d ^= QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))
|
|
210
|
+
}
|
|
211
|
+
return ((data << 10) | d) ^ QRUtil.G15_MASK
|
|
212
|
+
},
|
|
213
|
+
getBCHTypeNumber(data) {
|
|
214
|
+
let d = data << 12
|
|
215
|
+
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
|
|
216
|
+
d ^= QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))
|
|
217
|
+
}
|
|
218
|
+
return (data << 12) | d
|
|
219
|
+
},
|
|
220
|
+
getBCHDigit(data) {
|
|
221
|
+
let digit = 0
|
|
222
|
+
while (data !== 0) { digit++; data >>>= 1 }
|
|
223
|
+
return digit
|
|
224
|
+
},
|
|
225
|
+
getPatternPosition(typeNumber) { return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1] },
|
|
226
|
+
getMask(maskPattern, i, j) {
|
|
227
|
+
switch (maskPattern) {
|
|
228
|
+
case QRMaskPattern.PATTERN000: return (i + j) % 2 === 0
|
|
229
|
+
case QRMaskPattern.PATTERN001: return i % 2 === 0
|
|
230
|
+
case QRMaskPattern.PATTERN010: return j % 3 === 0
|
|
231
|
+
case QRMaskPattern.PATTERN011: return (i + j) % 3 === 0
|
|
232
|
+
case QRMaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0
|
|
233
|
+
case QRMaskPattern.PATTERN101: return ((i * j) % 2) + ((i * j) % 3) === 0
|
|
234
|
+
case QRMaskPattern.PATTERN110: return (((i * j) % 2) + ((i * j) % 3)) % 2 === 0
|
|
235
|
+
case QRMaskPattern.PATTERN111: return (((i * j) % 3) + ((i + j) % 2)) % 2 === 0
|
|
236
|
+
default: throw new Error(`bad maskPattern:${maskPattern}`)
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
getErrorCorrectPolynomial(errorCorrectLength) {
|
|
240
|
+
let a = new QRPolynomial([1], 0)
|
|
241
|
+
for (let i = 0; i < errorCorrectLength; i++) a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0))
|
|
242
|
+
return a
|
|
243
|
+
},
|
|
244
|
+
getLengthInBits(mode, type) {
|
|
245
|
+
if (type >= 1 && type < 10) {
|
|
246
|
+
switch (mode) {
|
|
247
|
+
case QRMode.MODE_NUMBER: return 10
|
|
248
|
+
case QRMode.MODE_ALPHA_NUM: return 9
|
|
249
|
+
case QRMode.MODE_8BIT_BYTE: return 8
|
|
250
|
+
case QRMode.MODE_KANJI: return 8
|
|
251
|
+
default: throw new Error(`mode:${mode}`)
|
|
252
|
+
}
|
|
253
|
+
} else if (type < 27) {
|
|
254
|
+
switch (mode) {
|
|
255
|
+
case QRMode.MODE_NUMBER: return 12
|
|
256
|
+
case QRMode.MODE_ALPHA_NUM: return 11
|
|
257
|
+
case QRMode.MODE_8BIT_BYTE: return 16
|
|
258
|
+
case QRMode.MODE_KANJI: return 10
|
|
259
|
+
default: throw new Error(`mode:${mode}`)
|
|
260
|
+
}
|
|
261
|
+
} else if (type < 41) {
|
|
262
|
+
switch (mode) {
|
|
263
|
+
case QRMode.MODE_NUMBER: return 14
|
|
264
|
+
case QRMode.MODE_ALPHA_NUM: return 13
|
|
265
|
+
case QRMode.MODE_8BIT_BYTE: return 16
|
|
266
|
+
case QRMode.MODE_KANJI: return 12
|
|
267
|
+
default: throw new Error(`mode:${mode}`)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
throw new Error(`type:${type}`)
|
|
271
|
+
},
|
|
272
|
+
getLostPoint(qrCode) {
|
|
273
|
+
const moduleCount = qrCode.getModuleCount()
|
|
274
|
+
let lostPoint = 0
|
|
275
|
+
for (let row = 0; row < moduleCount; row++) {
|
|
276
|
+
for (let col = 0; col < moduleCount; col++) {
|
|
277
|
+
let sameCount = 0
|
|
278
|
+
const dark = qrCode.isDark(row, col)
|
|
279
|
+
for (let r = -1; r <= 1; r++) {
|
|
280
|
+
if (row + r < 0 || moduleCount <= row + r) continue
|
|
281
|
+
for (let c = -1; c <= 1; c++) {
|
|
282
|
+
if (col + c < 0 || moduleCount <= col + c) continue
|
|
283
|
+
if (r === 0 && c === 0) continue
|
|
284
|
+
if (dark === qrCode.isDark(row + r, col + c)) sameCount++
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (sameCount > 5) lostPoint += 3 + sameCount - 5
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
for (let row = 0; row < moduleCount - 1; row++) {
|
|
291
|
+
for (let col = 0; col < moduleCount - 1; col++) {
|
|
292
|
+
let count = 0
|
|
293
|
+
if (qrCode.isDark(row, col)) count++
|
|
294
|
+
if (qrCode.isDark(row + 1, col)) count++
|
|
295
|
+
if (qrCode.isDark(row, col + 1)) count++
|
|
296
|
+
if (qrCode.isDark(row + 1, col + 1)) count++
|
|
297
|
+
if (count === 0 || count === 4) lostPoint += 3
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
for (let row = 0; row < moduleCount; row++) {
|
|
301
|
+
for (let col = 0; col < moduleCount - 6; col++) {
|
|
302
|
+
if (qrCode.isDark(row, col)
|
|
303
|
+
&& !qrCode.isDark(row, col + 1)
|
|
304
|
+
&& qrCode.isDark(row, col + 2)
|
|
305
|
+
&& qrCode.isDark(row, col + 3)
|
|
306
|
+
&& qrCode.isDark(row, col + 4)
|
|
307
|
+
&& !qrCode.isDark(row, col + 5)
|
|
308
|
+
&& qrCode.isDark(row, col + 6)) {
|
|
309
|
+
lostPoint += 40
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
for (let col = 0; col < moduleCount; col++) {
|
|
314
|
+
for (let row = 0; row < moduleCount - 6; row++) {
|
|
315
|
+
if (qrCode.isDark(row, col)
|
|
316
|
+
&& !qrCode.isDark(row + 1, col)
|
|
317
|
+
&& qrCode.isDark(row + 2, col)
|
|
318
|
+
&& qrCode.isDark(row + 3, col)
|
|
319
|
+
&& qrCode.isDark(row + 4, col)
|
|
320
|
+
&& !qrCode.isDark(row + 5, col)
|
|
321
|
+
&& qrCode.isDark(row + 6, col)) {
|
|
322
|
+
lostPoint += 40
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
let darkCount = 0
|
|
327
|
+
for (let col = 0; col < moduleCount; col++) {
|
|
328
|
+
for (let row = 0; row < moduleCount; row++) {
|
|
329
|
+
if (qrCode.isDark(row, col)) darkCount++
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const ratio = Math.abs((100 * darkCount) / moduleCount / moduleCount - 50) / 5
|
|
333
|
+
lostPoint += ratio * 10
|
|
334
|
+
return lostPoint
|
|
335
|
+
},
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function QRCode(typeNumber, errorCorrectLevel) {
|
|
339
|
+
this.typeNumber = typeNumber
|
|
340
|
+
this.errorCorrectLevel = errorCorrectLevel
|
|
341
|
+
this.modules = null
|
|
342
|
+
this.moduleCount = 0
|
|
343
|
+
this.dataCache = null
|
|
344
|
+
this.dataList = []
|
|
345
|
+
}
|
|
346
|
+
QRCode.prototype = {
|
|
347
|
+
addData(data) {
|
|
348
|
+
this.dataList.push(new QR8bitByte(data))
|
|
349
|
+
this.dataCache = null
|
|
350
|
+
},
|
|
351
|
+
isDark(row, col) {
|
|
352
|
+
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) throw new Error(`${row},${col}`)
|
|
353
|
+
return this.modules[row][col]
|
|
354
|
+
},
|
|
355
|
+
getModuleCount() { return this.moduleCount },
|
|
356
|
+
make() {
|
|
357
|
+
if (this.typeNumber < 1) {
|
|
358
|
+
let typeNumber = 1
|
|
359
|
+
for (typeNumber = 1; typeNumber < 40; typeNumber++) {
|
|
360
|
+
const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel)
|
|
361
|
+
const buffer = new QRBitBuffer()
|
|
362
|
+
let totalDataCount = 0
|
|
363
|
+
for (let i = 0; i < rsBlocks.length; i++) totalDataCount += rsBlocks[i].dataCount
|
|
364
|
+
for (let x = 0; x < this.dataList.length; x++) {
|
|
365
|
+
const data = this.dataList[x]
|
|
366
|
+
buffer.put(data.mode, 4)
|
|
367
|
+
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber))
|
|
368
|
+
data.write(buffer)
|
|
369
|
+
}
|
|
370
|
+
if (buffer.getLengthInBits() <= totalDataCount * 8) break
|
|
371
|
+
}
|
|
372
|
+
this.typeNumber = typeNumber
|
|
373
|
+
}
|
|
374
|
+
this.makeImpl(false, this.getBestMaskPattern())
|
|
375
|
+
},
|
|
376
|
+
makeImpl(test, maskPattern) {
|
|
377
|
+
this.moduleCount = this.typeNumber * 4 + 17
|
|
378
|
+
this.modules = new Array(this.moduleCount)
|
|
379
|
+
for (let row = 0; row < this.moduleCount; row++) {
|
|
380
|
+
this.modules[row] = new Array(this.moduleCount)
|
|
381
|
+
for (let col = 0; col < this.moduleCount; col++) this.modules[row][col] = null
|
|
382
|
+
}
|
|
383
|
+
this.setupPositionProbePattern(0, 0)
|
|
384
|
+
this.setupPositionProbePattern(this.moduleCount - 7, 0)
|
|
385
|
+
this.setupPositionProbePattern(0, this.moduleCount - 7)
|
|
386
|
+
this.setupPositionAdjustPattern()
|
|
387
|
+
this.setupTimingPattern()
|
|
388
|
+
this.setupTypeInfo(test, maskPattern)
|
|
389
|
+
if (this.typeNumber >= 7) this.setupTypeNumber(test)
|
|
390
|
+
if (this.dataCache === null) this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList)
|
|
391
|
+
this.mapData(this.dataCache, maskPattern)
|
|
392
|
+
},
|
|
393
|
+
setupPositionProbePattern(row, col) {
|
|
394
|
+
for (let r = -1; r <= 7; r++) {
|
|
395
|
+
if (row + r <= -1 || this.moduleCount <= row + r) continue
|
|
396
|
+
for (let c = -1; c <= 7; c++) {
|
|
397
|
+
if (col + c <= -1 || this.moduleCount <= col + c) continue
|
|
398
|
+
if ((r >= 0 && r <= 6 && (c === 0 || c === 6))
|
|
399
|
+
|| (c >= 0 && c <= 6 && (r === 0 || r === 6))
|
|
400
|
+
|| (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {
|
|
401
|
+
this.modules[row + r][col + c] = true
|
|
402
|
+
} else {
|
|
403
|
+
this.modules[row + r][col + c] = false
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
getBestMaskPattern() {
|
|
409
|
+
let minLostPoint = 0
|
|
410
|
+
let pattern = 0
|
|
411
|
+
for (let i = 0; i < 8; i++) {
|
|
412
|
+
this.makeImpl(true, i)
|
|
413
|
+
const lostPoint = QRUtil.getLostPoint(this)
|
|
414
|
+
if (i === 0 || minLostPoint > lostPoint) {
|
|
415
|
+
minLostPoint = lostPoint
|
|
416
|
+
pattern = i
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return pattern
|
|
420
|
+
},
|
|
421
|
+
setupTimingPattern() {
|
|
422
|
+
for (let r = 8; r < this.moduleCount - 8; r++) {
|
|
423
|
+
if (this.modules[r][6] !== null) continue
|
|
424
|
+
this.modules[r][6] = r % 2 === 0
|
|
425
|
+
}
|
|
426
|
+
for (let c = 8; c < this.moduleCount - 8; c++) {
|
|
427
|
+
if (this.modules[6][c] !== null) continue
|
|
428
|
+
this.modules[6][c] = c % 2 === 0
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
setupPositionAdjustPattern() {
|
|
432
|
+
const pos = QRUtil.getPatternPosition(this.typeNumber)
|
|
433
|
+
for (let i = 0; i < pos.length; i++) {
|
|
434
|
+
for (let j = 0; j < pos.length; j++) {
|
|
435
|
+
const row = pos[i]
|
|
436
|
+
const col = pos[j]
|
|
437
|
+
if (this.modules[row][col] !== null) continue
|
|
438
|
+
for (let r = -2; r <= 2; r++) {
|
|
439
|
+
for (let c = -2; c <= 2; c++) {
|
|
440
|
+
if (Math.abs(r) === 2 || Math.abs(c) === 2 || (r === 0 && c === 0)) {
|
|
441
|
+
this.modules[row + r][col + c] = true
|
|
442
|
+
} else {
|
|
443
|
+
this.modules[row + r][col + c] = false
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
setupTypeNumber(test) {
|
|
451
|
+
const bits = QRUtil.getBCHTypeNumber(this.typeNumber)
|
|
452
|
+
for (let i = 0; i < 18; i++) {
|
|
453
|
+
const mod = !test && ((bits >> i) & 1) === 1
|
|
454
|
+
this.modules[Math.floor(i / 3)][(i % 3) + this.moduleCount - 8 - 3] = mod
|
|
455
|
+
}
|
|
456
|
+
for (let x = 0; x < 18; x++) {
|
|
457
|
+
const mod = !test && ((bits >> x) & 1) === 1
|
|
458
|
+
this.modules[(x % 3) + this.moduleCount - 8 - 3][Math.floor(x / 3)] = mod
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
setupTypeInfo(test, maskPattern) {
|
|
462
|
+
const data = (this.errorCorrectLevel << 3) | maskPattern
|
|
463
|
+
const bits = QRUtil.getBCHTypeInfo(data)
|
|
464
|
+
for (let v = 0; v < 15; v++) {
|
|
465
|
+
const mod = !test && ((bits >> v) & 1) === 1
|
|
466
|
+
if (v < 6) this.modules[v][8] = mod
|
|
467
|
+
else if (v < 8) this.modules[v + 1][8] = mod
|
|
468
|
+
else this.modules[this.moduleCount - 15 + v][8] = mod
|
|
469
|
+
}
|
|
470
|
+
for (let h = 0; h < 15; h++) {
|
|
471
|
+
const mod = !test && ((bits >> h) & 1) === 1
|
|
472
|
+
if (h < 8) this.modules[8][this.moduleCount - h - 1] = mod
|
|
473
|
+
else if (h < 9) this.modules[8][15 - h - 1 + 1] = mod
|
|
474
|
+
else this.modules[8][15 - h - 1] = mod
|
|
475
|
+
}
|
|
476
|
+
this.modules[this.moduleCount - 8][8] = !test
|
|
477
|
+
},
|
|
478
|
+
mapData(data, maskPattern) {
|
|
479
|
+
let inc = -1
|
|
480
|
+
let row = this.moduleCount - 1
|
|
481
|
+
let bitIndex = 7
|
|
482
|
+
let byteIndex = 0
|
|
483
|
+
for (let col = this.moduleCount - 1; col > 0; col -= 2) {
|
|
484
|
+
if (col === 6) col--
|
|
485
|
+
while (true) {
|
|
486
|
+
for (let c = 0; c < 2; c++) {
|
|
487
|
+
if (this.modules[row][col - c] === null) {
|
|
488
|
+
let dark = false
|
|
489
|
+
if (byteIndex < data.length) dark = ((data[byteIndex] >>> bitIndex) & 1) === 1
|
|
490
|
+
const mask = QRUtil.getMask(maskPattern, row, col - c)
|
|
491
|
+
if (mask) dark = !dark
|
|
492
|
+
this.modules[row][col - c] = dark
|
|
493
|
+
bitIndex--
|
|
494
|
+
if (bitIndex === -1) { byteIndex++; bitIndex = 7 }
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
row += inc
|
|
498
|
+
if (row < 0 || this.moduleCount <= row) {
|
|
499
|
+
row -= inc
|
|
500
|
+
inc = -inc
|
|
501
|
+
break
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
}
|
|
507
|
+
QRCode.PAD0 = 0xEC
|
|
508
|
+
QRCode.PAD1 = 0x11
|
|
509
|
+
QRCode.createData = function (typeNumber, errorCorrectLevel, dataList) {
|
|
510
|
+
const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel)
|
|
511
|
+
const buffer = new QRBitBuffer()
|
|
512
|
+
for (let i = 0; i < dataList.length; i++) {
|
|
513
|
+
const data = dataList[i]
|
|
514
|
+
buffer.put(data.mode, 4)
|
|
515
|
+
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber))
|
|
516
|
+
data.write(buffer)
|
|
517
|
+
}
|
|
518
|
+
let totalDataCount = 0
|
|
519
|
+
for (let x = 0; x < rsBlocks.length; x++) totalDataCount += rsBlocks[x].dataCount
|
|
520
|
+
if (buffer.getLengthInBits() > totalDataCount * 8) {
|
|
521
|
+
throw new Error(`code length overflow. (${buffer.getLengthInBits()}>${totalDataCount * 8})`)
|
|
522
|
+
}
|
|
523
|
+
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) buffer.put(0, 4)
|
|
524
|
+
while (buffer.getLengthInBits() % 8 !== 0) buffer.putBit(false)
|
|
525
|
+
while (true) {
|
|
526
|
+
if (buffer.getLengthInBits() >= totalDataCount * 8) break
|
|
527
|
+
buffer.put(QRCode.PAD0, 8)
|
|
528
|
+
if (buffer.getLengthInBits() >= totalDataCount * 8) break
|
|
529
|
+
buffer.put(QRCode.PAD1, 8)
|
|
530
|
+
}
|
|
531
|
+
return QRCode.createBytes(buffer, rsBlocks)
|
|
532
|
+
}
|
|
533
|
+
QRCode.createBytes = function (buffer, rsBlocks) {
|
|
534
|
+
let offset = 0
|
|
535
|
+
let maxDcCount = 0
|
|
536
|
+
let maxEcCount = 0
|
|
537
|
+
const dcdata = new Array(rsBlocks.length)
|
|
538
|
+
const ecdata = new Array(rsBlocks.length)
|
|
539
|
+
for (let r = 0; r < rsBlocks.length; r++) {
|
|
540
|
+
const dcCount = rsBlocks[r].dataCount
|
|
541
|
+
const ecCount = rsBlocks[r].totalCount - dcCount
|
|
542
|
+
maxDcCount = Math.max(maxDcCount, dcCount)
|
|
543
|
+
maxEcCount = Math.max(maxEcCount, ecCount)
|
|
544
|
+
dcdata[r] = new Array(dcCount)
|
|
545
|
+
for (let i = 0; i < dcdata[r].length; i++) dcdata[r][i] = 0xff & buffer.buffer[i + offset]
|
|
546
|
+
offset += dcCount
|
|
547
|
+
const rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount)
|
|
548
|
+
const rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1)
|
|
549
|
+
const modPoly = rawPoly.mod(rsPoly)
|
|
550
|
+
ecdata[r] = new Array(rsPoly.getLength() - 1)
|
|
551
|
+
for (let x = 0; x < ecdata[r].length; x++) {
|
|
552
|
+
const modIndex = x + modPoly.getLength() - ecdata[r].length
|
|
553
|
+
ecdata[r][x] = modIndex >= 0 ? modPoly.get(modIndex) : 0
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
let totalCodeCount = 0
|
|
557
|
+
for (let y = 0; y < rsBlocks.length; y++) totalCodeCount += rsBlocks[y].totalCount
|
|
558
|
+
const data = new Array(totalCodeCount)
|
|
559
|
+
let index = 0
|
|
560
|
+
for (let z = 0; z < maxDcCount; z++) {
|
|
561
|
+
for (let s = 0; s < rsBlocks.length; s++) {
|
|
562
|
+
if (z < dcdata[s].length) data[index++] = dcdata[s][z]
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
for (let xx = 0; xx < maxEcCount; xx++) {
|
|
566
|
+
for (let t = 0; t < rsBlocks.length; t++) {
|
|
567
|
+
if (xx < ecdata[t].length) data[index++] = ecdata[t][xx]
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return data
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Encode `text` into a QR matrix. Returns the module count and a count×count
|
|
575
|
+
* grid of 0/1 cells (row-major) for the browser to render.
|
|
576
|
+
* @param {string} text - payload to encode (8-bit byte mode).
|
|
577
|
+
* @returns {{ count: number, modules: number[][] }}
|
|
578
|
+
*/
|
|
579
|
+
export function encodeQrMatrix(text) {
|
|
580
|
+
const qr = new QRCode(-1, QRErrorCorrectLevel.L)
|
|
581
|
+
qr.addData(text)
|
|
582
|
+
qr.make()
|
|
583
|
+
const count = qr.getModuleCount()
|
|
584
|
+
const modules = []
|
|
585
|
+
for (let r = 0; r < count; r++) {
|
|
586
|
+
const row = []
|
|
587
|
+
for (let c = 0; c < count; c++) row.push(qr.isDark(r, c) ? 1 : 0)
|
|
588
|
+
modules.push(row)
|
|
589
|
+
}
|
|
590
|
+
return { count, modules }
|
|
591
|
+
}
|