@basmilius/apple-encoding 0.5.3 → 0.6.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 +1 -1
- package/dist/daap.d.ts +95 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +891 -9
- package/dist/rtsp.d.ts +1 -1
- package/package.json +3 -5
package/LICENSE
CHANGED
package/dist/daap.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export declare const ContentCode: {
|
|
2
|
+
readonly mlit: "dmap.listingitem";
|
|
3
|
+
readonly mlcl: "dmap.listing";
|
|
4
|
+
readonly msrv: "dmap.serverinforesponse";
|
|
5
|
+
readonly mcon: "dmap.container";
|
|
6
|
+
readonly miid: "dmap.itemid";
|
|
7
|
+
readonly minm: "dmap.itemname";
|
|
8
|
+
readonly mikd: "dmap.itemkind";
|
|
9
|
+
readonly mper: "dmap.persistentid";
|
|
10
|
+
readonly asal: "daap.songalbum";
|
|
11
|
+
readonly asar: "daap.songartist";
|
|
12
|
+
readonly asaa: "daap.songalbumartist";
|
|
13
|
+
readonly ascp: "daap.songcomposer";
|
|
14
|
+
readonly asgn: "daap.songgenre";
|
|
15
|
+
readonly astm: "daap.songtime";
|
|
16
|
+
readonly astn: "daap.songtracknumber";
|
|
17
|
+
readonly asdc: "daap.songdisccount";
|
|
18
|
+
readonly asdn: "daap.songdiscnumber";
|
|
19
|
+
readonly astc: "daap.songtrackcount";
|
|
20
|
+
readonly asyr: "daap.songyear";
|
|
21
|
+
readonly asbr: "daap.songbitrate";
|
|
22
|
+
readonly assr: "daap.songsamplerate";
|
|
23
|
+
readonly assz: "daap.songsize";
|
|
24
|
+
readonly caps: "daap.songplaystatus";
|
|
25
|
+
readonly cash: "daap.songshufflestate";
|
|
26
|
+
readonly carp: "daap.songrepeatstate";
|
|
27
|
+
readonly cavs: "daap.songvisiblestate";
|
|
28
|
+
readonly aePP: "com.apple.itunes.photo-properties";
|
|
29
|
+
};
|
|
30
|
+
export declare const TagType: {
|
|
31
|
+
readonly mlit: 12;
|
|
32
|
+
readonly mlcl: 12;
|
|
33
|
+
readonly mcon: 12;
|
|
34
|
+
readonly msrv: 12;
|
|
35
|
+
readonly miid: 5;
|
|
36
|
+
readonly minm: 9;
|
|
37
|
+
readonly mikd: 1;
|
|
38
|
+
readonly mper: 7;
|
|
39
|
+
readonly asal: 9;
|
|
40
|
+
readonly asar: 9;
|
|
41
|
+
readonly asaa: 9;
|
|
42
|
+
readonly ascp: 9;
|
|
43
|
+
readonly asgn: 9;
|
|
44
|
+
readonly astm: 5;
|
|
45
|
+
readonly astn: 3;
|
|
46
|
+
readonly asdc: 3;
|
|
47
|
+
readonly asdn: 3;
|
|
48
|
+
readonly astc: 3;
|
|
49
|
+
readonly asyr: 3;
|
|
50
|
+
readonly asbr: 3;
|
|
51
|
+
readonly assr: 5;
|
|
52
|
+
readonly assz: 5;
|
|
53
|
+
readonly caps: 1;
|
|
54
|
+
readonly cash: 1;
|
|
55
|
+
readonly carp: 1;
|
|
56
|
+
readonly cavs: 1;
|
|
57
|
+
readonly aePP: 9;
|
|
58
|
+
};
|
|
59
|
+
export declare function encodeTag(tag: string, value: Buffer | string | number | bigint): Buffer;
|
|
60
|
+
export declare function encodeContainer(tag: string, content: Buffer): Buffer;
|
|
61
|
+
export declare function encodePlaybackStatus(status: PlaybackStatus): Buffer;
|
|
62
|
+
export declare function encodeTagWithSize(tag: string, value: number, byteSize: 1 | 2 | 4 | 8): Buffer;
|
|
63
|
+
export declare function encodeTrackMetadata(metadata: TrackMetadata): Buffer;
|
|
64
|
+
export declare function decode(buffer: Buffer): DecodedTag[];
|
|
65
|
+
export declare function decodeTag(buffer: Buffer): [DecodedTag, Buffer] | null;
|
|
66
|
+
export declare function decodeToObject(buffer: Buffer): Record<string, unknown>;
|
|
67
|
+
export declare function decodeTrackMetadata(buffer: Buffer): TrackMetadata;
|
|
68
|
+
export type ContentCodeKey = keyof typeof ContentCode;
|
|
69
|
+
export type DecodedTag = {
|
|
70
|
+
readonly tag: string;
|
|
71
|
+
readonly length: number;
|
|
72
|
+
readonly value: Buffer;
|
|
73
|
+
};
|
|
74
|
+
export type PlaybackStatus = {
|
|
75
|
+
readonly playing?: boolean;
|
|
76
|
+
readonly shuffle?: boolean;
|
|
77
|
+
readonly repeat?: "off" | "one" | "all";
|
|
78
|
+
};
|
|
79
|
+
export type TrackMetadata = {
|
|
80
|
+
readonly title?: string;
|
|
81
|
+
readonly artist?: string;
|
|
82
|
+
readonly albumArtist?: string;
|
|
83
|
+
readonly album?: string;
|
|
84
|
+
readonly composer?: string;
|
|
85
|
+
readonly genre?: string;
|
|
86
|
+
readonly duration?: number;
|
|
87
|
+
readonly trackNumber?: number;
|
|
88
|
+
readonly trackCount?: number;
|
|
89
|
+
readonly discNumber?: number;
|
|
90
|
+
readonly discCount?: number;
|
|
91
|
+
readonly year?: number;
|
|
92
|
+
readonly bitrate?: number;
|
|
93
|
+
readonly sampleRate?: number;
|
|
94
|
+
readonly size?: number;
|
|
95
|
+
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -9,6 +9,284 @@ var __export = (target, all) => {
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// src/daap.ts
|
|
13
|
+
var exports_daap = {};
|
|
14
|
+
__export(exports_daap, {
|
|
15
|
+
encodeTrackMetadata: () => encodeTrackMetadata,
|
|
16
|
+
encodeTagWithSize: () => encodeTagWithSize,
|
|
17
|
+
encodeTag: () => encodeTag,
|
|
18
|
+
encodePlaybackStatus: () => encodePlaybackStatus,
|
|
19
|
+
encodeContainer: () => encodeContainer,
|
|
20
|
+
decodeTrackMetadata: () => decodeTrackMetadata,
|
|
21
|
+
decodeToObject: () => decodeToObject,
|
|
22
|
+
decodeTag: () => decodeTag,
|
|
23
|
+
decode: () => decode,
|
|
24
|
+
TagType: () => TagType,
|
|
25
|
+
ContentCode: () => ContentCode
|
|
26
|
+
});
|
|
27
|
+
var ContentCode = {
|
|
28
|
+
mlit: "dmap.listingitem",
|
|
29
|
+
mlcl: "dmap.listing",
|
|
30
|
+
msrv: "dmap.serverinforesponse",
|
|
31
|
+
mcon: "dmap.container",
|
|
32
|
+
miid: "dmap.itemid",
|
|
33
|
+
minm: "dmap.itemname",
|
|
34
|
+
mikd: "dmap.itemkind",
|
|
35
|
+
mper: "dmap.persistentid",
|
|
36
|
+
asal: "daap.songalbum",
|
|
37
|
+
asar: "daap.songartist",
|
|
38
|
+
asaa: "daap.songalbumartist",
|
|
39
|
+
ascp: "daap.songcomposer",
|
|
40
|
+
asgn: "daap.songgenre",
|
|
41
|
+
astm: "daap.songtime",
|
|
42
|
+
astn: "daap.songtracknumber",
|
|
43
|
+
asdc: "daap.songdisccount",
|
|
44
|
+
asdn: "daap.songdiscnumber",
|
|
45
|
+
astc: "daap.songtrackcount",
|
|
46
|
+
asyr: "daap.songyear",
|
|
47
|
+
asbr: "daap.songbitrate",
|
|
48
|
+
assr: "daap.songsamplerate",
|
|
49
|
+
assz: "daap.songsize",
|
|
50
|
+
caps: "daap.songplaystatus",
|
|
51
|
+
cash: "daap.songshufflestate",
|
|
52
|
+
carp: "daap.songrepeatstate",
|
|
53
|
+
cavs: "daap.songvisiblestate",
|
|
54
|
+
aePP: "com.apple.itunes.photo-properties"
|
|
55
|
+
};
|
|
56
|
+
var TagType = {
|
|
57
|
+
mlit: 12,
|
|
58
|
+
mlcl: 12,
|
|
59
|
+
mcon: 12,
|
|
60
|
+
msrv: 12,
|
|
61
|
+
miid: 5,
|
|
62
|
+
minm: 9,
|
|
63
|
+
mikd: 1,
|
|
64
|
+
mper: 7,
|
|
65
|
+
asal: 9,
|
|
66
|
+
asar: 9,
|
|
67
|
+
asaa: 9,
|
|
68
|
+
ascp: 9,
|
|
69
|
+
asgn: 9,
|
|
70
|
+
astm: 5,
|
|
71
|
+
astn: 3,
|
|
72
|
+
asdc: 3,
|
|
73
|
+
asdn: 3,
|
|
74
|
+
astc: 3,
|
|
75
|
+
asyr: 3,
|
|
76
|
+
asbr: 3,
|
|
77
|
+
assr: 5,
|
|
78
|
+
assz: 5,
|
|
79
|
+
caps: 1,
|
|
80
|
+
cash: 1,
|
|
81
|
+
carp: 1,
|
|
82
|
+
cavs: 1,
|
|
83
|
+
aePP: 9
|
|
84
|
+
};
|
|
85
|
+
function encodeTag(tag, value) {
|
|
86
|
+
if (tag.length !== 4) {
|
|
87
|
+
throw new Error(`Invalid DAAP tag: ${tag}. Tags must be exactly 4 characters.`);
|
|
88
|
+
}
|
|
89
|
+
const tagBuffer = Buffer.from(tag, "ascii");
|
|
90
|
+
let valueBuffer;
|
|
91
|
+
if (typeof value === "string") {
|
|
92
|
+
valueBuffer = Buffer.from(value, "utf8");
|
|
93
|
+
} else if (typeof value === "bigint") {
|
|
94
|
+
valueBuffer = Buffer.alloc(8);
|
|
95
|
+
valueBuffer.writeBigUInt64BE(value, 0);
|
|
96
|
+
} else if (typeof value === "number") {
|
|
97
|
+
if (value <= 255 && value >= 0) {
|
|
98
|
+
valueBuffer = Buffer.alloc(1);
|
|
99
|
+
valueBuffer.writeUInt8(value, 0);
|
|
100
|
+
} else if (value <= 65535 && value >= 0) {
|
|
101
|
+
valueBuffer = Buffer.alloc(2);
|
|
102
|
+
valueBuffer.writeUInt16BE(value, 0);
|
|
103
|
+
} else if (value <= 4294967295 && value >= 0) {
|
|
104
|
+
valueBuffer = Buffer.alloc(4);
|
|
105
|
+
valueBuffer.writeUInt32BE(value, 0);
|
|
106
|
+
} else {
|
|
107
|
+
valueBuffer = Buffer.alloc(8);
|
|
108
|
+
valueBuffer.writeBigInt64BE(BigInt(value), 0);
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
valueBuffer = value;
|
|
112
|
+
}
|
|
113
|
+
const lengthBuffer = Buffer.alloc(4);
|
|
114
|
+
lengthBuffer.writeUInt32BE(valueBuffer.length, 0);
|
|
115
|
+
return Buffer.concat([tagBuffer, lengthBuffer, valueBuffer]);
|
|
116
|
+
}
|
|
117
|
+
function encodeContainer(tag, content) {
|
|
118
|
+
if (tag.length !== 4) {
|
|
119
|
+
throw new Error(`Invalid DAAP tag: ${tag}. Tags must be exactly 4 characters.`);
|
|
120
|
+
}
|
|
121
|
+
const tagBuffer = Buffer.from(tag, "ascii");
|
|
122
|
+
const lengthBuffer = Buffer.alloc(4);
|
|
123
|
+
lengthBuffer.writeUInt32BE(content.length, 0);
|
|
124
|
+
return Buffer.concat([tagBuffer, lengthBuffer, content]);
|
|
125
|
+
}
|
|
126
|
+
function encodePlaybackStatus(status) {
|
|
127
|
+
const tags = [];
|
|
128
|
+
if (status.playing !== undefined) {
|
|
129
|
+
tags.push(encodeTagWithSize("caps", status.playing ? 4 : 3, 1));
|
|
130
|
+
}
|
|
131
|
+
if (status.shuffle !== undefined) {
|
|
132
|
+
tags.push(encodeTagWithSize("cash", status.shuffle ? 1 : 0, 1));
|
|
133
|
+
}
|
|
134
|
+
if (status.repeat !== undefined) {
|
|
135
|
+
let repeatValue = 0;
|
|
136
|
+
if (status.repeat === "one")
|
|
137
|
+
repeatValue = 1;
|
|
138
|
+
else if (status.repeat === "all")
|
|
139
|
+
repeatValue = 2;
|
|
140
|
+
tags.push(encodeTagWithSize("carp", repeatValue, 1));
|
|
141
|
+
}
|
|
142
|
+
return Buffer.concat(tags);
|
|
143
|
+
}
|
|
144
|
+
function encodeTagWithSize(tag, value, byteSize) {
|
|
145
|
+
if (tag.length !== 4) {
|
|
146
|
+
throw new Error(`Invalid DAAP tag: ${tag}. Tags must be exactly 4 characters.`);
|
|
147
|
+
}
|
|
148
|
+
const tagBuffer = Buffer.from(tag, "ascii");
|
|
149
|
+
const valueBuffer = Buffer.alloc(byteSize);
|
|
150
|
+
switch (byteSize) {
|
|
151
|
+
case 1:
|
|
152
|
+
valueBuffer.writeUInt8(value, 0);
|
|
153
|
+
break;
|
|
154
|
+
case 2:
|
|
155
|
+
valueBuffer.writeUInt16BE(value, 0);
|
|
156
|
+
break;
|
|
157
|
+
case 4:
|
|
158
|
+
valueBuffer.writeUInt32BE(value, 0);
|
|
159
|
+
break;
|
|
160
|
+
case 8:
|
|
161
|
+
valueBuffer.writeBigUInt64BE(BigInt(value), 0);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
const lengthBuffer = Buffer.alloc(4);
|
|
165
|
+
lengthBuffer.writeUInt32BE(byteSize, 0);
|
|
166
|
+
return Buffer.concat([tagBuffer, lengthBuffer, valueBuffer]);
|
|
167
|
+
}
|
|
168
|
+
function encodeTrackMetadata(metadata) {
|
|
169
|
+
const tags = [];
|
|
170
|
+
if (metadata.title !== undefined) {
|
|
171
|
+
tags.push(encodeTag("minm", metadata.title));
|
|
172
|
+
}
|
|
173
|
+
if (metadata.artist !== undefined) {
|
|
174
|
+
tags.push(encodeTag("asar", metadata.artist));
|
|
175
|
+
}
|
|
176
|
+
if (metadata.albumArtist !== undefined) {
|
|
177
|
+
tags.push(encodeTag("asaa", metadata.albumArtist));
|
|
178
|
+
}
|
|
179
|
+
if (metadata.album !== undefined) {
|
|
180
|
+
tags.push(encodeTag("asal", metadata.album));
|
|
181
|
+
}
|
|
182
|
+
if (metadata.composer !== undefined) {
|
|
183
|
+
tags.push(encodeTag("ascp", metadata.composer));
|
|
184
|
+
}
|
|
185
|
+
if (metadata.genre !== undefined) {
|
|
186
|
+
tags.push(encodeTag("asgn", metadata.genre));
|
|
187
|
+
}
|
|
188
|
+
if (metadata.duration !== undefined) {
|
|
189
|
+
tags.push(encodeTagWithSize("astm", Math.floor(metadata.duration * 1000), 4));
|
|
190
|
+
}
|
|
191
|
+
if (metadata.trackNumber !== undefined) {
|
|
192
|
+
tags.push(encodeTagWithSize("astn", metadata.trackNumber, 2));
|
|
193
|
+
}
|
|
194
|
+
if (metadata.trackCount !== undefined) {
|
|
195
|
+
tags.push(encodeTagWithSize("astc", metadata.trackCount, 2));
|
|
196
|
+
}
|
|
197
|
+
if (metadata.discNumber !== undefined) {
|
|
198
|
+
tags.push(encodeTagWithSize("asdn", metadata.discNumber, 2));
|
|
199
|
+
}
|
|
200
|
+
if (metadata.discCount !== undefined) {
|
|
201
|
+
tags.push(encodeTagWithSize("asdc", metadata.discCount, 2));
|
|
202
|
+
}
|
|
203
|
+
if (metadata.year !== undefined) {
|
|
204
|
+
tags.push(encodeTagWithSize("asyr", metadata.year, 2));
|
|
205
|
+
}
|
|
206
|
+
if (metadata.bitrate !== undefined) {
|
|
207
|
+
tags.push(encodeTagWithSize("asbr", metadata.bitrate, 2));
|
|
208
|
+
}
|
|
209
|
+
if (metadata.sampleRate !== undefined) {
|
|
210
|
+
tags.push(encodeTagWithSize("assr", metadata.sampleRate, 4));
|
|
211
|
+
}
|
|
212
|
+
if (metadata.size !== undefined) {
|
|
213
|
+
tags.push(encodeTagWithSize("assz", metadata.size, 4));
|
|
214
|
+
}
|
|
215
|
+
const content = Buffer.concat(tags);
|
|
216
|
+
return encodeContainer("mlit", content);
|
|
217
|
+
}
|
|
218
|
+
function decode(buffer) {
|
|
219
|
+
const tags = [];
|
|
220
|
+
let remaining = buffer;
|
|
221
|
+
while (remaining.length > 0) {
|
|
222
|
+
const result = decodeTag(remaining);
|
|
223
|
+
if (!result)
|
|
224
|
+
break;
|
|
225
|
+
const [tag, rest] = result;
|
|
226
|
+
tags.push(tag);
|
|
227
|
+
remaining = rest;
|
|
228
|
+
}
|
|
229
|
+
return tags;
|
|
230
|
+
}
|
|
231
|
+
function decodeTag(buffer) {
|
|
232
|
+
if (buffer.length < 8) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
const tag = buffer.subarray(0, 4).toString("ascii");
|
|
236
|
+
const length = buffer.readUInt32BE(4);
|
|
237
|
+
if (buffer.length < 8 + length) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
const value = buffer.subarray(8, 8 + length);
|
|
241
|
+
const remaining = buffer.subarray(8 + length);
|
|
242
|
+
return [{ tag, length, value }, remaining];
|
|
243
|
+
}
|
|
244
|
+
function decodeToObject(buffer) {
|
|
245
|
+
const result = {};
|
|
246
|
+
const tags = decode(buffer);
|
|
247
|
+
for (const { tag, value } of tags) {
|
|
248
|
+
const tagType = TagType[tag];
|
|
249
|
+
if (tagType === undefined) {
|
|
250
|
+
result[tag] = value;
|
|
251
|
+
} else if (tagType === 12) {
|
|
252
|
+
result[tag] = decodeToObject(value);
|
|
253
|
+
} else if (tagType === 9) {
|
|
254
|
+
result[tag] = value.toString("utf8");
|
|
255
|
+
} else if (tagType === 1 || tagType === 2) {
|
|
256
|
+
result[tag] = value.readUInt8(0);
|
|
257
|
+
} else if (tagType === 3 || tagType === 4) {
|
|
258
|
+
result[tag] = value.readUInt16BE(0);
|
|
259
|
+
} else if (tagType === 5 || tagType === 6) {
|
|
260
|
+
result[tag] = value.readUInt32BE(0);
|
|
261
|
+
} else if (tagType === 7 || tagType === 8) {
|
|
262
|
+
result[tag] = value.readBigUInt64BE(0);
|
|
263
|
+
} else {
|
|
264
|
+
result[tag] = value;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
function decodeTrackMetadata(buffer) {
|
|
270
|
+
const obj = decodeToObject(buffer);
|
|
271
|
+
const mlit = obj.mlit ?? obj;
|
|
272
|
+
return {
|
|
273
|
+
title: mlit.minm,
|
|
274
|
+
artist: mlit.asar,
|
|
275
|
+
albumArtist: mlit.asaa,
|
|
276
|
+
album: mlit.asal,
|
|
277
|
+
composer: mlit.ascp,
|
|
278
|
+
genre: mlit.asgn,
|
|
279
|
+
duration: mlit.astm !== undefined ? mlit.astm / 1000 : undefined,
|
|
280
|
+
trackNumber: mlit.astn,
|
|
281
|
+
trackCount: mlit.astc,
|
|
282
|
+
discNumber: mlit.asdn,
|
|
283
|
+
discCount: mlit.asdc,
|
|
284
|
+
year: mlit.asyr,
|
|
285
|
+
bitrate: mlit.asbr,
|
|
286
|
+
sampleRate: mlit.assr,
|
|
287
|
+
size: mlit.assz
|
|
288
|
+
};
|
|
289
|
+
}
|
|
12
290
|
// src/ntp.ts
|
|
13
291
|
var exports_ntp = {};
|
|
14
292
|
__export(exports_ntp, {
|
|
@@ -16,7 +294,7 @@ __export(exports_ntp, {
|
|
|
16
294
|
ns: () => ns,
|
|
17
295
|
now: () => now,
|
|
18
296
|
encode: () => encode,
|
|
19
|
-
decode: () =>
|
|
297
|
+
decode: () => decode2
|
|
20
298
|
});
|
|
21
299
|
var EPOCH = 0x83AA7E80n;
|
|
22
300
|
function now() {
|
|
@@ -34,7 +312,7 @@ function parts(ntp) {
|
|
|
34
312
|
Number(ntp & 0xFFFFFFFFn)
|
|
35
313
|
];
|
|
36
314
|
}
|
|
37
|
-
function
|
|
315
|
+
function decode2(buffer) {
|
|
38
316
|
if (buffer.length < 24) {
|
|
39
317
|
throw new RangeError(`NTP packet too small: expected at least 24 bytes, got ${buffer.length}`);
|
|
40
318
|
}
|
|
@@ -72,7 +350,7 @@ __export(exports_opack, {
|
|
|
72
350
|
int: () => int,
|
|
73
351
|
float: () => float,
|
|
74
352
|
encode: () => encode2,
|
|
75
|
-
decode: () =>
|
|
353
|
+
decode: () => decode3
|
|
76
354
|
});
|
|
77
355
|
var TAG = {
|
|
78
356
|
TRUE: 1,
|
|
@@ -160,7 +438,7 @@ function int(value) {
|
|
|
160
438
|
function sizedInteger(value, size) {
|
|
161
439
|
return new SizedInteger(value, size);
|
|
162
440
|
}
|
|
163
|
-
function
|
|
441
|
+
function decode3(data) {
|
|
164
442
|
const [value] = _unpack(data, []);
|
|
165
443
|
return value;
|
|
166
444
|
}
|
|
@@ -453,8 +731,611 @@ __export(exports_plist, {
|
|
|
453
731
|
serialize: () => serialize,
|
|
454
732
|
parse: () => parse
|
|
455
733
|
});
|
|
456
|
-
|
|
457
|
-
|
|
734
|
+
// ../../node_modules/@plist/common/lib/esm/constants.js
|
|
735
|
+
var EPOCH2 = 978307200000;
|
|
736
|
+
var HEADER_BINARY = "bplist00";
|
|
737
|
+
var PlistFormat;
|
|
738
|
+
(function(PlistFormat2) {
|
|
739
|
+
PlistFormat2[PlistFormat2["BINARY"] = 0] = "BINARY";
|
|
740
|
+
PlistFormat2[PlistFormat2["XML"] = 1] = "XML";
|
|
741
|
+
PlistFormat2[PlistFormat2["OPENSTEP"] = 2] = "OPENSTEP";
|
|
742
|
+
})(PlistFormat || (PlistFormat = {}));
|
|
743
|
+
// ../../node_modules/@plist/binary.parse/lib/esm/index.js
|
|
744
|
+
var maxObjectSize = 100 * 1000 * 1000;
|
|
745
|
+
var maxObjectCount = 32768;
|
|
746
|
+
var DECODER_UTF8 = new TextDecoder("utf-8");
|
|
747
|
+
var DECODER_UTF16 = new TextDecoder("utf-16");
|
|
748
|
+
function readDouble(buffer, start = 0) {
|
|
749
|
+
return new DataView(buffer).getFloat64(start, false);
|
|
750
|
+
}
|
|
751
|
+
function readFloat(buffer, start = 0) {
|
|
752
|
+
return new DataView(buffer).getFloat32(start, false);
|
|
753
|
+
}
|
|
754
|
+
function readUInt8(buffer, start = 0) {
|
|
755
|
+
return new DataView(buffer).getUint8(start);
|
|
756
|
+
}
|
|
757
|
+
function readUInt16(buffer, start = 0) {
|
|
758
|
+
return new DataView(buffer).getUint16(start, false);
|
|
759
|
+
}
|
|
760
|
+
function readUInt32(buffer, start = 0) {
|
|
761
|
+
return new DataView(buffer).getUint32(start, false);
|
|
762
|
+
}
|
|
763
|
+
function readUInt64(buffer, start = 0) {
|
|
764
|
+
return new DataView(buffer).getBigUint64(start, false);
|
|
765
|
+
}
|
|
766
|
+
function readUInt(buffer) {
|
|
767
|
+
switch (buffer.byteLength) {
|
|
768
|
+
case 1:
|
|
769
|
+
return readUInt8(buffer);
|
|
770
|
+
case 2:
|
|
771
|
+
return readUInt16(buffer);
|
|
772
|
+
case 4:
|
|
773
|
+
return readUInt32(buffer);
|
|
774
|
+
case 8:
|
|
775
|
+
return readUInt64(buffer);
|
|
776
|
+
case 16:
|
|
777
|
+
return readUInt64(buffer, 8);
|
|
778
|
+
}
|
|
779
|
+
throw new Error(`Invalid unsigned int length: ${buffer.byteLength}`);
|
|
780
|
+
}
|
|
781
|
+
function readInt8(buffer, start = 0) {
|
|
782
|
+
return new DataView(buffer).getInt8(start);
|
|
783
|
+
}
|
|
784
|
+
function readInt16(buffer, start = 0) {
|
|
785
|
+
return new DataView(buffer).getInt16(start, false);
|
|
786
|
+
}
|
|
787
|
+
function readInt32(buffer, start = 0) {
|
|
788
|
+
return new DataView(buffer).getInt32(start, false);
|
|
789
|
+
}
|
|
790
|
+
function readInt64(buffer, start = 0) {
|
|
791
|
+
return new DataView(buffer).getBigInt64(start, false);
|
|
792
|
+
}
|
|
793
|
+
function readInt(buffer) {
|
|
794
|
+
switch (buffer.byteLength) {
|
|
795
|
+
case 1:
|
|
796
|
+
return readInt8(buffer);
|
|
797
|
+
case 2:
|
|
798
|
+
return readInt16(buffer);
|
|
799
|
+
case 4:
|
|
800
|
+
return readInt32(buffer);
|
|
801
|
+
case 8:
|
|
802
|
+
return readInt64(buffer);
|
|
803
|
+
case 16:
|
|
804
|
+
return readUInt64(buffer, 8);
|
|
805
|
+
}
|
|
806
|
+
throw new Error(`Invalid int length: ${buffer.byteLength}`);
|
|
807
|
+
}
|
|
808
|
+
function swapBytes(buffer) {
|
|
809
|
+
const array = new Uint8Array(buffer);
|
|
810
|
+
for (let i = 0;i < array.length; i += 2) {
|
|
811
|
+
const a = array[i];
|
|
812
|
+
array[i] = array[i + 1];
|
|
813
|
+
array[i + 1] = a;
|
|
814
|
+
}
|
|
815
|
+
return array.buffer;
|
|
816
|
+
}
|
|
817
|
+
var parse = (buffer) => {
|
|
818
|
+
const headerBytes = buffer.slice(0, HEADER_BINARY.length);
|
|
819
|
+
if (DECODER_UTF8.decode(headerBytes) !== HEADER_BINARY) {
|
|
820
|
+
throw new Error(`Invalid binary plist. Expected '${HEADER_BINARY}' at offset 0.`);
|
|
821
|
+
}
|
|
822
|
+
const trailer = buffer.slice(buffer.byteLength - 32, buffer.byteLength);
|
|
823
|
+
const offsetSize = readUInt8(trailer, 6);
|
|
824
|
+
const objectRefSize = readUInt8(trailer, 7);
|
|
825
|
+
const numObjects = Number(readUInt64(trailer, 8));
|
|
826
|
+
const topObject = Number(readUInt64(trailer, 16));
|
|
827
|
+
const offsetTableOffset = Number(readUInt64(trailer, 24));
|
|
828
|
+
if (numObjects > maxObjectCount) {
|
|
829
|
+
throw new Error("maxObjectCount exceeded");
|
|
830
|
+
}
|
|
831
|
+
const offsetTable = [];
|
|
832
|
+
for (let i = 0;i < numObjects; i++) {
|
|
833
|
+
const offsetBytes = buffer.slice(offsetTableOffset + i * offsetSize, offsetTableOffset + (i + 1) * offsetSize);
|
|
834
|
+
offsetTable[i] = Number(readUInt(offsetBytes));
|
|
835
|
+
}
|
|
836
|
+
function parseObject(tableOffset) {
|
|
837
|
+
const offset = offsetTable[tableOffset];
|
|
838
|
+
const type = readUInt8(buffer, offset);
|
|
839
|
+
const objType = (type & 240) >> 4;
|
|
840
|
+
const objInfo = type & 15;
|
|
841
|
+
switch (objType) {
|
|
842
|
+
case 0:
|
|
843
|
+
return parseSimple();
|
|
844
|
+
case 1:
|
|
845
|
+
return parseInteger();
|
|
846
|
+
case 8:
|
|
847
|
+
return parseUID();
|
|
848
|
+
case 2:
|
|
849
|
+
return parseReal();
|
|
850
|
+
case 3:
|
|
851
|
+
return parseDate();
|
|
852
|
+
case 4:
|
|
853
|
+
return parseData();
|
|
854
|
+
case 5:
|
|
855
|
+
return parsePlistString();
|
|
856
|
+
case 6:
|
|
857
|
+
return parsePlistString(true);
|
|
858
|
+
case 10:
|
|
859
|
+
return parseArray();
|
|
860
|
+
case 13:
|
|
861
|
+
return parseDictionary();
|
|
862
|
+
default:
|
|
863
|
+
throw new Error("Unhandled type 0x" + objType.toString(16));
|
|
864
|
+
}
|
|
865
|
+
function parseSimple() {
|
|
866
|
+
switch (objInfo) {
|
|
867
|
+
case 0:
|
|
868
|
+
return null;
|
|
869
|
+
case 8:
|
|
870
|
+
return false;
|
|
871
|
+
case 9:
|
|
872
|
+
return true;
|
|
873
|
+
case 15:
|
|
874
|
+
return null;
|
|
875
|
+
default:
|
|
876
|
+
throw new Error("Unhandled simple type 0x" + objType.toString(16));
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
function parseInteger() {
|
|
880
|
+
const length = Math.pow(2, objInfo);
|
|
881
|
+
if (length < maxObjectSize) {
|
|
882
|
+
const data = buffer.slice(offset + 1, offset + 1 + length);
|
|
883
|
+
return readInt(data);
|
|
884
|
+
}
|
|
885
|
+
throw new Error("Too little heap space available! Wanted to read " + length + " bytes, but only " + maxObjectSize + " are available.");
|
|
886
|
+
}
|
|
887
|
+
function parseUID() {
|
|
888
|
+
const length = objInfo + 1;
|
|
889
|
+
if (length < maxObjectSize) {
|
|
890
|
+
return {
|
|
891
|
+
CF$UID: readUInt(buffer.slice(offset + 1, offset + 1 + length))
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
throw new Error("Too little heap space available! Wanted to read " + length + " bytes, but only " + maxObjectSize + " are available.");
|
|
895
|
+
}
|
|
896
|
+
function parseReal() {
|
|
897
|
+
const length = Math.pow(2, objInfo);
|
|
898
|
+
if (length < maxObjectSize) {
|
|
899
|
+
const realBuffer = buffer.slice(offset + 1, offset + 1 + length);
|
|
900
|
+
if (length === 4) {
|
|
901
|
+
return readFloat(realBuffer);
|
|
902
|
+
} else if (length === 8) {
|
|
903
|
+
return readDouble(realBuffer);
|
|
904
|
+
}
|
|
905
|
+
throw new Error(`Invalid real length: ${length}`);
|
|
906
|
+
} else {
|
|
907
|
+
throw new Error("Too little heap space available! Wanted to read " + length + " bytes, but only " + maxObjectSize + " are available.");
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function parseDate() {
|
|
911
|
+
if (objInfo != 3) {
|
|
912
|
+
console.error("Unknown date type :" + objInfo + ". Parsing anyway...");
|
|
913
|
+
}
|
|
914
|
+
const dateBuffer = buffer.slice(offset + 1, offset + 9);
|
|
915
|
+
return new Date(EPOCH2 + 1000 * readDouble(dateBuffer));
|
|
916
|
+
}
|
|
917
|
+
function parseData() {
|
|
918
|
+
let dataoffset = 1;
|
|
919
|
+
let length = objInfo;
|
|
920
|
+
if (objInfo == 15) {
|
|
921
|
+
const int_type = readInt8(buffer, offset + 1);
|
|
922
|
+
const intType = (int_type & 240) / 16;
|
|
923
|
+
if (intType != 1) {
|
|
924
|
+
console.error("0x4: UNEXPECTED LENGTH-INT TYPE! " + intType);
|
|
925
|
+
}
|
|
926
|
+
const intInfo = int_type & 15;
|
|
927
|
+
const intLength = Math.pow(2, intInfo);
|
|
928
|
+
dataoffset = 2 + intLength;
|
|
929
|
+
length = Number(readUInt(buffer.slice(offset + 2, offset + 2 + intLength)));
|
|
930
|
+
}
|
|
931
|
+
if (length < maxObjectSize) {
|
|
932
|
+
return buffer.slice(offset + dataoffset, offset + dataoffset + Number(length));
|
|
933
|
+
}
|
|
934
|
+
throw new Error("Too little heap space available! Wanted to read " + length + " bytes, but only " + maxObjectSize + " are available.");
|
|
935
|
+
}
|
|
936
|
+
function parsePlistString(isUtf16 = false) {
|
|
937
|
+
let length = objInfo;
|
|
938
|
+
let stroffset = 1;
|
|
939
|
+
if (objInfo == 15) {
|
|
940
|
+
const int_type = readUInt8(buffer, offset + 1);
|
|
941
|
+
const intType = (int_type & 240) / 16;
|
|
942
|
+
if (intType != 1) {
|
|
943
|
+
console.error("UNEXPECTED LENGTH-INT TYPE! " + intType);
|
|
944
|
+
}
|
|
945
|
+
const intInfo = int_type & 15;
|
|
946
|
+
const intLength = Math.pow(2, intInfo);
|
|
947
|
+
stroffset = 2 + intLength;
|
|
948
|
+
length = Number(readUInt(buffer.slice(offset + 2, offset + 2 + intLength)));
|
|
949
|
+
}
|
|
950
|
+
length *= isUtf16 ? 2 : 1;
|
|
951
|
+
if (length < maxObjectSize) {
|
|
952
|
+
let plistString = buffer.slice(offset + stroffset, offset + stroffset + length);
|
|
953
|
+
if (isUtf16) {
|
|
954
|
+
plistString = swapBytes(plistString);
|
|
955
|
+
return DECODER_UTF16.decode(plistString);
|
|
956
|
+
} else {
|
|
957
|
+
return DECODER_UTF8.decode(plistString);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
throw new Error("Too little heap space available! Wanted to read " + length + " bytes, but only " + maxObjectSize + " are available.");
|
|
961
|
+
}
|
|
962
|
+
function parseArray() {
|
|
963
|
+
let length = objInfo;
|
|
964
|
+
let arrayoffset = 1;
|
|
965
|
+
if (objInfo == 15) {
|
|
966
|
+
const int_type = readUInt8(buffer, offset + 1);
|
|
967
|
+
const intType = (int_type & 240) / 16;
|
|
968
|
+
if (intType != 1) {
|
|
969
|
+
console.error("0xa: UNEXPECTED LENGTH-INT TYPE! " + intType);
|
|
970
|
+
}
|
|
971
|
+
const intInfo = int_type & 15;
|
|
972
|
+
const intLength = Math.pow(2, intInfo);
|
|
973
|
+
arrayoffset = 2 + intLength;
|
|
974
|
+
length = Number(readUInt(buffer.slice(offset + 2, offset + 2 + intLength)));
|
|
975
|
+
}
|
|
976
|
+
if (length * objectRefSize > maxObjectSize) {
|
|
977
|
+
throw new Error("Too little heap space available!");
|
|
978
|
+
}
|
|
979
|
+
const array = [];
|
|
980
|
+
for (let i = 0;i < length; i++) {
|
|
981
|
+
const objRef = Number(readUInt(buffer.slice(offset + arrayoffset + i * objectRefSize, offset + arrayoffset + (i + 1) * objectRefSize)));
|
|
982
|
+
array[i] = parseObject(objRef);
|
|
983
|
+
}
|
|
984
|
+
return array;
|
|
985
|
+
}
|
|
986
|
+
function parseDictionary() {
|
|
987
|
+
let length = objInfo;
|
|
988
|
+
let dictoffset = 1;
|
|
989
|
+
if (objInfo == 15) {
|
|
990
|
+
const int_type = readUInt8(buffer, offset + 1);
|
|
991
|
+
const intType = (int_type & 240) / 16;
|
|
992
|
+
if (intType != 1) {
|
|
993
|
+
console.error("0xD: UNEXPECTED LENGTH-INT TYPE! " + intType);
|
|
994
|
+
}
|
|
995
|
+
const intInfo = int_type & 15;
|
|
996
|
+
const intLength = Math.pow(2, intInfo);
|
|
997
|
+
dictoffset = 2 + intLength;
|
|
998
|
+
length = Number(readUInt(buffer.slice(offset + 2, offset + 2 + intLength)));
|
|
999
|
+
}
|
|
1000
|
+
if (length * 2 * objectRefSize > maxObjectSize) {
|
|
1001
|
+
throw new Error("Too little heap space available!");
|
|
1002
|
+
}
|
|
1003
|
+
const dict = {};
|
|
1004
|
+
for (let i = 0;i < length; i++) {
|
|
1005
|
+
const keyRef = Number(readUInt(buffer.slice(offset + dictoffset + i * objectRefSize, offset + dictoffset + (i + 1) * objectRefSize)));
|
|
1006
|
+
const valRef = Number(readUInt(buffer.slice(offset + dictoffset + length * objectRefSize + i * objectRefSize, offset + dictoffset + length * objectRefSize + (i + 1) * objectRefSize)));
|
|
1007
|
+
const key = parseObject(keyRef);
|
|
1008
|
+
if (typeof key !== "string") {
|
|
1009
|
+
throw new Error("Invalid key type.");
|
|
1010
|
+
}
|
|
1011
|
+
if (key === "__proto__") {
|
|
1012
|
+
throw new Error("Attempted prototype pollution");
|
|
1013
|
+
}
|
|
1014
|
+
const val = parseObject(valRef);
|
|
1015
|
+
dict[key] = val;
|
|
1016
|
+
}
|
|
1017
|
+
return dict;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return parseObject(topObject);
|
|
1021
|
+
};
|
|
1022
|
+
// ../../node_modules/@plist/binary.serialize/lib/esm/index.js
|
|
1023
|
+
var encoder = new TextEncoder;
|
|
1024
|
+
var nullBytes = new Uint8Array([0, 0, 0, 0, 0, 0]);
|
|
1025
|
+
var fromHexString = (hexString) => Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
|
1026
|
+
var isUID = (value) => !!value && typeof value === "object" && Object.keys(value).length == 1 && typeof value.CF$UID === "number";
|
|
1027
|
+
var toUTF16 = (string) => {
|
|
1028
|
+
const buf = new ArrayBuffer(string.length * 2);
|
|
1029
|
+
const bufView = new Uint16Array(buf);
|
|
1030
|
+
for (let i = 0, strLen = string.length;i < strLen; i++) {
|
|
1031
|
+
bufView[i] = string.charCodeAt(i);
|
|
1032
|
+
}
|
|
1033
|
+
return new Uint8Array(buf);
|
|
1034
|
+
};
|
|
1035
|
+
var concat2 = (first, second) => {
|
|
1036
|
+
const third = new Uint8Array(first.length + second.length);
|
|
1037
|
+
third.set(first);
|
|
1038
|
+
third.set(second, first.length);
|
|
1039
|
+
return third;
|
|
1040
|
+
};
|
|
1041
|
+
var writeUInt = (buffer, int2, size) => {
|
|
1042
|
+
const output = new Uint8Array(buffer.length + size);
|
|
1043
|
+
const dataView = new DataView(output.buffer);
|
|
1044
|
+
output.set(buffer);
|
|
1045
|
+
switch (size) {
|
|
1046
|
+
case 1:
|
|
1047
|
+
dataView.setUint8(buffer.length, Number(int2));
|
|
1048
|
+
break;
|
|
1049
|
+
case 2:
|
|
1050
|
+
dataView.setUint16(buffer.length, Number(int2), false);
|
|
1051
|
+
break;
|
|
1052
|
+
case 4:
|
|
1053
|
+
dataView.setUint32(buffer.length, Number(int2), false);
|
|
1054
|
+
break;
|
|
1055
|
+
case 8:
|
|
1056
|
+
dataView.setBigUint64(buffer.length, BigInt(int2), false);
|
|
1057
|
+
break;
|
|
1058
|
+
default:
|
|
1059
|
+
throw new Error("Unsupported int size");
|
|
1060
|
+
}
|
|
1061
|
+
return output;
|
|
1062
|
+
};
|
|
1063
|
+
var writeInt = (buffer, int2, size) => {
|
|
1064
|
+
const output = new Uint8Array(buffer.length + size);
|
|
1065
|
+
const dataView = new DataView(output.buffer);
|
|
1066
|
+
output.set(buffer);
|
|
1067
|
+
switch (size) {
|
|
1068
|
+
case 1:
|
|
1069
|
+
dataView.setInt8(buffer.length, Number(int2));
|
|
1070
|
+
break;
|
|
1071
|
+
case 2:
|
|
1072
|
+
dataView.setInt16(buffer.length, Number(int2), false);
|
|
1073
|
+
break;
|
|
1074
|
+
case 4:
|
|
1075
|
+
dataView.setInt32(buffer.length, Number(int2), false);
|
|
1076
|
+
break;
|
|
1077
|
+
case 8:
|
|
1078
|
+
dataView.setBigInt64(buffer.length, BigInt(int2), false);
|
|
1079
|
+
break;
|
|
1080
|
+
default:
|
|
1081
|
+
throw new Error("Unsupported int size");
|
|
1082
|
+
}
|
|
1083
|
+
return output;
|
|
1084
|
+
};
|
|
1085
|
+
var writeDouble = (buffer, double) => {
|
|
1086
|
+
const output = new Uint8Array(buffer.length + 8);
|
|
1087
|
+
const dataView = new DataView(output.buffer);
|
|
1088
|
+
output.set(buffer);
|
|
1089
|
+
dataView.setFloat64(buffer.length, double);
|
|
1090
|
+
return output;
|
|
1091
|
+
};
|
|
1092
|
+
var serialize = (value) => {
|
|
1093
|
+
let buffer = encoder.encode(HEADER_BINARY);
|
|
1094
|
+
if (value instanceof Array && value.length === 1) {
|
|
1095
|
+
value = value[0];
|
|
1096
|
+
}
|
|
1097
|
+
let entries = toEntries(value);
|
|
1098
|
+
const idSizeInBytes = computeIdSizeInBytes(entries.length);
|
|
1099
|
+
const offsets = [];
|
|
1100
|
+
let offsetSizeInBytes;
|
|
1101
|
+
let offsetTableOffset;
|
|
1102
|
+
updateEntryIds();
|
|
1103
|
+
entries.forEach((entry, entryIdx) => {
|
|
1104
|
+
offsets[entryIdx] = buffer.byteLength;
|
|
1105
|
+
if (typeof entry === "undefined" || entry === null) {
|
|
1106
|
+
buffer = writeUInt(buffer, 0, 1);
|
|
1107
|
+
} else {
|
|
1108
|
+
write(entry);
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
writeOffsetTable();
|
|
1112
|
+
writeTrailer();
|
|
1113
|
+
return buffer.buffer;
|
|
1114
|
+
function updateEntryIds() {
|
|
1115
|
+
const strings = {};
|
|
1116
|
+
let entryId = 0;
|
|
1117
|
+
entries.forEach((entry) => {
|
|
1118
|
+
if (entry.id) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
if (typeof entry.value === "string") {
|
|
1122
|
+
if (strings.hasOwnProperty(entry.value)) {
|
|
1123
|
+
entry.type = "stringref";
|
|
1124
|
+
entry.id = strings[entry.value];
|
|
1125
|
+
} else {
|
|
1126
|
+
strings[entry.value] = entry.id = entryId++;
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
entry.id = entryId++;
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
entries = entries.filter((entry) => {
|
|
1133
|
+
return entry.type !== "stringref";
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
function writeTrailer() {
|
|
1137
|
+
buffer = concat2(buffer, nullBytes);
|
|
1138
|
+
buffer = concat2(buffer, new Uint8Array([offsetSizeInBytes, idSizeInBytes]));
|
|
1139
|
+
buffer = writeUInt(buffer, BigInt(entries.length), 8);
|
|
1140
|
+
buffer = writeUInt(buffer, BigInt("0"), 8);
|
|
1141
|
+
buffer = writeUInt(buffer, BigInt(offsetTableOffset), 8);
|
|
1142
|
+
}
|
|
1143
|
+
function writeOffsetTable() {
|
|
1144
|
+
offsetTableOffset = buffer.byteLength;
|
|
1145
|
+
offsetSizeInBytes = computeOffsetSizeInBytes(offsetTableOffset);
|
|
1146
|
+
offsets.forEach((offset) => {
|
|
1147
|
+
buffer = writeUInt(buffer, offset, offsetSizeInBytes);
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
function write(entry) {
|
|
1151
|
+
if (entry.type === "primitive") {
|
|
1152
|
+
const value2 = entry.value;
|
|
1153
|
+
switch (typeof value2) {
|
|
1154
|
+
case "number":
|
|
1155
|
+
case "bigint":
|
|
1156
|
+
writeNumber(value2);
|
|
1157
|
+
break;
|
|
1158
|
+
case "string":
|
|
1159
|
+
writeString(value2);
|
|
1160
|
+
break;
|
|
1161
|
+
case "boolean":
|
|
1162
|
+
writeBoolean(value2);
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
if (value2 instanceof Date) {
|
|
1166
|
+
writeDate(value2);
|
|
1167
|
+
} else if (value2 instanceof ArrayBuffer) {
|
|
1168
|
+
writeData(value2);
|
|
1169
|
+
} else if (isUID(value2)) {
|
|
1170
|
+
writeUID(value2.CF$UID);
|
|
1171
|
+
}
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
switch (entry.type) {
|
|
1175
|
+
case "dict":
|
|
1176
|
+
writeDict(entry);
|
|
1177
|
+
break;
|
|
1178
|
+
case "array":
|
|
1179
|
+
writeArray(entry);
|
|
1180
|
+
break;
|
|
1181
|
+
default:
|
|
1182
|
+
throw new Error("unhandled entry type: " + entry.type);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
function writeDate(value2) {
|
|
1186
|
+
buffer = writeUInt(buffer, 51, 1);
|
|
1187
|
+
const date = (value2.getTime() - EPOCH2) / 1000;
|
|
1188
|
+
buffer = writeDouble(buffer, date);
|
|
1189
|
+
}
|
|
1190
|
+
function writeDict(entry) {
|
|
1191
|
+
writeIntHeader(13, entry.entryKeys.length);
|
|
1192
|
+
entry.entryKeys.forEach((entry2) => {
|
|
1193
|
+
writeID(entry2.id);
|
|
1194
|
+
});
|
|
1195
|
+
entry.entryValues.forEach((entry2) => {
|
|
1196
|
+
writeID(entry2.id);
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
function writeNumber(value2) {
|
|
1200
|
+
if (typeof value2 === "bigint") {
|
|
1201
|
+
const width = 16;
|
|
1202
|
+
const hex = value2.toString(16);
|
|
1203
|
+
const buf = fromHexString(hex.padStart(width * 2, "0").slice(0, width * 2));
|
|
1204
|
+
buffer = writeUInt(buffer, 20, 1);
|
|
1205
|
+
buffer = concat2(buffer, buf);
|
|
1206
|
+
} else {
|
|
1207
|
+
if (Number.isInteger(value2)) {
|
|
1208
|
+
if (value2 < 0) {
|
|
1209
|
+
buffer = writeUInt(buffer, 19, 1);
|
|
1210
|
+
buffer = writeInt(buffer, value2, 8);
|
|
1211
|
+
} else if (value2 <= 255) {
|
|
1212
|
+
buffer = writeUInt(buffer, 16, 1);
|
|
1213
|
+
buffer = writeUInt(buffer, value2, 1);
|
|
1214
|
+
} else if (value2 <= 65535) {
|
|
1215
|
+
buffer = writeUInt(buffer, 17, 1);
|
|
1216
|
+
buffer = writeUInt(buffer, value2, 2);
|
|
1217
|
+
} else if (value2 <= 4294967295) {
|
|
1218
|
+
buffer = writeUInt(buffer, 18, 1);
|
|
1219
|
+
buffer = writeUInt(buffer, value2, 4);
|
|
1220
|
+
} else {
|
|
1221
|
+
buffer = writeUInt(buffer, 19, 1);
|
|
1222
|
+
buffer = writeUInt(buffer, value2, 8);
|
|
1223
|
+
}
|
|
1224
|
+
} else {
|
|
1225
|
+
buffer = writeUInt(buffer, 35, 1);
|
|
1226
|
+
buffer = writeDouble(buffer, value2);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
function writeUID(uid) {
|
|
1231
|
+
writeIntHeader(8, 0);
|
|
1232
|
+
writeID(uid);
|
|
1233
|
+
}
|
|
1234
|
+
function writeArray(entry) {
|
|
1235
|
+
writeIntHeader(10, entry.entries.length);
|
|
1236
|
+
entry.entries.forEach((e) => {
|
|
1237
|
+
writeID(e.id);
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
function writeBoolean(value2) {
|
|
1241
|
+
buffer = writeUInt(buffer, value2 ? 9 : 8, 1);
|
|
1242
|
+
}
|
|
1243
|
+
function writeString(value2) {
|
|
1244
|
+
if (mustBeUtf16(value2)) {
|
|
1245
|
+
const utf16 = toUTF16(value2);
|
|
1246
|
+
writeIntHeader(6, utf16.length / 2);
|
|
1247
|
+
for (let i = 0;i < utf16.length; i += 2) {
|
|
1248
|
+
const t = utf16[i + 0];
|
|
1249
|
+
utf16[i + 0] = utf16[i + 1];
|
|
1250
|
+
utf16[i + 1] = t;
|
|
1251
|
+
}
|
|
1252
|
+
buffer = concat2(buffer, utf16);
|
|
1253
|
+
} else {
|
|
1254
|
+
const utf8 = encoder.encode(value2);
|
|
1255
|
+
writeIntHeader(5, utf8.length);
|
|
1256
|
+
buffer = concat2(buffer, utf8);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
function writeData(data) {
|
|
1260
|
+
writeIntHeader(4, data.byteLength);
|
|
1261
|
+
buffer = concat2(buffer, new Uint8Array(data));
|
|
1262
|
+
}
|
|
1263
|
+
function writeIntHeader(kind, value2) {
|
|
1264
|
+
if (value2 < 15) {
|
|
1265
|
+
buffer = writeUInt(buffer, (kind << 4) + value2, 1);
|
|
1266
|
+
} else {
|
|
1267
|
+
buffer = writeUInt(buffer, (kind << 4) + 15, 1);
|
|
1268
|
+
writeNumber(value2);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
function writeID(id) {
|
|
1272
|
+
buffer = writeUInt(buffer, id, idSizeInBytes);
|
|
1273
|
+
}
|
|
1274
|
+
function mustBeUtf16(string) {
|
|
1275
|
+
return encoder.encode(string).byteLength != string.length;
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
var typeofPrimitive = ["string", "number", "boolean", "bigint"];
|
|
1279
|
+
function toEntries(value) {
|
|
1280
|
+
if (typeofPrimitive.includes(typeof value) || value instanceof ArrayBuffer || value instanceof Date || isUID(value)) {
|
|
1281
|
+
return [
|
|
1282
|
+
{
|
|
1283
|
+
type: "primitive",
|
|
1284
|
+
value
|
|
1285
|
+
}
|
|
1286
|
+
];
|
|
1287
|
+
}
|
|
1288
|
+
if (value != null && typeof value === "object") {
|
|
1289
|
+
return Array.isArray(value) ? toEntriesArray(value) : toEntriesObject(value);
|
|
1290
|
+
}
|
|
1291
|
+
throw new Error("unhandled entry: " + value);
|
|
1292
|
+
}
|
|
1293
|
+
function toEntriesArray(array) {
|
|
1294
|
+
const entries = array.map(toEntries);
|
|
1295
|
+
return [
|
|
1296
|
+
{
|
|
1297
|
+
type: "array",
|
|
1298
|
+
value: undefined,
|
|
1299
|
+
entries: entries.map((entries2) => entries2[0])
|
|
1300
|
+
},
|
|
1301
|
+
...entries.flat()
|
|
1302
|
+
];
|
|
1303
|
+
}
|
|
1304
|
+
function toEntriesObject(dict) {
|
|
1305
|
+
const entryKeys = Object.keys(dict).map(toEntries).flat(1);
|
|
1306
|
+
const entryValues = Object.values(dict).map(toEntries);
|
|
1307
|
+
return [
|
|
1308
|
+
{
|
|
1309
|
+
type: "dict",
|
|
1310
|
+
value: undefined,
|
|
1311
|
+
entryKeys,
|
|
1312
|
+
entryValues: entryValues.map((entries) => entries[0])
|
|
1313
|
+
},
|
|
1314
|
+
...entryKeys,
|
|
1315
|
+
...entryValues.flat()
|
|
1316
|
+
];
|
|
1317
|
+
}
|
|
1318
|
+
function computeOffsetSizeInBytes(maxOffset) {
|
|
1319
|
+
if (maxOffset < 256) {
|
|
1320
|
+
return 1;
|
|
1321
|
+
}
|
|
1322
|
+
if (maxOffset < 65536) {
|
|
1323
|
+
return 2;
|
|
1324
|
+
}
|
|
1325
|
+
if (maxOffset < 4294967296) {
|
|
1326
|
+
return 4;
|
|
1327
|
+
}
|
|
1328
|
+
return 8;
|
|
1329
|
+
}
|
|
1330
|
+
function computeIdSizeInBytes(numberOfIds) {
|
|
1331
|
+
if (numberOfIds < 256) {
|
|
1332
|
+
return 1;
|
|
1333
|
+
}
|
|
1334
|
+
if (numberOfIds < 65536) {
|
|
1335
|
+
return 2;
|
|
1336
|
+
}
|
|
1337
|
+
return 4;
|
|
1338
|
+
}
|
|
458
1339
|
// src/rtsp.ts
|
|
459
1340
|
var exports_rtsp = {};
|
|
460
1341
|
__export(exports_rtsp, {
|
|
@@ -569,7 +1450,7 @@ function parseResponseHeaders(buffer) {
|
|
|
569
1450
|
var exports_tlv8 = {};
|
|
570
1451
|
__export(exports_tlv8, {
|
|
571
1452
|
encode: () => encode3,
|
|
572
|
-
decode: () =>
|
|
1453
|
+
decode: () => decode4,
|
|
573
1454
|
bail: () => bail,
|
|
574
1455
|
Value: () => Value,
|
|
575
1456
|
State: () => State,
|
|
@@ -664,7 +1545,7 @@ function encode3(entries) {
|
|
|
664
1545
|
}
|
|
665
1546
|
return Buffer.from(chunks);
|
|
666
1547
|
}
|
|
667
|
-
function
|
|
1548
|
+
function decode4(buf) {
|
|
668
1549
|
const map = new Map;
|
|
669
1550
|
let i = 0;
|
|
670
1551
|
while (i < buf.length) {
|
|
@@ -686,5 +1567,6 @@ export {
|
|
|
686
1567
|
exports_rtsp as RTSP,
|
|
687
1568
|
exports_plist as Plist,
|
|
688
1569
|
exports_opack as OPack,
|
|
689
|
-
exports_ntp as NTP
|
|
1570
|
+
exports_ntp as NTP,
|
|
1571
|
+
exports_daap as DAAP
|
|
690
1572
|
};
|
package/dist/rtsp.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type Method = "GET" | "OPTIONS" | "POST" | "PUT" | "GET_PARAMETER" | "SET_PARAMETER" | "ANNOUNCE" | "RECORD" | "SETUP" | "TEARDOWN";
|
|
1
|
+
export type Method = "GET" | "OPTIONS" | "POST" | "PUT" | "GET_PARAMETER" | "SET_PARAMETER" | "ANNOUNCE" | "FLUSH" | "RECORD" | "SETUP" | "TEARDOWN";
|
|
2
2
|
export declare function makeHeader(method: Method, path: string, headers: HeadersInit, cseq: number, activeRemote: string, dacpId: string, sessionId: string): string;
|
|
3
3
|
export declare function makeRequest(buffer: Buffer): HttpRequest | null;
|
|
4
4
|
export declare function makeResponse(buffer: Buffer): HttpResponse | null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basmilius/apple-encoding",
|
|
3
3
|
"description": "Common encoding utilities for Apple Protocols.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|
|
@@ -38,12 +38,10 @@
|
|
|
38
38
|
"default": "./dist/index.js"
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@plist/binary.parse": "^1.1.0",
|
|
43
|
-
"@plist/binary.serialize": "^1.1.0"
|
|
44
|
-
},
|
|
45
41
|
"devDependencies": {
|
|
46
42
|
"@basmilius/tools": "^2.23.0",
|
|
43
|
+
"@plist/binary.parse": "^1.1.0",
|
|
44
|
+
"@plist/binary.serialize": "^1.1.0",
|
|
47
45
|
"@types/bun": "^1.3.8"
|
|
48
46
|
}
|
|
49
47
|
}
|