networkwm-js 0.1.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 (57) hide show
  1. package/LICENSE +339 -0
  2. package/README.MD +110 -0
  3. package/dist/bytemanip.d.ts +12 -0
  4. package/dist/bytemanip.d.ts.map +1 -0
  5. package/dist/bytemanip.js +71 -0
  6. package/dist/database-abstraction.d.ts +39 -0
  7. package/dist/database-abstraction.d.ts.map +1 -0
  8. package/dist/database-abstraction.js +288 -0
  9. package/dist/databases.d.ts +85 -0
  10. package/dist/databases.d.ts.map +1 -0
  11. package/dist/databases.js +303 -0
  12. package/dist/devices.d.ts +6 -0
  13. package/dist/devices.d.ts.map +1 -0
  14. package/dist/devices.js +9 -0
  15. package/dist/encryption.d.ts +16 -0
  16. package/dist/encryption.d.ts.map +1 -0
  17. package/dist/encryption.js +123 -0
  18. package/dist/errors.d.ts +4 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +10 -0
  21. package/dist/filesystem/index.d.ts +2 -0
  22. package/dist/filesystem/index.d.ts.map +1 -0
  23. package/dist/filesystem/index.js +17 -0
  24. package/dist/filesystem/usb-mass-storage-webusb-filesystem.d.ts +44 -0
  25. package/dist/filesystem/usb-mass-storage-webusb-filesystem.d.ts.map +1 -0
  26. package/dist/filesystem/usb-mass-storage-webusb-filesystem.js +187 -0
  27. package/dist/functions.d.ts +12 -0
  28. package/dist/functions.d.ts.map +1 -0
  29. package/dist/functions.js +73 -0
  30. package/dist/helpers.d.ts +9 -0
  31. package/dist/helpers.d.ts.map +1 -0
  32. package/dist/helpers.js +47 -0
  33. package/dist/id3.d.ts +18 -0
  34. package/dist/id3.d.ts.map +1 -0
  35. package/dist/id3.js +137 -0
  36. package/dist/index.d.ts +10 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +28 -0
  39. package/dist/init-data.d.ts +16 -0
  40. package/dist/init-data.d.ts.map +1 -0
  41. package/dist/init-data.js +18 -0
  42. package/dist/initialization.d.ts +4 -0
  43. package/dist/initialization.d.ts.map +1 -0
  44. package/dist/initialization.js +32 -0
  45. package/dist/sort.d.ts +13 -0
  46. package/dist/sort.d.ts.map +1 -0
  47. package/dist/sort.js +62 -0
  48. package/dist/tables.d.ts +19 -0
  49. package/dist/tables.d.ts.map +1 -0
  50. package/dist/tables.js +101 -0
  51. package/dist/tagged-oma.d.ts +12 -0
  52. package/dist/tagged-oma.d.ts.map +1 -0
  53. package/dist/tagged-oma.js +175 -0
  54. package/dist/utils.d.ts +9 -0
  55. package/dist/utils.d.ts.map +1 -0
  56. package/dist/utils.js +90 -0
  57. package/package.json +43 -0
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.updateMetadata = exports.createTaggedEncryptedOMA = void 0;
7
+ const crypto_js_wasm_1 = __importDefault(require("@originjs/crypto-js-wasm"));
8
+ const himd_js_1 = require("himd-js");
9
+ const utils_1 = require("./utils");
10
+ const id3_1 = require("./id3");
11
+ const encryption_1 = require("./encryption");
12
+ const textEncoder = new TextEncoder();
13
+ const PHONY_CID = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x50, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xA9, 0xC1, 0x6A, 0x81, 0x6A, 0x87, 0xDA, 0xAD, 0x4B, 0xA2, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
14
+ const EKB1001D_CONTENTS = new Uint8Array([0x45, 0x4B, 0x42, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x39, 0x47, 0xF4, 0x0A, 0x33, 0x65, 0x2F, 0x98, 0x71, 0x73, 0xC3, 0x98, 0x68, 0xC5, 0x23, 0x5B, 0x84, 0x20, 0xC8, 0xCF, 0xFB, 0x0E, 0x7F, 0x4E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x34, 0x85, 0x14, 0x51, 0x45, 0x04, 0x02, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x36, 0xD2, 0x00, 0x38, 0x74, 0x91, 0x51, 0x9D, 0xA7, 0x75, 0x94, 0x70, 0xA0, 0x17, 0x69, 0xDA, 0x69, 0x55, 0xAE, 0xA6, 0x9F, 0x6A, 0x3E, 0x69, 0x18, 0xC7, 0xC6, 0xBB, 0xD7, 0xCC, 0xFB, 0x1B, 0x81, 0x8D, 0xA9, 0x97, 0x90, 0x67, 0x29, 0x5C, 0xB7, 0x55, 0x5A, 0xEC, 0x21, 0x1B, 0x9E, 0xBD, 0xD4, 0x7E, 0xD9, 0x09, 0x79, 0xE0, 0x39, 0xA1, 0xE0, 0x76, 0x68, 0x0D, 0xB8, 0xBF, 0xED, 0xB0, 0xD3, 0x24, 0x26, 0xB8, 0xF7, 0x79, 0x22, 0xBD, 0x46, 0xC9, 0x44, 0x9F, 0xDF, 0x01, 0x74, 0xC0, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x28, 0xDB, 0x54, 0x6A, 0xC5, 0xE0, 0x4D, 0x4F, 0xCB, 0xF2, 0x46, 0x3B, 0x01, 0xDE, 0x2C, 0xD0, 0xFB, 0xAF, 0x7A, 0xA7, 0x1E, 0xEF, 0x44, 0x29, 0x05, 0x97, 0x9D, 0xBE, 0xE7, 0x28, 0x4E, 0xA4, 0x53, 0x3A, 0x2F, 0x71, 0xC7, 0xCB, 0x86, 0x58, 0x39]);
15
+ function encodeSonyWeirdString(type, data) {
16
+ return (0, utils_1.concatUint8Arrays)([
17
+ (0, id3_1.encodeUTF16BEStringEA3)(type),
18
+ new Uint8Array([0, 0]),
19
+ (0, id3_1.encodeUTF16BEStringEA3)(data, false),
20
+ ]);
21
+ }
22
+ function createSonyGEOB(geobName, header, kvmap) {
23
+ // Header:
24
+ const dataSlices = [
25
+ new Uint8Array([0x02]),
26
+ textEncoder.encode("binary"),
27
+ new Uint8Array([0, 0, 0]),
28
+ (0, id3_1.encodeUTF16BEStringEA3)(geobName, false),
29
+ new Uint8Array([0, 0]),
30
+ header,
31
+ ];
32
+ // KVs:
33
+ for (let val of kvmap) {
34
+ const name = textEncoder.encode(val.name.padEnd(12, ' '));
35
+ dataSlices.push(name, new Uint8Array([0, val.chunkLen, 0, val.chunks]), val.contents);
36
+ }
37
+ return (0, utils_1.concatUint8Arrays)(dataSlices);
38
+ }
39
+ function createEncryptionHeader(titleInfo, milliseconds) {
40
+ const verificationKey = (0, utils_1.createRandomBytes)(8);
41
+ const actualTrackKey = (0, utils_1.createRandomBytes)(8);
42
+ // In every KEYRING section, the track key is stored as decrypted by the verification key decrypted by the ekbroot
43
+ const padding = (0, utils_1.createRandomBytes)(8); // What's this???
44
+ const keyringDataA = (0, utils_1.concatUint8Arrays)([
45
+ new Uint8Array([
46
+ 0x00, 0x28, 0x00, 0x01,
47
+ 0x00, 0x03, 0x00, 0x00,
48
+ 0x00, 0x00, 0x00, 0x00,
49
+ 0x00, 0x01, 0x00, 0x21,
50
+ ]),
51
+ verificationKey, (0, encryption_1.createTrackKeyForKeyring)(0x00010021, verificationKey, actualTrackKey), padding,
52
+ new Uint8Array(8).fill(0),
53
+ ]);
54
+ const firstGEOBContents = createSonyGEOB("OMG_ULINF", new Uint8Array(), [
55
+ { name: 'KEYRING', chunkLen: 0x10, chunks: 0x03, contents: keyringDataA },
56
+ { name: '!CID', chunkLen: 0x10, chunks: 0x02, contents: PHONY_CID },
57
+ { name: '!REFID', chunkLen: 0x10, chunks: 0x01, contents: new Uint8Array([0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) },
58
+ { name: 'PLEASE', chunkLen: 0x10, chunks: 0x02, contents: textEncoder.encode("don't do DRM - it's bad for you.") }
59
+ ]);
60
+ const verificationKeyCA = crypto_js_wasm_1.default.lib.CipherParams.create({
61
+ ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(verificationKey),
62
+ });
63
+ const decryptedVerificationKeyWaA = crypto_js_wasm_1.default.TripleDES.decrypt(verificationKeyCA, crypto_js_wasm_1.default.lib.WordArray.create(encryption_1.EKBROOTS[0x00010021]), { mode: crypto_js_wasm_1.default.mode.ECB });
64
+ const maclistVerifiedData = firstGEOBContents.slice(94); // Offset to '!CID'
65
+ const maclistValue = (0, encryption_1.createTrackMac2)(decryptedVerificationKeyWaA, maclistVerifiedData);
66
+ const keyringDataB = (0, utils_1.concatUint8Arrays)([
67
+ new Uint8Array([0x00, 0x28, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1D]),
68
+ verificationKey, (0, encryption_1.createTrackKeyForKeyring)(0x0001001D, verificationKey, actualTrackKey), padding,
69
+ new Uint8Array(8).fill(0),
70
+ EKB1001D_CONTENTS,
71
+ ]);
72
+ let secondGEOBContents = createSonyGEOB("OMG_BKLSI", new Uint8Array([0x00, 0x01, 0x00, 0x40, 0x00, 0xDC, 0x00, 0x70, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), [
73
+ { name: 'KEYRING', chunkLen: 0x10, chunks: 0x03, contents: keyringDataB },
74
+ { name: '!CID', chunkLen: 0x10, chunks: 0x02, contents: PHONY_CID },
75
+ { name: 'SHARE_P_SID', chunkLen: 0x10, chunks: 0x01, contents: new Uint8Array([0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0xE3, 0x22, 0xB5, 0x46, 0x89, 0xED, 0x10]) },
76
+ { name: '!REFID', chunkLen: 0x10, chunks: 0x01, contents: new Uint8Array([0x01, 0x01, 0x00, 0x00, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) },
77
+ ]);
78
+ const verificationKeyC = crypto_js_wasm_1.default.lib.CipherParams.create({
79
+ ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(verificationKey),
80
+ });
81
+ const decryptedVerificationKeyWa = crypto_js_wasm_1.default.TripleDES.decrypt(verificationKeyC, crypto_js_wasm_1.default.lib.WordArray.create(encryption_1.EKBROOTS[0x0001001D]), { mode: crypto_js_wasm_1.default.mode.ECB });
82
+ const cbcMac = (0, encryption_1.createTrackMac2)(decryptedVerificationKeyWa, secondGEOBContents.subarray(0x14a));
83
+ // Merge the CBC-MAC into the GEOB
84
+ secondGEOBContents = (0, utils_1.concatUint8Arrays)([secondGEOBContents, cbcMac, new Uint8Array(8).fill(0)]);
85
+ const id3Info = {
86
+ flags: 0,
87
+ version: { major: 3, minor: 0 },
88
+ tags: [
89
+ { id: "GEOB", contents: firstGEOBContents, flags: 0 },
90
+ { id: "TIT2", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.title), flags: 0 },
91
+ { id: "TPE1", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.artist), flags: 0 },
92
+ { id: "TALB", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.album), flags: 0 },
93
+ { id: "TALB", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.album), flags: 0 },
94
+ { id: "TCON", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.genre), flags: 0 },
95
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_TPE1S", titleInfo.artist), flags: 0 },
96
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_TRACK", '0'), flags: 0 },
97
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_ALBMS", titleInfo.album), flags: 0 },
98
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_TIT2S", titleInfo.title), flags: 0 },
99
+ { id: "TLEN", contents: (0, id3_1.encodeUTF16BEStringEA3)(milliseconds.toString()), flags: 0 },
100
+ { id: "GEOB", contents: secondGEOBContents, flags: 0 }, // OMG_BKLSI
101
+ ]
102
+ };
103
+ return { contents: (0, id3_1.serialize)(id3Info), trackEncryptionKey: actualTrackKey, maclistValue };
104
+ }
105
+ function createTaggedEncryptedOMA(rawData, titleInfo, codec) {
106
+ const formatHeader = (0, utils_1.createEA3Header)(codec, true);
107
+ const milliseconds = Math.floor(1000 * (0, himd_js_1.getSeconds)(codec, Math.ceil(rawData.length / (0, himd_js_1.getBytesPerFrame)(codec))));
108
+ const { contents: encHeader, trackEncryptionKey, maclistValue } = createEncryptionHeader(titleInfo, milliseconds);
109
+ let iv = (0, utils_1.createRandomBytes)(8);
110
+ formatHeader.set(iv, formatHeader.length - 8);
111
+ // Encrypt the whole file
112
+ const keyWa = crypto_js_wasm_1.default.lib.WordArray.create(trackEncryptionKey);
113
+ const ivWa = crypto_js_wasm_1.default.lib.WordArray.create(iv);
114
+ const blockWa = crypto_js_wasm_1.default.lib.WordArray.create(rawData);
115
+ const allData = crypto_js_wasm_1.default.DES.encrypt(blockWa, keyWa, { mode: crypto_js_wasm_1.default.mode.CBC, iv: ivWa });
116
+ rawData = (0, utils_1.wordArrayToByteArray)(allData.ciphertext, rawData.length);
117
+ return { data: (0, utils_1.concatUint8Arrays)([encHeader, formatHeader, rawData]), maclistValue, duration: milliseconds };
118
+ }
119
+ exports.createTaggedEncryptedOMA = createTaggedEncryptedOMA;
120
+ function findInMetadata(metadata, id, asGeob) {
121
+ if (!asGeob)
122
+ return metadata.tags.find(e => e.id === id);
123
+ return metadata.tags.filter(e => e.id === "GEOB")
124
+ .find(e => {
125
+ if (e.contents[0] !== 0x02)
126
+ return false;
127
+ // This is a valid Sony crypto block
128
+ for (let i = 0; i < id.length * 2; i += 2) {
129
+ if (e.contents[i + 11] !== id.charCodeAt(i / 2))
130
+ return false;
131
+ }
132
+ return true;
133
+ });
134
+ }
135
+ async function updateMetadata(file, titleInfo) {
136
+ // Read the first 10 bytes to get the encryption header's size.
137
+ const ea3Header = await file.read(10);
138
+ if (ea3Header.length !== 10)
139
+ throw new Error("Invalid header");
140
+ const headerSizeRemaining = (0, id3_1.readSynchsafeInt32)(new DataView(ea3Header.buffer), 6)[0];
141
+ const fullEncryptionHeader = (0, utils_1.concatUint8Arrays)([ea3Header, await file.read(headerSizeRemaining)]);
142
+ const subsequentData = await file.read();
143
+ const metadata = (0, id3_1.parse)(fullEncryptionHeader);
144
+ const tlen = findInMetadata(metadata, "TLEN", false);
145
+ const ulinf = findInMetadata(metadata, "OMG_ULINF", true);
146
+ const bklsi = findInMetadata(metadata, "OMG_BKLSI", true);
147
+ if (!ulinf || !bklsi || !tlen)
148
+ throw new Error("Not a valid encrypted OMA");
149
+ const newMetadataBlock = {
150
+ flags: metadata.flags,
151
+ version: metadata.version,
152
+ tags: [
153
+ ulinf,
154
+ { id: "TIT2", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.title), flags: 0 },
155
+ { id: "TPE1", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.artist), flags: 0 },
156
+ { id: "TALB", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.album), flags: 0 },
157
+ { id: "TALB", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.album), flags: 0 },
158
+ { id: "TCON", contents: (0, id3_1.encodeUTF16BEStringEA3)(titleInfo.genre), flags: 0 },
159
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_TPE1S", titleInfo.artist), flags: 0 },
160
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_TRACK", '0'), flags: 0 },
161
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_ALBMS", titleInfo.album), flags: 0 },
162
+ { id: "TXXX", contents: encodeSonyWeirdString("OMG_TIT2S", titleInfo.title), flags: 0 },
163
+ tlen,
164
+ bklsi,
165
+ ]
166
+ };
167
+ const serialized = (0, id3_1.serialize)(newMetadataBlock);
168
+ // Rewrite the file
169
+ const zeroOutDifference = Math.max(0, fullEncryptionHeader.length - serialized.length);
170
+ await file.seek(0);
171
+ await file.write(serialized);
172
+ await file.write(subsequentData);
173
+ await file.write(new Uint8Array(zeroOutDifference).fill(0));
174
+ }
175
+ exports.updateMetadata = updateMetadata;
@@ -0,0 +1,9 @@
1
+ import { CodecInfo } from 'himd-js';
2
+ export declare function assert(condition: boolean, message?: string): void;
3
+ export declare function join(...paths: string[]): string;
4
+ export declare function concatUint8Arrays(args: Uint8Array[]): Uint8Array;
5
+ export declare function createEA3Header({ codecId, codecInfo }: CodecInfo, encrypted?: boolean): Uint8Array;
6
+ export declare function wordArrayToByteArray(wordArray: any, length?: number): Uint8Array;
7
+ export declare function createRandomBytes(length?: number): Uint8Array;
8
+ export declare function arrayEq<T>(a: ArrayLike<T>, b: ArrayLike<T>): boolean;
9
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,wBAAgB,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,QAM1D;AAED,wBAAgB,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,UAEtC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,cAcnD;AAED,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,SAAS,UAAQ,cASnF;AAmBD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,GAAE,MAA2B,cAavF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,SAAI,cAM3C;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,WAM1D"}
package/dist/utils.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.arrayEq = exports.createRandomBytes = exports.wordArrayToByteArray = exports.createEA3Header = exports.concatUint8Arrays = exports.join = exports.assert = void 0;
4
+ function assert(condition, message) {
5
+ if (condition) {
6
+ return;
7
+ }
8
+ message = message || 'no message provided';
9
+ throw new Error(`Assertion failed: ${message}`);
10
+ }
11
+ exports.assert = assert;
12
+ function join(...paths) {
13
+ return paths.join("/").replace(/\/*/, '/');
14
+ }
15
+ exports.join = join;
16
+ function concatUint8Arrays(args) {
17
+ let totalLength = 0;
18
+ for (let a of args) {
19
+ totalLength += a.length;
20
+ }
21
+ let res = new Uint8Array(totalLength);
22
+ let offset = 0;
23
+ for (let a of args) {
24
+ res.set(a, offset);
25
+ offset += a.length;
26
+ }
27
+ return res;
28
+ }
29
+ exports.concatUint8Arrays = concatUint8Arrays;
30
+ function createEA3Header({ codecId, codecInfo }, encrypted = false) {
31
+ const headerSize = 96;
32
+ const header = new Uint8Array(headerSize);
33
+ header.set(new Uint8Array([0x45, 0x41, 0x33, 0x01, 0x00, 0x60, encrypted ? 0x00 : 0xff, encrypted ? 0x01 : 0xff, 0x00, 0x00, 0x00, 0x00]));
34
+ header[32] = codecId;
35
+ header[33] = codecInfo[0];
36
+ header[34] = codecInfo[1];
37
+ header[35] = codecInfo[2];
38
+ return header;
39
+ }
40
+ exports.createEA3Header = createEA3Header;
41
+ function wordToByteArray(word, length, littleEndian = false) {
42
+ let ba = [], xFF = 0xff;
43
+ let actualLength = length;
44
+ if (littleEndian) {
45
+ length = 4;
46
+ }
47
+ if (length > 0)
48
+ ba.push(word >>> 24);
49
+ if (length > 1)
50
+ ba.push((word >>> 16) & xFF);
51
+ if (length > 2)
52
+ ba.push((word >>> 8) & xFF);
53
+ if (length > 3)
54
+ ba.push(word & xFF);
55
+ if (littleEndian) {
56
+ ba = ba.splice(4 - actualLength).reverse();
57
+ }
58
+ return ba;
59
+ }
60
+ function wordArrayToByteArray(wordArray, length = wordArray.sigBytes) {
61
+ let res = new Uint8Array(length);
62
+ let bytes;
63
+ let i = 0;
64
+ let offset = 0;
65
+ while (length > 0) {
66
+ bytes = wordToByteArray(wordArray.words[i], Math.min(4, length));
67
+ res.set(bytes, offset);
68
+ length -= bytes.length;
69
+ offset += bytes.length;
70
+ i++;
71
+ }
72
+ return res;
73
+ }
74
+ exports.wordArrayToByteArray = wordArrayToByteArray;
75
+ function createRandomBytes(length = 8) {
76
+ return new Uint8Array(Array(length)
77
+ .fill(0)
78
+ .map(() => Math.floor(Math.random() * 256)));
79
+ }
80
+ exports.createRandomBytes = createRandomBytes;
81
+ function arrayEq(a, b) {
82
+ if (a.length !== b.length)
83
+ return false;
84
+ for (let i = 0; i < a.length; i++) {
85
+ if (a[i] !== b[i])
86
+ return false;
87
+ }
88
+ return true;
89
+ }
90
+ exports.arrayEq = arrayEq;
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "networkwm-js",
3
+ "version": "0.1.0",
4
+ "description": "A library which lets you manage tracks and metadata on Sony Network Walkmen.",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/asivery/networkwm-js.git"
12
+ },
13
+ "keywords": [
14
+ "sony",
15
+ "walkman",
16
+ "mp3",
17
+ "atrac"
18
+ ],
19
+ "author": "asivery",
20
+ "license": "GPL-2.0",
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "bugs": {
25
+ "url": "https://github.com/asivery/networkwm-js/issues"
26
+ },
27
+ "homepage": "https://github.com/asivery/networkwm-js#readme",
28
+ "devDependencies": {
29
+ "@types/node": "^18.11.9",
30
+ "prettier": "^2.8.8",
31
+ "typescript": "^4.8.4"
32
+ },
33
+ "dependencies": {
34
+ "@originjs/crypto-js-wasm": "github:asivery/crypto-js-wasm",
35
+ "async-mutex": "^0.4.0",
36
+ "himd-js": "^0.2.0-alpha.5",
37
+ "mp3-parser": "^0.3.0",
38
+ "node-id3": "^0.2.5",
39
+ "node-mass-storage": "^0.2.0",
40
+ "nufatfs": "^0.1.5",
41
+ "usb": "^2.4.1"
42
+ }
43
+ }