appium-ios-remotexpc 0.0.4 → 0.0.5
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/CHANGELOG.md +6 -0
- package/build/src/lib/apple-tv/constants.d.ts +28 -0
- package/build/src/lib/apple-tv/constants.d.ts.map +1 -1
- package/build/src/lib/apple-tv/constants.js +35 -0
- package/build/src/lib/apple-tv/encryption/chacha20-poly1305.d.ts +22 -0
- package/build/src/lib/apple-tv/encryption/chacha20-poly1305.d.ts.map +1 -0
- package/build/src/lib/apple-tv/encryption/chacha20-poly1305.js +97 -0
- package/build/src/lib/apple-tv/encryption/ed25519.d.ts +16 -0
- package/build/src/lib/apple-tv/encryption/ed25519.d.ts.map +1 -0
- package/build/src/lib/apple-tv/encryption/ed25519.js +93 -0
- package/build/src/lib/apple-tv/encryption/hkdf.d.ts +18 -0
- package/build/src/lib/apple-tv/encryption/hkdf.d.ts.map +1 -0
- package/build/src/lib/apple-tv/encryption/hkdf.js +73 -0
- package/build/src/lib/apple-tv/encryption/index.d.ts +5 -0
- package/build/src/lib/apple-tv/encryption/index.d.ts.map +1 -0
- package/build/src/lib/apple-tv/encryption/index.js +4 -0
- package/build/src/lib/apple-tv/encryption/opack2.d.ts +57 -0
- package/build/src/lib/apple-tv/encryption/opack2.d.ts.map +1 -0
- package/build/src/lib/apple-tv/encryption/opack2.js +203 -0
- package/package.json +1 -1
- package/src/lib/apple-tv/constants.ts +42 -0
- package/src/lib/apple-tv/encryption/chacha20-poly1305.ts +147 -0
- package/src/lib/apple-tv/encryption/ed25519.ts +126 -0
- package/src/lib/apple-tv/encryption/hkdf.ts +95 -0
- package/src/lib/apple-tv/encryption/index.ts +11 -0
- package/src/lib/apple-tv/encryption/opack2.ts +257 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import * as constants from '../constants.js';
|
|
2
|
+
import { AppleTVError } from '../errors.js';
|
|
3
|
+
|
|
4
|
+
interface SerializableArray extends Array<SerializableValue> {}
|
|
5
|
+
interface SerializableObject extends Record<string, SerializableValue> {}
|
|
6
|
+
|
|
7
|
+
type SerializableValue =
|
|
8
|
+
| null
|
|
9
|
+
| undefined
|
|
10
|
+
| boolean
|
|
11
|
+
| number
|
|
12
|
+
| string
|
|
13
|
+
| Buffer
|
|
14
|
+
| SerializableArray
|
|
15
|
+
| SerializableObject;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* OPACK2 binary serialization format encoder
|
|
19
|
+
* Implements Apple's OPACK2 protocol for efficient binary serialization of structured data
|
|
20
|
+
*/
|
|
21
|
+
export class Opack2 {
|
|
22
|
+
/**
|
|
23
|
+
* Serializes a JavaScript object to OPACK2 binary format
|
|
24
|
+
* @param obj - The object to serialize (supports primitives, arrays, objects, and Buffers)
|
|
25
|
+
* @returns Buffer containing the serialized data
|
|
26
|
+
* @throws AppleTVError if the object contains unsupported types
|
|
27
|
+
*/
|
|
28
|
+
static dumps(obj: SerializableValue): Buffer {
|
|
29
|
+
return this.encode(obj);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Main encoding dispatcher that routes values to appropriate type-specific encoders
|
|
34
|
+
* @param obj - Value to encode
|
|
35
|
+
* @returns Buffer containing encoded value
|
|
36
|
+
* @throws AppleTVError for unsupported types
|
|
37
|
+
*/
|
|
38
|
+
private static encode(obj: SerializableValue): Buffer {
|
|
39
|
+
if (obj === null || obj === undefined) {
|
|
40
|
+
return Buffer.from([constants.OPACK2_NULL]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (typeof obj === 'boolean') {
|
|
44
|
+
return Buffer.from([
|
|
45
|
+
obj ? constants.OPACK2_TRUE : constants.OPACK2_FALSE,
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (typeof obj === 'number') {
|
|
50
|
+
return this.encodeNumber(obj);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof obj === 'string') {
|
|
54
|
+
return this.encodeString(obj);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (Buffer.isBuffer(obj)) {
|
|
58
|
+
return this.encodeBytes(obj);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (Array.isArray(obj)) {
|
|
62
|
+
return this.encodeArray(obj);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (
|
|
66
|
+
typeof obj === 'object' &&
|
|
67
|
+
!Array.isArray(obj) &&
|
|
68
|
+
!Buffer.isBuffer(obj)
|
|
69
|
+
) {
|
|
70
|
+
return this.encodeDict(obj as Record<string, SerializableValue>);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
throw new AppleTVError(
|
|
74
|
+
`Unsupported type for OPACK2 serialization: ${typeof obj}`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Encodes numeric values with the appropriate size optimization
|
|
80
|
+
* @param num - Number to encode
|
|
81
|
+
* @returns Buffer containing encoded number
|
|
82
|
+
*/
|
|
83
|
+
private static encodeNumber(num: number): Buffer {
|
|
84
|
+
if (!Number.isInteger(num) || num < 0) {
|
|
85
|
+
const buffer = Buffer.allocUnsafe(5);
|
|
86
|
+
buffer[0] = constants.OPACK2_FLOAT_MARKER;
|
|
87
|
+
buffer.writeFloatLE(num, 1);
|
|
88
|
+
return buffer;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (num <= constants.OPACK2_SMALL_INT_MAX) {
|
|
92
|
+
return Buffer.from([num + constants.OPACK2_SMALL_INT_OFFSET]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (num <= constants.OPACK2_UINT8_MAX) {
|
|
96
|
+
return Buffer.from([constants.OPACK2_INT8_MARKER, num]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (num <= constants.OPACK2_UINT32_MAX) {
|
|
100
|
+
const buffer = Buffer.allocUnsafe(5);
|
|
101
|
+
buffer[0] = constants.OPACK2_INT32_MARKER;
|
|
102
|
+
buffer.writeUInt32LE(num, 1);
|
|
103
|
+
return buffer;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (num <= Number.MAX_SAFE_INTEGER) {
|
|
107
|
+
const buffer = Buffer.allocUnsafe(9);
|
|
108
|
+
buffer[0] = constants.OPACK2_INT64_MARKER;
|
|
109
|
+
buffer.writeBigUInt64LE(BigInt(num), 1);
|
|
110
|
+
return buffer;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
throw new AppleTVError(`Number too large for OPACK2 encoding: ${num}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Encodes UTF-8 strings with length-optimized headers
|
|
118
|
+
* @param str - String to encode
|
|
119
|
+
* @returns Buffer containing encoded string
|
|
120
|
+
*/
|
|
121
|
+
private static encodeString(str: string): Buffer {
|
|
122
|
+
const encoded = Buffer.from(str, 'utf8');
|
|
123
|
+
const length = encoded.length;
|
|
124
|
+
|
|
125
|
+
if (length <= constants.OPACK2_SMALL_STRING_MAX) {
|
|
126
|
+
return Buffer.concat([
|
|
127
|
+
Buffer.from([constants.OPACK2_SMALL_STRING_BASE + length]),
|
|
128
|
+
encoded,
|
|
129
|
+
]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (length <= constants.OPACK2_UINT8_MAX) {
|
|
133
|
+
return Buffer.concat([
|
|
134
|
+
Buffer.from([constants.OPACK2_STRING_8BIT_LEN_MARKER, length]),
|
|
135
|
+
encoded,
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (length <= constants.OPACK2_UINT16_MAX) {
|
|
140
|
+
const header = Buffer.allocUnsafe(3);
|
|
141
|
+
header[0] = constants.OPACK2_STRING_16BIT_LEN_MARKER;
|
|
142
|
+
header.writeUInt16BE(length, 1);
|
|
143
|
+
return Buffer.concat([header, encoded]);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (length <= constants.OPACK2_UINT32_MAX) {
|
|
147
|
+
const header = Buffer.allocUnsafe(5);
|
|
148
|
+
header[0] = constants.OPACK2_STRING_32BIT_LEN_MARKER;
|
|
149
|
+
header.writeUInt32BE(length, 1);
|
|
150
|
+
return Buffer.concat([header, encoded]);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
throw new AppleTVError(
|
|
154
|
+
`String too long for OPACK2 encoding: ${length} bytes`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Encodes binary data with length-optimized headers
|
|
160
|
+
* @param bytes - Buffer to encode
|
|
161
|
+
* @returns Buffer containing encoded binary data
|
|
162
|
+
*/
|
|
163
|
+
private static encodeBytes(bytes: Buffer): Buffer {
|
|
164
|
+
const length = bytes.length;
|
|
165
|
+
|
|
166
|
+
if (length <= constants.OPACK2_SMALL_BYTES_MAX) {
|
|
167
|
+
return Buffer.concat([
|
|
168
|
+
Buffer.from([constants.OPACK2_SMALL_BYTES_BASE + length]),
|
|
169
|
+
bytes,
|
|
170
|
+
]);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (length <= constants.OPACK2_UINT8_MAX) {
|
|
174
|
+
return Buffer.concat([
|
|
175
|
+
Buffer.from([constants.OPACK2_BYTES_8BIT_LEN_MARKER, length]),
|
|
176
|
+
bytes,
|
|
177
|
+
]);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (length <= constants.OPACK2_UINT16_MAX) {
|
|
181
|
+
const header = Buffer.allocUnsafe(3);
|
|
182
|
+
header[0] = constants.OPACK2_BYTES_16BIT_LEN_MARKER;
|
|
183
|
+
header.writeUInt16BE(length, 1);
|
|
184
|
+
return Buffer.concat([header, bytes]);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (length <= constants.OPACK2_UINT32_MAX) {
|
|
188
|
+
const header = Buffer.allocUnsafe(5);
|
|
189
|
+
header[0] = constants.OPACK2_BYTES_32BIT_LEN_MARKER;
|
|
190
|
+
header.writeUInt32BE(length, 1);
|
|
191
|
+
return Buffer.concat([header, bytes]);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
throw new AppleTVError(
|
|
195
|
+
`Byte array too long for OPACK2 encoding: ${length} bytes`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Encodes arrays with count-optimized headers
|
|
201
|
+
* @param arr - Array to encode
|
|
202
|
+
* @returns Buffer containing encoded array
|
|
203
|
+
*/
|
|
204
|
+
private static encodeArray(arr: SerializableValue[]): Buffer {
|
|
205
|
+
const length = arr.length;
|
|
206
|
+
|
|
207
|
+
if (length <= constants.OPACK2_SMALL_ARRAY_MAX) {
|
|
208
|
+
const parts: Buffer[] = [
|
|
209
|
+
Buffer.from([constants.OPACK2_SMALL_ARRAY_BASE + length]),
|
|
210
|
+
];
|
|
211
|
+
for (const item of arr) {
|
|
212
|
+
parts.push(this.encode(item));
|
|
213
|
+
}
|
|
214
|
+
return Buffer.concat(parts);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const parts: Buffer[] = [
|
|
218
|
+
Buffer.from([constants.OPACK2_VARIABLE_ARRAY_MARKER]),
|
|
219
|
+
];
|
|
220
|
+
for (const item of arr) {
|
|
221
|
+
parts.push(this.encode(item));
|
|
222
|
+
}
|
|
223
|
+
parts.push(Buffer.from([constants.OPACK2_NULL]));
|
|
224
|
+
return Buffer.concat(parts);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Encodes objects/dictionaries with count-optimized headers
|
|
229
|
+
* @param dict - Object to encode
|
|
230
|
+
* @returns Buffer containing encoded dictionary
|
|
231
|
+
*/
|
|
232
|
+
private static encodeDict(dict: Record<string, SerializableValue>): Buffer {
|
|
233
|
+
const entries = Object.entries(dict);
|
|
234
|
+
const length = entries.length;
|
|
235
|
+
|
|
236
|
+
if (length < constants.OPACK2_SMALL_DICT_MAX) {
|
|
237
|
+
const parts: Buffer[] = [
|
|
238
|
+
Buffer.from([constants.OPACK2_SMALL_DICT_BASE + length]),
|
|
239
|
+
];
|
|
240
|
+
for (const [key, value] of entries) {
|
|
241
|
+
parts.push(this.encode(key));
|
|
242
|
+
parts.push(this.encode(value));
|
|
243
|
+
}
|
|
244
|
+
return Buffer.concat(parts);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const parts: Buffer[] = [
|
|
248
|
+
Buffer.from([constants.OPACK2_VARIABLE_DICT_MARKER]),
|
|
249
|
+
];
|
|
250
|
+
for (const [key, value] of entries) {
|
|
251
|
+
parts.push(this.encode(key));
|
|
252
|
+
parts.push(this.encode(value));
|
|
253
|
+
}
|
|
254
|
+
parts.push(Buffer.from([constants.OPACK2_NULL, constants.OPACK2_NULL]));
|
|
255
|
+
return Buffer.concat(parts);
|
|
256
|
+
}
|
|
257
|
+
}
|