fast-cocos 1.1.2 → 1.1.3
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/dist/xor/src/index.js +6 -8
- package/dist/xor/src/xor.js +37 -92
- package/package.json +1 -1
package/dist/xor/src/index.js
CHANGED
|
@@ -18,7 +18,7 @@ function main() {
|
|
|
18
18
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
commander_1.program
|
|
20
20
|
.name("xor")
|
|
21
|
-
.description("XOR
|
|
21
|
+
.description("XOR 图片文件加解密(输出与源文件同名,建议加密到单独目录)")
|
|
22
22
|
.version(xor_1.XOR_VERSION)
|
|
23
23
|
.argument("<mode>", "encrypt 或 decrypt", (v) => {
|
|
24
24
|
if (v !== "encrypt" && v !== "decrypt") {
|
|
@@ -27,17 +27,16 @@ function main() {
|
|
|
27
27
|
return v;
|
|
28
28
|
})
|
|
29
29
|
.argument("<input>", "输入文件或目录路径")
|
|
30
|
-
.argument("[output]", "
|
|
30
|
+
.argument("[output]", "输出文件或目录(可选;目录时写入同名文件)")
|
|
31
31
|
.option("-s, --sign <sign>", "签名", xor_1.DEFAULT_SIGN)
|
|
32
32
|
.option("-k, --key <key>", "密钥", xor_1.DEFAULT_KEY)
|
|
33
|
-
.option("
|
|
34
|
-
.option("--ext <list>", "批量处理时的扩展名列表,逗号分隔(解密时默认会包含加密后缀对应扩展)")
|
|
33
|
+
.option("--ext <list>", "批量处理时的扩展名列表,逗号分隔")
|
|
35
34
|
.addHelpText("after", `
|
|
36
35
|
示例:
|
|
37
|
-
fast-cocos xor encrypt
|
|
38
|
-
fast-cocos xor encrypt
|
|
36
|
+
fast-cocos xor encrypt a.png
|
|
37
|
+
fast-cocos xor encrypt a.png ./encrypted/
|
|
38
|
+
fast-cocos xor decrypt ./encrypted/a.png
|
|
39
39
|
fast-cocos xor encrypt ./assets/ ./out/ --ext .png,.jpg
|
|
40
|
-
fast-cocos xor decrypt ./out/sprite.enc -e .enc
|
|
41
40
|
`)
|
|
42
41
|
.action((mode, input, output) => {
|
|
43
42
|
const o = commander_1.program.opts();
|
|
@@ -47,7 +46,6 @@ function main() {
|
|
|
47
46
|
output,
|
|
48
47
|
sign: o.sign,
|
|
49
48
|
key: o.key,
|
|
50
|
-
encryptedFileSuffix: o.encryptedSuffix,
|
|
51
49
|
extensionsCsv: o.ext
|
|
52
50
|
});
|
|
53
51
|
});
|
package/dist/xor/src/xor.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.XOR_VERSION = exports.DEFAULT_IMAGE_EXTS = exports.DEFAULT_KEY = exports.DEFAULT_SIGN = void 0;
|
|
7
7
|
exports.xorTransform = xorTransform;
|
|
8
8
|
exports.encryptFile = encryptFile;
|
|
9
9
|
exports.decryptFile = decryptFile;
|
|
@@ -15,11 +15,9 @@ const path_1 = __importDefault(require("path"));
|
|
|
15
15
|
exports.DEFAULT_SIGN = "CrP3";
|
|
16
16
|
/** 默认密钥(16 字节) */
|
|
17
17
|
exports.DEFAULT_KEY = "Xk9#mQ2$vL5@nR8w";
|
|
18
|
-
/**
|
|
18
|
+
/** 默认参与批量处理的图片扩展名 */
|
|
19
19
|
exports.DEFAULT_IMAGE_EXTS = [".png", ".jpg", ".jpeg", ".webp", ".bmp"];
|
|
20
20
|
exports.XOR_VERSION = "1.0.0";
|
|
21
|
-
/** 默认加密输出文件名后缀(如 sprite.png -> sprite.enc) */
|
|
22
|
-
exports.DEFAULT_ENCRYPTED_FILE_SUFFIX = ".enc";
|
|
23
21
|
/**
|
|
24
22
|
* XOR 加密/解密(对称)
|
|
25
23
|
*/
|
|
@@ -33,24 +31,21 @@ function xorTransform(opts) {
|
|
|
33
31
|
return result;
|
|
34
32
|
}
|
|
35
33
|
/**
|
|
36
|
-
* 加密文件(签名头 + XOR
|
|
34
|
+
* 加密文件(签名头 + XOR),输出文件名与源文件 basename 相同(通常配合输出目录使用)
|
|
37
35
|
*/
|
|
38
36
|
function encryptFile(opts) {
|
|
39
|
-
var _a, _b, _c
|
|
37
|
+
var _a, _b, _c;
|
|
40
38
|
const finalSign = (_a = opts.sign) !== null && _a !== void 0 ? _a : exports.DEFAULT_SIGN;
|
|
41
39
|
const finalKey = (_b = opts.key) !== null && _b !== void 0 ? _b : exports.DEFAULT_KEY;
|
|
42
|
-
|
|
43
|
-
let out = (_d = opts.outputPath) !== null && _d !== void 0 ? _d : null;
|
|
40
|
+
let out = (_c = opts.outputPath) !== null && _c !== void 0 ? _c : null;
|
|
44
41
|
if (!out) {
|
|
45
|
-
out =
|
|
42
|
+
out = opts.inputPath;
|
|
46
43
|
}
|
|
47
44
|
else if (out.endsWith("/") || out.endsWith(path_1.default.sep)) {
|
|
48
|
-
|
|
49
|
-
out = path_1.default.join(out, stem + suffix);
|
|
45
|
+
out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
|
|
50
46
|
}
|
|
51
47
|
else if (fs_1.default.existsSync(out) && fs_1.default.statSync(out).isDirectory()) {
|
|
52
|
-
|
|
53
|
-
out = path_1.default.join(out, stem + suffix);
|
|
48
|
+
out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
|
|
54
49
|
}
|
|
55
50
|
if (out === null) {
|
|
56
51
|
throw new Error("输出路径解析失败");
|
|
@@ -68,23 +63,18 @@ function encryptFile(opts) {
|
|
|
68
63
|
* @returns 签名不匹配时为 false
|
|
69
64
|
*/
|
|
70
65
|
function decryptFile(opts) {
|
|
71
|
-
var _a, _b, _c
|
|
66
|
+
var _a, _b, _c;
|
|
72
67
|
const finalSign = (_a = opts.sign) !== null && _a !== void 0 ? _a : exports.DEFAULT_SIGN;
|
|
73
68
|
const finalKey = (_b = opts.key) !== null && _b !== void 0 ? _b : exports.DEFAULT_KEY;
|
|
74
|
-
|
|
75
|
-
let out = (_d = opts.outputPath) !== null && _d !== void 0 ? _d : null;
|
|
69
|
+
let out = (_c = opts.outputPath) !== null && _c !== void 0 ? _c : null;
|
|
76
70
|
if (!out) {
|
|
77
|
-
out =
|
|
71
|
+
out = opts.inputPath;
|
|
78
72
|
}
|
|
79
73
|
else if (out.endsWith("/") || out.endsWith(path_1.default.sep)) {
|
|
80
|
-
|
|
81
|
-
const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(opts.inputPath, path_1.default.extname(opts.inputPath));
|
|
82
|
-
out = path_1.default.join(out, stem);
|
|
74
|
+
out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
|
|
83
75
|
}
|
|
84
76
|
else if (fs_1.default.existsSync(out) && fs_1.default.statSync(out).isDirectory()) {
|
|
85
|
-
|
|
86
|
-
const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(opts.inputPath, path_1.default.extname(opts.inputPath));
|
|
87
|
-
out = path_1.default.join(out, stem);
|
|
77
|
+
out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
|
|
88
78
|
}
|
|
89
79
|
if (out === null) {
|
|
90
80
|
throw new Error("输出路径解析失败");
|
|
@@ -104,13 +94,12 @@ function decryptFile(opts) {
|
|
|
104
94
|
return true;
|
|
105
95
|
}
|
|
106
96
|
/**
|
|
107
|
-
*
|
|
97
|
+
* 递归批量处理目录(输出与源文件同名,仅目录可不同)
|
|
108
98
|
*/
|
|
109
99
|
function batchProcess(opts) {
|
|
110
|
-
var _a
|
|
100
|
+
var _a;
|
|
111
101
|
const { dirPath, mode, outputDir = null, sign = null, key = null } = opts;
|
|
112
|
-
const
|
|
113
|
-
const extensions = (_b = opts.extensions) !== null && _b !== void 0 ? _b : defaultExtensionsForMode(mode, suffix);
|
|
102
|
+
const extensions = (_a = opts.extensions) !== null && _a !== void 0 ? _a : defaultExtensionsForMode(mode);
|
|
114
103
|
if (!fs_1.default.existsSync(dirPath)) {
|
|
115
104
|
console.error(`目录不存在: ${dirPath}`);
|
|
116
105
|
return;
|
|
@@ -125,27 +114,20 @@ function batchProcess(opts) {
|
|
|
125
114
|
const stat = fs_1.default.statSync(fullPath);
|
|
126
115
|
if (stat.isDirectory()) {
|
|
127
116
|
const subOutputDir = outputDir ? path_1.default.join(outputDir, file) : null;
|
|
128
|
-
batchProcess({ dirPath: fullPath, mode, outputDir: subOutputDir, extensions, sign, key
|
|
117
|
+
batchProcess({ dirPath: fullPath, mode, outputDir: subOutputDir, extensions, sign, key });
|
|
129
118
|
}
|
|
130
119
|
else {
|
|
131
120
|
const ext = path_1.default.extname(file).toLowerCase();
|
|
132
121
|
if (!extensions.includes(ext)) {
|
|
133
122
|
continue;
|
|
134
123
|
}
|
|
135
|
-
|
|
124
|
+
const outputFile = outputDir ? path_1.default.join(outputDir, file) : fullPath;
|
|
136
125
|
if (mode === "encrypt") {
|
|
137
|
-
|
|
138
|
-
outputFile = outputDir ? path_1.default.join(outputDir, stem + suffix) : path_1.default.join(path_1.default.dirname(fullPath), stem + suffix);
|
|
139
|
-
encryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key, encryptedFileSuffix: suffix });
|
|
126
|
+
encryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key });
|
|
140
127
|
processedCount++;
|
|
141
128
|
}
|
|
142
|
-
else {
|
|
143
|
-
|
|
144
|
-
const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(file, ext);
|
|
145
|
-
outputFile = outputDir ? path_1.default.join(outputDir, stem) : path_1.default.join(path_1.default.dirname(fullPath), stem);
|
|
146
|
-
if (decryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key, encryptedFileSuffix: suffix })) {
|
|
147
|
-
processedCount++;
|
|
148
|
-
}
|
|
129
|
+
else if (decryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key })) {
|
|
130
|
+
processedCount++;
|
|
149
131
|
}
|
|
150
132
|
}
|
|
151
133
|
}
|
|
@@ -157,88 +139,51 @@ function batchProcess(opts) {
|
|
|
157
139
|
* 由 CLI 解析结果驱动:单文件或目录批量
|
|
158
140
|
*/
|
|
159
141
|
function runXorCommand(opts) {
|
|
160
|
-
var _a, _b, _c
|
|
142
|
+
var _a, _b, _c;
|
|
161
143
|
const { mode, input } = opts;
|
|
162
|
-
const
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
console.log(`\n使用配置: 签名="${sign}", 密钥="${key.substring(0, 4)}***", 加密后缀="${suffix}"`);
|
|
144
|
+
const sign = (_a = opts.sign) !== null && _a !== void 0 ? _a : exports.DEFAULT_SIGN;
|
|
145
|
+
const key = (_b = opts.key) !== null && _b !== void 0 ? _b : exports.DEFAULT_KEY;
|
|
146
|
+
const extensions = parseExtensionsCsv(opts.extensionsCsv, mode);
|
|
147
|
+
console.log(`\n使用配置: 签名="${sign}", 密钥="${key.substring(0, 4)}***"`);
|
|
167
148
|
const stats = fs_1.default.statSync(input);
|
|
168
149
|
if (stats.isFile()) {
|
|
169
150
|
let finalOutput = opts.output;
|
|
170
151
|
if (!finalOutput) {
|
|
171
|
-
|
|
172
|
-
finalOutput = defaultEncryptedOutputPath(input, suffix);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
finalOutput = defaultDecryptedOutputPath(input, suffix);
|
|
176
|
-
}
|
|
152
|
+
finalOutput = input;
|
|
177
153
|
}
|
|
178
154
|
else if (finalOutput.endsWith("/") || finalOutput.endsWith(path_1.default.sep)) {
|
|
179
|
-
|
|
180
|
-
const stem = path_1.default.basename(input, path_1.default.extname(input));
|
|
181
|
-
finalOutput = path_1.default.join(finalOutput, stem + suffix);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
const base = path_1.default.basename(input);
|
|
185
|
-
const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(input, path_1.default.extname(input));
|
|
186
|
-
finalOutput = path_1.default.join(finalOutput, stem);
|
|
187
|
-
}
|
|
155
|
+
finalOutput = path_1.default.join(finalOutput, path_1.default.basename(input));
|
|
188
156
|
}
|
|
189
157
|
else if (fs_1.default.existsSync(finalOutput) && fs_1.default.statSync(finalOutput).isDirectory()) {
|
|
190
|
-
|
|
191
|
-
const stem = path_1.default.basename(input, path_1.default.extname(input));
|
|
192
|
-
finalOutput = path_1.default.join(finalOutput, stem + suffix);
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
const base = path_1.default.basename(input);
|
|
196
|
-
const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(input, path_1.default.extname(input));
|
|
197
|
-
finalOutput = path_1.default.join(finalOutput, stem);
|
|
198
|
-
}
|
|
158
|
+
finalOutput = path_1.default.join(finalOutput, path_1.default.basename(input));
|
|
199
159
|
}
|
|
200
160
|
if (mode === "encrypt") {
|
|
201
|
-
encryptFile({ inputPath: input, outputPath: finalOutput, sign, key
|
|
161
|
+
encryptFile({ inputPath: input, outputPath: finalOutput, sign, key });
|
|
202
162
|
}
|
|
203
163
|
else {
|
|
204
|
-
decryptFile({ inputPath: input, outputPath: finalOutput, sign, key
|
|
164
|
+
decryptFile({ inputPath: input, outputPath: finalOutput, sign, key });
|
|
205
165
|
}
|
|
206
166
|
}
|
|
207
167
|
else if (stats.isDirectory()) {
|
|
208
168
|
batchProcess({
|
|
209
169
|
dirPath: input,
|
|
210
170
|
mode,
|
|
211
|
-
outputDir: (
|
|
171
|
+
outputDir: (_c = opts.output) !== null && _c !== void 0 ? _c : null,
|
|
212
172
|
extensions,
|
|
213
173
|
sign,
|
|
214
|
-
key
|
|
215
|
-
encryptedFileSuffix: suffix
|
|
174
|
+
key
|
|
216
175
|
});
|
|
217
176
|
}
|
|
218
177
|
}
|
|
219
|
-
function
|
|
220
|
-
const dir = path_1.default.dirname(inputPath);
|
|
221
|
-
const stem = path_1.default.basename(inputPath, path_1.default.extname(inputPath));
|
|
222
|
-
return path_1.default.join(dir, stem + suffix);
|
|
223
|
-
}
|
|
224
|
-
function defaultDecryptedOutputPath(inputPath, suffix) {
|
|
225
|
-
const dir = path_1.default.dirname(inputPath);
|
|
226
|
-
const base = path_1.default.basename(inputPath);
|
|
227
|
-
if (base.endsWith(suffix)) {
|
|
228
|
-
return path_1.default.join(dir, base.slice(0, -suffix.length));
|
|
229
|
-
}
|
|
230
|
-
return inputPath;
|
|
231
|
-
}
|
|
232
|
-
function defaultExtensionsForMode(mode, encryptedSuffix) {
|
|
178
|
+
function defaultExtensionsForMode(mode) {
|
|
233
179
|
if (mode === "decrypt") {
|
|
234
|
-
|
|
235
|
-
return [...set];
|
|
180
|
+
return [...exports.DEFAULT_IMAGE_EXTS];
|
|
236
181
|
}
|
|
237
182
|
return [...exports.DEFAULT_IMAGE_EXTS];
|
|
238
183
|
}
|
|
239
|
-
function parseExtensionsCsv(csv, mode
|
|
184
|
+
function parseExtensionsCsv(csv, mode) {
|
|
240
185
|
if (!csv || !csv.trim()) {
|
|
241
|
-
return defaultExtensionsForMode(mode
|
|
186
|
+
return defaultExtensionsForMode(mode);
|
|
242
187
|
}
|
|
243
188
|
return csv
|
|
244
189
|
.split(",")
|