@iyexin/mio-android-tools 0.0.0-stage → 0.1.1
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 +30 -0
- package/README.md +86 -2
- package/dist/apk.d.ts +23 -0
- package/dist/apk.js +109 -0
- package/dist/apk.js.map +1 -0
- package/dist/apksigner.d.ts +48 -0
- package/dist/apksigner.js +158 -0
- package/dist/apksigner.js.map +1 -0
- package/dist/axml.d.ts +36 -0
- package/dist/axml.js +248 -0
- package/dist/axml.js.map +1 -0
- package/dist/discover.d.ts +33 -0
- package/dist/discover.js +239 -0
- package/dist/discover.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/exec.d.ts +17 -0
- package/dist/exec.js +67 -0
- package/dist/exec.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/keystore.d.ts +22 -0
- package/dist/keystore.js +65 -0
- package/dist/keystore.js.map +1 -0
- package/dist/signing.d.ts +28 -0
- package/dist/signing.js +72 -0
- package/dist/signing.js.map +1 -0
- package/dist/tool-bundle.d.ts +47 -0
- package/dist/tool-bundle.js +204 -0
- package/dist/tool-bundle.js.map +1 -0
- package/dist/windows.d.ts +22 -0
- package/dist/windows.js +74 -0
- package/dist/windows.js.map +1 -0
- package/dist/zip.d.ts +12 -0
- package/dist/zip.js +100 -0
- package/dist/zip.js.map +1 -0
- package/dist/zipalign.d.ts +17 -0
- package/dist/zipalign.js +36 -0
- package/dist/zipalign.js.map +1 -0
- package/package.json +55 -3
package/dist/windows.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
import pngToIco from "png-to-ico";
|
|
4
|
+
import { NtExecutable, NtExecutableResource, Resource, Data } from "resedit";
|
|
5
|
+
/**
|
|
6
|
+
* Inject app.asar as an RT_RCDATA resource into a Windows executable.
|
|
7
|
+
*
|
|
8
|
+
* The Flutter shell reads it with FindResourceW/LoadResource. This does not
|
|
9
|
+
* sign the executable; Authenticode must be applied after injection.
|
|
10
|
+
*/
|
|
11
|
+
export async function injectWindowsExe(options) {
|
|
12
|
+
const exeBuffer = await readFile(options.templateExe);
|
|
13
|
+
const asar = await readFile(options.asar);
|
|
14
|
+
if (asar.length === 0)
|
|
15
|
+
throw new Error("app.asar is empty");
|
|
16
|
+
const executable = NtExecutable.from(exeBuffer, { ignoreCert: true });
|
|
17
|
+
const resources = NtExecutableResource.from(executable);
|
|
18
|
+
const bin = asar.buffer.slice(asar.byteOffset, asar.byteOffset + asar.byteLength);
|
|
19
|
+
resources.replaceResourceEntry({
|
|
20
|
+
type: 10, // RT_RCDATA
|
|
21
|
+
id: options.resourceName ?? "MIO_ASAR",
|
|
22
|
+
lang: options.language ?? 1033,
|
|
23
|
+
codepage: 0,
|
|
24
|
+
bin,
|
|
25
|
+
});
|
|
26
|
+
if (options.appName || options.version) {
|
|
27
|
+
const versions = Resource.VersionInfo.fromEntries(resources.entries);
|
|
28
|
+
const oldEntries = resources.entries.filter((entry) => entry.type === 16);
|
|
29
|
+
for (const version of versions) {
|
|
30
|
+
if (options.version) {
|
|
31
|
+
version.setFileVersion(options.version, 1033);
|
|
32
|
+
version.setProductVersion(options.version, 1033);
|
|
33
|
+
}
|
|
34
|
+
if (options.appName) {
|
|
35
|
+
const values = {
|
|
36
|
+
ProductName: options.appName,
|
|
37
|
+
FileDescription: options.appName,
|
|
38
|
+
};
|
|
39
|
+
version.setStringValues({ lang: 1033, codepage: 1200 }, values, true);
|
|
40
|
+
// Some Windows shell APIs read the legacy ANSI table in preference to
|
|
41
|
+
// the Unicode table. Keep both tables in sync.
|
|
42
|
+
version.setStringValues({ lang: 1033, codepage: 1252 }, values, true);
|
|
43
|
+
}
|
|
44
|
+
if (options.version) {
|
|
45
|
+
const values = {
|
|
46
|
+
FileVersion: options.version,
|
|
47
|
+
ProductVersion: options.version,
|
|
48
|
+
};
|
|
49
|
+
version.setStringValues({ lang: 1033, codepage: 1200 }, values, true);
|
|
50
|
+
version.setStringValues({ lang: 1033, codepage: 1252 }, values, true);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const entry of oldEntries) {
|
|
54
|
+
resources.removeResourceEntry(16, entry.id, entry.lang);
|
|
55
|
+
}
|
|
56
|
+
for (const version of versions) {
|
|
57
|
+
version.outputToResourceEntries(resources.entries);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (options.icon) {
|
|
61
|
+
const ico = await pngToIco(options.icon);
|
|
62
|
+
const iconFile = Data.IconFile.from(ico);
|
|
63
|
+
const groups = Resource.IconGroupEntry.fromEntries(resources.entries);
|
|
64
|
+
const group = groups[0];
|
|
65
|
+
if (group) {
|
|
66
|
+
Resource.IconGroupEntry.replaceIconsForResource(resources.entries, group.id, group.lang, iconFile.icons.map((item) => item.data));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
resources.outputResource(executable);
|
|
70
|
+
const generated = executable.generate();
|
|
71
|
+
await writeFile(options.output, Buffer.from(generated));
|
|
72
|
+
return { output: options.output, asarBytes: asar.length };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=windows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows.js","sourceRoot":"","sources":["../src/windows.ts"],"names":[],"mappings":"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"}
|
package/dist/zip.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
/** Lists entry names in a zip, without extracting anything. */
|
|
3
|
+
export declare function listZipEntries(archive: string): Promise<string[]>;
|
|
4
|
+
/**
|
|
5
|
+
* Extracts a zip into `target`, rejecting entries that escape it.
|
|
6
|
+
*
|
|
7
|
+
* Templates are downloaded archives, so the path check is not optional.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractZip(archive: string, target: string): Promise<void>;
|
|
10
|
+
/** Extracts a single entry, or null when it is missing. */
|
|
11
|
+
export declare function readZipEntry(archive: string, wanted: string): Promise<Buffer | null>;
|
|
12
|
+
export { join as joinPath };
|
package/dist/zip.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createWriteStream } from "node:fs";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { pipeline } from "node:stream/promises";
|
|
5
|
+
import yauzl from "yauzl";
|
|
6
|
+
/** Lists entry names in a zip, without extracting anything. */
|
|
7
|
+
export function listZipEntries(archive) {
|
|
8
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
9
|
+
yauzl.open(archive, { lazyEntries: true, autoClose: true }, (error, zip) => {
|
|
10
|
+
if (error || !zip) {
|
|
11
|
+
rejectPromise(error ?? new Error(`cannot open ${archive}`));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const names = [];
|
|
15
|
+
zip.on("error", rejectPromise);
|
|
16
|
+
zip.on("entry", (entry) => {
|
|
17
|
+
names.push(entry.fileName.replaceAll("\\", "/"));
|
|
18
|
+
zip.readEntry();
|
|
19
|
+
});
|
|
20
|
+
zip.on("end", () => resolvePromise(names));
|
|
21
|
+
zip.readEntry();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extracts a zip into `target`, rejecting entries that escape it.
|
|
27
|
+
*
|
|
28
|
+
* Templates are downloaded archives, so the path check is not optional.
|
|
29
|
+
*/
|
|
30
|
+
export async function extractZip(archive, target) {
|
|
31
|
+
await mkdir(target, { recursive: true });
|
|
32
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
33
|
+
yauzl.open(archive, { lazyEntries: true, autoClose: true }, (error, zip) => {
|
|
34
|
+
if (error || !zip) {
|
|
35
|
+
rejectPromise(error ?? new Error(`cannot open ${archive}`));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
zip.on("error", rejectPromise);
|
|
39
|
+
zip.on("end", () => resolvePromise());
|
|
40
|
+
zip.on("entry", (entry) => {
|
|
41
|
+
const name = entry.fileName;
|
|
42
|
+
if (name.endsWith("/")) {
|
|
43
|
+
mkdir(resolve(target, name), { recursive: true })
|
|
44
|
+
.then(() => zip.readEntry())
|
|
45
|
+
.catch(rejectPromise);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const destination = resolve(target, name);
|
|
49
|
+
const contained = relative(target, destination);
|
|
50
|
+
if (contained.startsWith("..") || contained.includes(":")) {
|
|
51
|
+
rejectPromise(new Error(`zip entry escapes the target directory: ${name}`));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
zip.openReadStream(entry, (streamError, stream) => {
|
|
55
|
+
if (streamError || !stream) {
|
|
56
|
+
rejectPromise(streamError ?? new Error(`cannot read ${name}`));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
mkdir(dirname(destination), { recursive: true })
|
|
60
|
+
.then(() => pipeline(stream, createWriteStream(destination)))
|
|
61
|
+
.then(() => zip.readEntry())
|
|
62
|
+
.catch(rejectPromise);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
zip.readEntry();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Extracts a single entry, or null when it is missing. */
|
|
70
|
+
export function readZipEntry(archive, wanted) {
|
|
71
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
72
|
+
yauzl.open(archive, { lazyEntries: true, autoClose: true }, (error, zip) => {
|
|
73
|
+
if (error || !zip) {
|
|
74
|
+
rejectPromise(error ?? new Error(`cannot open ${archive}`));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
zip.on("error", rejectPromise);
|
|
78
|
+
zip.on("end", () => resolvePromise(null));
|
|
79
|
+
zip.on("entry", (entry) => {
|
|
80
|
+
if (entry.fileName.replaceAll("\\", "/") !== wanted) {
|
|
81
|
+
zip.readEntry();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
zip.openReadStream(entry, (streamError, stream) => {
|
|
85
|
+
if (streamError || !stream) {
|
|
86
|
+
rejectPromise(streamError ?? new Error(`cannot read ${wanted}`));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const chunks = [];
|
|
90
|
+
stream.on("data", (chunk) => chunks.push(chunk));
|
|
91
|
+
stream.on("error", rejectPromise);
|
|
92
|
+
stream.on("end", () => resolvePromise(Buffer.concat(chunks)));
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
zip.readEntry();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
export { join as joinPath };
|
|
100
|
+
//# sourceMappingURL=zip.js.map
|
package/dist/zip.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.js","sourceRoot":"","sources":["../src/zip.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AndroidTools } from "./discover.js";
|
|
2
|
+
export type PageSize = 4 | 16;
|
|
3
|
+
export interface AlignOptions {
|
|
4
|
+
pageSize?: PageSize;
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface AlignmentCheck {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
raw: string;
|
|
10
|
+
exitCode: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Run zipalign before signing. apksigner does not align; Android 15+ needs
|
|
14
|
+
* 16 KiB-aligned native libraries, hence the explicit page size.
|
|
15
|
+
*/
|
|
16
|
+
export declare function alignApk(tools: AndroidTools, input: string, output: string, options?: AlignOptions): Promise<void>;
|
|
17
|
+
export declare function checkAlignment(tools: AndroidTools, apk: string, options?: AlignOptions): Promise<AlignmentCheck>;
|
package/dist/zipalign.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { MioToolError } from "./errors.js";
|
|
2
|
+
import { run } from "./exec.js";
|
|
3
|
+
function pageArgs(pageSize) {
|
|
4
|
+
if (pageSize === 16)
|
|
5
|
+
return ["-P", "16"];
|
|
6
|
+
// Default zipalign page alignment (4 KiB).
|
|
7
|
+
return ["-p"];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Run zipalign before signing. apksigner does not align; Android 15+ needs
|
|
11
|
+
* 16 KiB-aligned native libraries, hence the explicit page size.
|
|
12
|
+
*/
|
|
13
|
+
export async function alignApk(tools, input, output, options = {}) {
|
|
14
|
+
const args = ["-f", ...pageArgs(options.pageSize)];
|
|
15
|
+
if (options.verbose)
|
|
16
|
+
args.push("-v");
|
|
17
|
+
args.push("4", input, output);
|
|
18
|
+
const result = await run(tools.zipalign, args, { timeoutMs: 120_000 });
|
|
19
|
+
if (result.code !== 0) {
|
|
20
|
+
throw new MioToolError("ZIPALIGN_FAILED", "zipalign failed", {
|
|
21
|
+
stdout: result.stdout,
|
|
22
|
+
stderr: result.stderr,
|
|
23
|
+
details: `exit code ${result.code}`,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function checkAlignment(tools, apk, options = {}) {
|
|
28
|
+
const args = ["-c", "-v", ...pageArgs(options.pageSize), "4", apk];
|
|
29
|
+
const result = await run(tools.zipalign, args, { timeoutMs: 120_000 });
|
|
30
|
+
return {
|
|
31
|
+
ok: result.code === 0,
|
|
32
|
+
raw: `${result.stdout}${result.stderr}`,
|
|
33
|
+
exitCode: result.code,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=zipalign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zipalign.js","sourceRoot":"","sources":["../src/zipalign.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAgBhC,SAAS,QAAQ,CAAC,QAA8B;IAC9C,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,2CAA2C;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAmB,EACnB,KAAa,EACb,MAAc,EACd,UAAwB,EAAE;IAE1B,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,IAAI,OAAO,CAAC,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAE9B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,YAAY,CAAC,iBAAiB,EAAE,iBAAiB,EAAE;YAC3D,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,aAAa,MAAM,CAAC,IAAI,EAAE;SACpC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAmB,EACnB,GAAW,EACX,UAAwB,EAAE;IAE1B,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC;QACrB,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE;QACvC,QAAQ,EAAE,MAAM,CAAC,IAAI;KACtB,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyexin/mio-android-tools",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Android APK alignment, signing and verification for Mio",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"png-to-ico": "^3.0.2",
|
|
21
|
+
"resedit": "^3.1.0",
|
|
22
|
+
"sharp": "^0.35.5",
|
|
23
|
+
"tar": "^7.5.22",
|
|
24
|
+
"undici": "^8.12.4",
|
|
25
|
+
"yauzl": "^3.4.0",
|
|
26
|
+
"yazl": "^3.3.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/yauzl": "^3.4.0",
|
|
30
|
+
"@types/yazl": "^3.3.1"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/iYeXin/Mio.git",
|
|
36
|
+
"directory": "packages/android-tools"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/iYeXin/Mio#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/iYeXin/Mio/issues"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"mio",
|
|
44
|
+
"flutter",
|
|
45
|
+
"webview",
|
|
46
|
+
"web-app",
|
|
47
|
+
"android",
|
|
48
|
+
"windows"
|
|
49
|
+
],
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc -p tsconfig.json",
|
|
55
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
56
|
+
"test": "node --import tsx --test test/apksigner.test.ts test/discovery.test.ts test/signing.test.ts test/tool-bundle.test.ts"
|
|
57
|
+
}
|
|
6
58
|
}
|