appium-ios-remotexpc 0.0.3 → 0.0.4

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 (192) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/src/base-plist-service.d.ts +51 -0
  3. package/build/src/base-plist-service.d.ts.map +1 -0
  4. package/build/src/base-plist-service.js +61 -0
  5. package/build/src/base-socket-service.d.ts +15 -0
  6. package/build/src/base-socket-service.d.ts.map +1 -0
  7. package/build/src/base-socket-service.js +46 -0
  8. package/build/src/index.d.ts +9 -0
  9. package/build/src/index.d.ts.map +1 -0
  10. package/build/src/index.js +7 -0
  11. package/build/src/lib/apple-tv/constants.d.ts +49 -0
  12. package/build/src/lib/apple-tv/constants.d.ts.map +1 -0
  13. package/build/src/lib/apple-tv/constants.js +71 -0
  14. package/build/src/lib/apple-tv/errors.d.ts +17 -0
  15. package/build/src/lib/apple-tv/errors.d.ts.map +1 -0
  16. package/build/src/lib/apple-tv/errors.js +30 -0
  17. package/build/src/lib/apple-tv/tlv/decoder.d.ts +19 -0
  18. package/build/src/lib/apple-tv/tlv/decoder.d.ts.map +1 -0
  19. package/build/src/lib/apple-tv/tlv/decoder.js +49 -0
  20. package/build/src/lib/apple-tv/tlv/encoder.d.ts +10 -0
  21. package/build/src/lib/apple-tv/tlv/encoder.d.ts.map +1 -0
  22. package/build/src/lib/apple-tv/tlv/encoder.js +20 -0
  23. package/build/src/lib/apple-tv/tlv/index.d.ts +4 -0
  24. package/build/src/lib/apple-tv/tlv/index.d.ts.map +1 -0
  25. package/build/src/lib/apple-tv/tlv/index.js +3 -0
  26. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts +14 -0
  27. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts.map +1 -0
  28. package/build/src/lib/apple-tv/tlv/pairing-tlv.js +27 -0
  29. package/build/src/lib/apple-tv/types.d.ts +36 -0
  30. package/build/src/lib/apple-tv/types.d.ts.map +1 -0
  31. package/build/src/lib/apple-tv/types.js +1 -0
  32. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts +40 -0
  33. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts.map +1 -0
  34. package/build/src/lib/apple-tv/utils/buffer-utils.js +76 -0
  35. package/build/src/lib/apple-tv/utils/index.d.ts +3 -0
  36. package/build/src/lib/apple-tv/utils/index.d.ts.map +1 -0
  37. package/build/src/lib/apple-tv/utils/index.js +2 -0
  38. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts +9 -0
  39. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts.map +1 -0
  40. package/build/src/lib/apple-tv/utils/uuid-generator.js +36 -0
  41. package/build/src/lib/lockdown/index.d.ts +87 -0
  42. package/build/src/lib/lockdown/index.d.ts.map +1 -0
  43. package/build/src/lib/lockdown/index.js +324 -0
  44. package/build/src/lib/pair-record/index.d.ts +3 -0
  45. package/build/src/lib/pair-record/index.d.ts.map +1 -0
  46. package/build/src/lib/pair-record/index.js +2 -0
  47. package/build/src/lib/pair-record/pair-record.d.ts +48 -0
  48. package/build/src/lib/pair-record/pair-record.d.ts.map +1 -0
  49. package/build/src/lib/pair-record/pair-record.js +85 -0
  50. package/build/src/lib/plist/binary-plist-creator.d.ts +14 -0
  51. package/build/src/lib/plist/binary-plist-creator.d.ts.map +1 -0
  52. package/build/src/lib/plist/binary-plist-creator.js +475 -0
  53. package/build/src/lib/plist/binary-plist-parser.d.ts +14 -0
  54. package/build/src/lib/plist/binary-plist-parser.d.ts.map +1 -0
  55. package/build/src/lib/plist/binary-plist-parser.js +449 -0
  56. package/build/src/lib/plist/constants.d.ts +36 -0
  57. package/build/src/lib/plist/constants.d.ts.map +1 -0
  58. package/build/src/lib/plist/constants.js +43 -0
  59. package/build/src/lib/plist/index.d.ts +14 -0
  60. package/build/src/lib/plist/index.d.ts.map +1 -0
  61. package/build/src/lib/plist/index.js +16 -0
  62. package/build/src/lib/plist/length-based-splitter.d.ts +43 -0
  63. package/build/src/lib/plist/length-based-splitter.d.ts.map +1 -0
  64. package/build/src/lib/plist/length-based-splitter.js +228 -0
  65. package/build/src/lib/plist/plist-creator.d.ts +8 -0
  66. package/build/src/lib/plist/plist-creator.d.ts.map +1 -0
  67. package/build/src/lib/plist/plist-creator.js +33 -0
  68. package/build/src/lib/plist/plist-decoder.d.ts +25 -0
  69. package/build/src/lib/plist/plist-decoder.d.ts.map +1 -0
  70. package/build/src/lib/plist/plist-decoder.js +103 -0
  71. package/build/src/lib/plist/plist-encoder.d.ts +10 -0
  72. package/build/src/lib/plist/plist-encoder.d.ts.map +1 -0
  73. package/build/src/lib/plist/plist-encoder.js +27 -0
  74. package/build/src/lib/plist/plist-parser.d.ts +9 -0
  75. package/build/src/lib/plist/plist-parser.d.ts.map +1 -0
  76. package/build/src/lib/plist/plist-parser.js +109 -0
  77. package/build/src/lib/plist/plist-service.d.ts +86 -0
  78. package/build/src/lib/plist/plist-service.d.ts.map +1 -0
  79. package/build/src/lib/plist/plist-service.js +180 -0
  80. package/build/src/lib/plist/unified-plist-creator.d.ts +9 -0
  81. package/build/src/lib/plist/unified-plist-creator.d.ts.map +1 -0
  82. package/build/src/lib/plist/unified-plist-creator.js +14 -0
  83. package/build/src/lib/plist/unified-plist-parser.d.ts +8 -0
  84. package/build/src/lib/plist/unified-plist-parser.d.ts.map +1 -0
  85. package/build/src/lib/plist/unified-plist-parser.js +23 -0
  86. package/build/src/lib/plist/utils.d.ts +97 -0
  87. package/build/src/lib/plist/utils.d.ts.map +1 -0
  88. package/build/src/lib/plist/utils.js +287 -0
  89. package/build/src/lib/remote-xpc/constants.d.ts +20 -0
  90. package/build/src/lib/remote-xpc/constants.d.ts.map +1 -0
  91. package/build/src/lib/remote-xpc/constants.js +21 -0
  92. package/build/src/lib/remote-xpc/handshake-frames.d.ts +74 -0
  93. package/build/src/lib/remote-xpc/handshake-frames.d.ts.map +1 -0
  94. package/build/src/lib/remote-xpc/handshake-frames.js +285 -0
  95. package/build/src/lib/remote-xpc/handshake.d.ts +14 -0
  96. package/build/src/lib/remote-xpc/handshake.d.ts.map +1 -0
  97. package/build/src/lib/remote-xpc/handshake.js +95 -0
  98. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts +55 -0
  99. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts.map +1 -0
  100. package/build/src/lib/remote-xpc/remote-xpc-connection.js +365 -0
  101. package/build/src/lib/remote-xpc/xpc-protocol.d.ts +22 -0
  102. package/build/src/lib/remote-xpc/xpc-protocol.d.ts.map +1 -0
  103. package/build/src/lib/remote-xpc/xpc-protocol.js +368 -0
  104. package/build/src/lib/tunnel/index.d.ts +69 -0
  105. package/build/src/lib/tunnel/index.d.ts.map +1 -0
  106. package/build/src/lib/tunnel/index.js +205 -0
  107. package/build/src/lib/tunnel/packet-stream-client.d.ts +46 -0
  108. package/build/src/lib/tunnel/packet-stream-client.d.ts.map +1 -0
  109. package/build/src/lib/tunnel/packet-stream-client.js +152 -0
  110. package/build/src/lib/tunnel/packet-stream-server.d.ts +37 -0
  111. package/build/src/lib/tunnel/packet-stream-server.d.ts.map +1 -0
  112. package/build/src/lib/tunnel/packet-stream-server.js +109 -0
  113. package/build/src/lib/tunnel/tunnel-api-client.d.ts +85 -0
  114. package/build/src/lib/tunnel/tunnel-api-client.d.ts.map +1 -0
  115. package/build/src/lib/tunnel/tunnel-api-client.js +207 -0
  116. package/build/src/lib/tunnel/tunnel-registry-server.d.ts +68 -0
  117. package/build/src/lib/tunnel/tunnel-registry-server.d.ts.map +1 -0
  118. package/build/src/lib/tunnel/tunnel-registry-server.js +351 -0
  119. package/build/src/lib/types.d.ts +238 -0
  120. package/build/src/lib/types.d.ts.map +1 -0
  121. package/build/src/lib/types.js +4 -0
  122. package/build/src/lib/usbmux/index.d.ts +177 -0
  123. package/build/src/lib/usbmux/index.d.ts.map +1 -0
  124. package/build/src/lib/usbmux/index.js +490 -0
  125. package/build/src/lib/usbmux/usbmux-decoder.d.ts +19 -0
  126. package/build/src/lib/usbmux/usbmux-decoder.d.ts.map +1 -0
  127. package/build/src/lib/usbmux/usbmux-decoder.js +38 -0
  128. package/build/src/lib/usbmux/usbmux-encoder.d.ts +12 -0
  129. package/build/src/lib/usbmux/usbmux-encoder.d.ts.map +1 -0
  130. package/build/src/lib/usbmux/usbmux-encoder.js +32 -0
  131. package/build/src/service-connection.d.ts +34 -0
  132. package/build/src/service-connection.d.ts.map +1 -0
  133. package/build/src/service-connection.js +51 -0
  134. package/build/src/services/index.d.ts +6 -0
  135. package/build/src/services/index.d.ts.map +1 -0
  136. package/build/src/services/index.js +5 -0
  137. package/build/src/services/ios/base-service.d.ts +35 -0
  138. package/build/src/services/ios/base-service.d.ts.map +1 -0
  139. package/build/src/services/ios/base-service.js +55 -0
  140. package/build/src/services/ios/diagnostic-service/index.d.ts +46 -0
  141. package/build/src/services/ios/diagnostic-service/index.d.ts.map +1 -0
  142. package/build/src/services/ios/diagnostic-service/index.js +169 -0
  143. package/build/src/services/ios/diagnostic-service/keys.d.ts +5 -0
  144. package/build/src/services/ios/diagnostic-service/keys.d.ts.map +1 -0
  145. package/build/src/services/ios/diagnostic-service/keys.js +770 -0
  146. package/build/src/services/ios/syslog-service/index.d.ts +91 -0
  147. package/build/src/services/ios/syslog-service/index.d.ts.map +1 -0
  148. package/build/src/services/ios/syslog-service/index.js +323 -0
  149. package/build/src/services/ios/tunnel-service/index.d.ts +17 -0
  150. package/build/src/services/ios/tunnel-service/index.d.ts.map +1 -0
  151. package/build/src/services/ios/tunnel-service/index.js +57 -0
  152. package/build/src/services.d.ts +14 -0
  153. package/build/src/services.d.ts.map +1 -0
  154. package/build/src/services.js +48 -0
  155. package/package.json +12 -3
  156. package/.github/dependabot.yml +0 -38
  157. package/.github/workflows/format-check.yml +0 -43
  158. package/.github/workflows/lint-and-build.yml +0 -40
  159. package/.github/workflows/pr-title.yml +0 -16
  160. package/.github/workflows/publish.js.yml +0 -43
  161. package/.github/workflows/test-validation.yml +0 -40
  162. package/.mocharc.json +0 -8
  163. package/.prettierignore +0 -3
  164. package/.prettierrc +0 -17
  165. package/.releaserc +0 -48
  166. package/assets/images/ios-arch.png +0 -0
  167. package/eslint.config.js +0 -45
  168. package/npm-shrinkwrap.json +0 -2711
  169. package/test/integration/diagnostics-test.ts +0 -44
  170. package/test/integration/read-pair-record-test.ts +0 -39
  171. package/test/integration/tunnel-test.ts +0 -104
  172. package/test/unit/apple-tv/tlv/decoder.spec.ts +0 -144
  173. package/test/unit/apple-tv/tlv/encoder.spec.ts +0 -91
  174. package/test/unit/apple-tv/tlv/pairing-tlv.spec.ts +0 -101
  175. package/test/unit/apple-tv/tlv/tlv-integration.spec.ts +0 -146
  176. package/test/unit/apple-tv/utils/buffer-utils.spec.ts +0 -74
  177. package/test/unit/apple-tv/utils/uuid-generator.spec.ts +0 -39
  178. package/test/unit/fixtures/index.ts +0 -88
  179. package/test/unit/fixtures/usbmuxconnectmessage.bin +0 -0
  180. package/test/unit/fixtures/usbmuxlistdevicemessage.bin +0 -0
  181. package/test/unit/plist/error-handling.spec.ts +0 -101
  182. package/test/unit/plist/fixtures/sample.binary.plist +0 -0
  183. package/test/unit/plist/fixtures/sample.xml.plist +0 -38
  184. package/test/unit/plist/plist-parser.spec.ts +0 -283
  185. package/test/unit/plist/plist.spec.ts +0 -205
  186. package/test/unit/plist/tag-position-handling.spec.ts +0 -90
  187. package/test/unit/plist/unified-plist-parser.spec.ts +0 -227
  188. package/test/unit/plist/utils.spec.ts +0 -249
  189. package/test/unit/plist/xml-cleaning.spec.ts +0 -60
  190. package/test/unit/tunnel/tunnel-registry-server.spec.ts +0 -194
  191. package/test/unit/usbmux/usbmux-specs.ts +0 -71
  192. package/tsconfig.json +0 -36
@@ -0,0 +1,449 @@
1
+ /**
2
+ * Binary Property List (bplist) Parser
3
+ *
4
+ * This module provides functionality to parse binary property lists (bplists)
5
+ * commonly used in Apple's iOS and macOS systems.
6
+ */
7
+ import { logger } from '@appium/support';
8
+ import { APPLE_EPOCH_OFFSET, BPLIST_MAGIC_AND_VERSION, BPLIST_TRAILER_SIZE, BPLIST_TYPE, } from './constants.js';
9
+ const log = logger.getLogger('Plist');
10
+ /**
11
+ * Class for parsing binary property lists
12
+ */
13
+ class BinaryPlistParser {
14
+ _buffer;
15
+ _offsetSize;
16
+ _objectRefSize;
17
+ _numObjects;
18
+ _topObject;
19
+ _offsetTableOffset;
20
+ _objectTable;
21
+ /**
22
+ * Creates a new BinaryPlistParser
23
+ * @param buffer - The binary plist data as a Buffer
24
+ */
25
+ constructor(buffer) {
26
+ this._buffer = buffer;
27
+ this._objectTable = [];
28
+ // Initialize with default values, will be set in parseTrailer
29
+ this._offsetSize = 0;
30
+ this._objectRefSize = 0;
31
+ this._numObjects = 0;
32
+ this._topObject = 0;
33
+ this._offsetTableOffset = 0;
34
+ }
35
+ /**
36
+ * Parses the binary plist
37
+ * @returns The parsed JavaScript object
38
+ */
39
+ parse() {
40
+ this._validateHeader();
41
+ this._parseTrailer();
42
+ this._parseObjects();
43
+ this._resolveReferences();
44
+ return this._handleTopObject();
45
+ }
46
+ /**
47
+ * Validates the binary plist header
48
+ * @throws Error if the buffer is not a valid binary plist
49
+ */
50
+ _validateHeader() {
51
+ if (this._buffer.length < 8 ||
52
+ !this._buffer.slice(0, 8).equals(BPLIST_MAGIC_AND_VERSION)) {
53
+ throw new Error('Not a binary plist. Expected bplist00 magic.');
54
+ }
55
+ }
56
+ /**
57
+ * Parses the trailer section of the binary plist
58
+ * @throws Error if the buffer is too small to contain a trailer
59
+ */
60
+ _parseTrailer() {
61
+ if (this._buffer.length < BPLIST_TRAILER_SIZE) {
62
+ throw new Error('Binary plist is too small to contain a trailer.');
63
+ }
64
+ const trailer = this._buffer.slice(this._buffer.length - BPLIST_TRAILER_SIZE);
65
+ // Extract trailer information
66
+ this._offsetSize = trailer.readUInt8(6);
67
+ this._objectRefSize = trailer.readUInt8(7);
68
+ this._numObjects = Number(trailer.readBigUInt64BE(8));
69
+ this._topObject = Number(trailer.readBigUInt64BE(16));
70
+ this._offsetTableOffset = Number(trailer.readBigUInt64BE(24));
71
+ }
72
+ /**
73
+ * Reads an object reference from the buffer
74
+ * @param offset - The offset to read from
75
+ * @returns The object reference index
76
+ */
77
+ /**
78
+ * Helper method to read multi-byte integers safely, handling potential overflow
79
+ * @param startOffset - The offset to start reading from
80
+ * @param byteCount - The number of bytes to read
81
+ * @param valueName - Name of the value type for error messages
82
+ * @returns The parsed integer value
83
+ */
84
+ _readMultiByteInteger(startOffset, byteCount, valueName) {
85
+ // Use BigInt for calculations if byteCount is large enough to potentially overflow
86
+ if (byteCount > 6) {
87
+ // 6 bytes = 48 bits, safely under MAX_SAFE_INTEGER
88
+ let result = 0n;
89
+ for (let i = 0; i < byteCount; i++) {
90
+ result =
91
+ (result << 8n) | BigInt(this._buffer.readUInt8(startOffset + i));
92
+ }
93
+ // Check if the value exceeds MAX_SAFE_INTEGER
94
+ if (result > BigInt(Number.MAX_SAFE_INTEGER)) {
95
+ throw new Error(`${valueName} value ${result} exceeds MAX_SAFE_INTEGER. Cannot safely convert to number.`);
96
+ }
97
+ // Safe to convert to number without precision loss
98
+ return Number(result);
99
+ }
100
+ // Use regular number arithmetic for smaller values
101
+ let result = 0;
102
+ for (let i = 0; i < byteCount; i++) {
103
+ result = (result << 8) | this._buffer.readUInt8(startOffset + i);
104
+ }
105
+ return result;
106
+ }
107
+ _readObjectRef(offset) {
108
+ return this._readMultiByteInteger(offset, this._objectRefSize, 'Object reference');
109
+ }
110
+ /**
111
+ * Reads an offset from the offset table
112
+ * @param index - The index in the offset table
113
+ * @returns The offset value
114
+ */
115
+ _readOffset(index) {
116
+ const offsetStart = this._offsetTableOffset + index * this._offsetSize;
117
+ return this._readMultiByteInteger(offsetStart, this._offsetSize, 'Offset');
118
+ }
119
+ /**
120
+ * Parses an integer value from the buffer
121
+ * @param startOffset - The offset to start reading from
122
+ * @param intByteCount - The number of bytes to read
123
+ * @returns The parsed integer value (number or bigint)
124
+ */
125
+ _parseIntegerValue(startOffset, intByteCount) {
126
+ // Handle different integer sizes
127
+ switch (intByteCount) {
128
+ case 1:
129
+ return this._buffer.readInt8(startOffset);
130
+ case 2:
131
+ return this._buffer.readInt16BE(startOffset);
132
+ case 4:
133
+ return this._buffer.readInt32BE(startOffset);
134
+ case 8: {
135
+ // For 64-bit integers, we need to handle potential precision loss
136
+ const bigInt = this._buffer.readBigInt64BE(startOffset);
137
+ const intValue = Number(bigInt);
138
+ // Check if conversion to Number caused precision loss
139
+ if (BigInt(intValue) !== bigInt) {
140
+ log.warn('Precision loss when converting 64-bit integer to Number. Returning BigInt value.');
141
+ return bigInt; // Return the BigInt directly to avoid precision loss
142
+ }
143
+ return intValue; // Return as number if no precision loss
144
+ }
145
+ default:
146
+ throw new TypeError(`Unexpected integer byte count: ${intByteCount}. Cannot parse integer value.`);
147
+ }
148
+ }
149
+ /**
150
+ * Parses a real (floating point) value from the buffer
151
+ * @param startOffset - The offset to start reading from
152
+ * @param floatByteCount - The number of bytes to read
153
+ * @returns The parsed floating point value
154
+ */
155
+ _parseRealValue(startOffset, floatByteCount) {
156
+ switch (floatByteCount) {
157
+ case 4:
158
+ return this._buffer.readFloatBE(startOffset);
159
+ case 8:
160
+ return this._buffer.readDoubleBE(startOffset);
161
+ default:
162
+ throw new TypeError(`Unexpected float byte count: ${floatByteCount}. Cannot parse real value.`);
163
+ }
164
+ }
165
+ /**
166
+ * Parses a date value from the buffer
167
+ * @param startOffset - The offset to start reading from
168
+ * @returns The parsed Date object
169
+ */
170
+ _parseDateValue(startOffset) {
171
+ // Date is stored as a float, seconds since 2001-01-01
172
+ const timestamp = this._buffer.readDoubleBE(startOffset);
173
+ // Convert Apple epoch (2001-01-01) to Unix epoch (1970-01-01)
174
+ return new Date((timestamp + APPLE_EPOCH_OFFSET) * 1000);
175
+ }
176
+ /**
177
+ * Parses a data value from the buffer
178
+ * @param startOffset - The offset to start reading from
179
+ * @param objLength - The length of the data
180
+ * @returns The parsed Buffer
181
+ */
182
+ _parseDataValue(startOffset, objLength) {
183
+ return Buffer.from(this._buffer.slice(startOffset, startOffset + objLength));
184
+ }
185
+ /**
186
+ * Parses an ASCII string from the buffer
187
+ * @param startOffset - The offset to start reading from
188
+ * @param objLength - The length of the string
189
+ * @returns The parsed string
190
+ */
191
+ _parseAsciiString(startOffset, objLength) {
192
+ return this._buffer
193
+ .slice(startOffset, startOffset + objLength)
194
+ .toString('ascii');
195
+ }
196
+ /**
197
+ * Parses a Unicode string from the buffer
198
+ * @param startOffset - The offset to start reading from
199
+ * @param objLength - The length of the string in characters
200
+ * @returns The parsed string
201
+ */
202
+ _parseUnicodeString(startOffset, objLength) {
203
+ // Unicode strings are stored as UTF-16BE
204
+ const utf16Buffer = Buffer.alloc(objLength * 2);
205
+ for (let j = 0; j < objLength; j++) {
206
+ utf16Buffer.writeUInt16BE(this._buffer.readUInt16BE(startOffset + j * 2), j * 2);
207
+ }
208
+ return utf16Buffer.toString('utf16le', 0, objLength * 2);
209
+ }
210
+ /**
211
+ * Parses a UID value from the buffer
212
+ * @param startOffset - The offset to start reading from
213
+ * @param uidByteCount - The number of bytes to read
214
+ * @returns The parsed UID value
215
+ */
216
+ _parseUidValue(startOffset, uidByteCount) {
217
+ return this._readMultiByteInteger(startOffset, uidByteCount, 'UID');
218
+ }
219
+ /**
220
+ * Parses all objects in the binary plist
221
+ */
222
+ _parseObjects() {
223
+ for (let i = 0; i < this._numObjects; i++) {
224
+ const objOffset = this._readOffset(i);
225
+ const objType = this._buffer.readUInt8(objOffset) & 0xf0;
226
+ const objInfo = this._buffer.readUInt8(objOffset) & 0x0f;
227
+ let objLength = objInfo;
228
+ let startOffset = objOffset + 1;
229
+ // For objects with length > 15, the actual length follows
230
+ if (objInfo === 0x0f) {
231
+ const intType = this._buffer.readUInt8(startOffset) & 0xf0;
232
+ if (intType !== BPLIST_TYPE.INT) {
233
+ throw new TypeError(`Expected integer type for length at offset ${startOffset}`);
234
+ }
235
+ const intInfo = this._buffer.readUInt8(startOffset) & 0x0f;
236
+ startOffset++;
237
+ // Read the length based on the integer size
238
+ const intByteCount = 1 << intInfo;
239
+ objLength = this._readMultiByteInteger(startOffset, intByteCount, 'Object length');
240
+ startOffset += intByteCount;
241
+ }
242
+ // Parse the object based on its type
243
+ this._objectTable[i] = this._parseObjectByType(objType, objInfo, startOffset, objLength);
244
+ }
245
+ }
246
+ /**
247
+ * Parses an object based on its type
248
+ * @param objType - The object type
249
+ * @param objInfo - The object info
250
+ * @param startOffset - The start offset
251
+ * @param objLength - The object length
252
+ * @returns The parsed object
253
+ */
254
+ _parseObjectByType(objType, objInfo, startOffset, objLength) {
255
+ switch (objType) {
256
+ case BPLIST_TYPE.NULL:
257
+ return this._parseNullType(objInfo);
258
+ case BPLIST_TYPE.INT:
259
+ return this._parseIntegerValue(startOffset, 1 << objInfo);
260
+ case BPLIST_TYPE.REAL:
261
+ return this._parseRealValue(startOffset, 1 << objInfo);
262
+ case BPLIST_TYPE.DATE:
263
+ return this._parseDateValue(startOffset);
264
+ case BPLIST_TYPE.DATA:
265
+ return this._parseDataValue(startOffset, objLength);
266
+ case BPLIST_TYPE.STRING_ASCII:
267
+ return this._parseAsciiString(startOffset, objLength);
268
+ case BPLIST_TYPE.STRING_UNICODE:
269
+ return this._parseUnicodeString(startOffset, objLength);
270
+ case BPLIST_TYPE.UID:
271
+ return this._parseUidValue(startOffset, objInfo + 1);
272
+ case BPLIST_TYPE.ARRAY:
273
+ return this._createTempArray(objLength, startOffset);
274
+ case BPLIST_TYPE.DICT:
275
+ return this._createTempDict(objLength, startOffset);
276
+ default:
277
+ throw new TypeError(`Unsupported binary plist object type: ${objType.toString(16)}`);
278
+ }
279
+ }
280
+ /**
281
+ * Parses a null type object
282
+ * @param objInfo - The object info
283
+ * @returns The parsed value (null, false, or true)
284
+ */
285
+ _parseNullType(objInfo) {
286
+ switch (objInfo) {
287
+ case 0x00:
288
+ return null;
289
+ case 0x08:
290
+ return false;
291
+ case 0x09:
292
+ return true;
293
+ case 0x0f:
294
+ return null; // fill byte
295
+ default:
296
+ throw new TypeError(`Unexpected null type object info: 0x${objInfo.toString(16)}. Cannot parse null value.`);
297
+ }
298
+ }
299
+ /**
300
+ * Creates a temporary array object
301
+ * @param objLength - The array length
302
+ * @param startOffset - The start offset
303
+ * @returns The temporary array object
304
+ */
305
+ _createTempArray(objLength, startOffset) {
306
+ return {
307
+ type: 'array',
308
+ objLength,
309
+ startOffset,
310
+ value: [],
311
+ };
312
+ }
313
+ /**
314
+ * Creates a temporary dictionary object
315
+ * @param objLength - The dictionary length
316
+ * @param startOffset - The start offset
317
+ * @returns The temporary dictionary object
318
+ */
319
+ _createTempDict(objLength, startOffset) {
320
+ return {
321
+ type: 'dict',
322
+ objLength,
323
+ startOffset,
324
+ value: {},
325
+ };
326
+ }
327
+ /**
328
+ * Type guard to check if an object is a TempObject
329
+ * @param obj - The object to check
330
+ * @returns True if the object is a TempObject
331
+ */
332
+ _isTempObject(obj) {
333
+ return typeof obj === 'object' && obj !== null && 'type' in obj;
334
+ }
335
+ /**
336
+ * Resolves references for arrays and dictionaries
337
+ */
338
+ _resolveReferences() {
339
+ for (let i = 0; i < this._numObjects; i++) {
340
+ const obj = this._objectTable[i];
341
+ if (this._isTempObject(obj)) {
342
+ if (obj.type === 'array') {
343
+ this._resolveArrayReferences(obj, i);
344
+ }
345
+ else if (obj.type === 'dict') {
346
+ this._resolveDictReferences(obj, i);
347
+ }
348
+ }
349
+ }
350
+ }
351
+ /**
352
+ * Resolves references for an array
353
+ * @param obj - The temporary array object
354
+ * @param index - The index in the object table
355
+ */
356
+ _resolveArrayReferences(obj, index) {
357
+ const array = obj.value;
358
+ for (let j = 0; j < obj.objLength; j++) {
359
+ const refIdx = this._readObjectRef(obj.startOffset + j * this._objectRefSize);
360
+ const refValue = this._objectTable[refIdx];
361
+ // Ensure we're not adding a TempObject to the array
362
+ if (!this._isTempObject(refValue)) {
363
+ array.push(refValue);
364
+ }
365
+ }
366
+ this._objectTable[index] = array;
367
+ }
368
+ /**
369
+ * Resolves references for a dictionary
370
+ * @param obj - The temporary dictionary object
371
+ * @param index - The index in the object table
372
+ */
373
+ _resolveDictReferences(obj, index) {
374
+ const dict = obj.value;
375
+ const keyCount = obj.objLength;
376
+ // Keys are stored first, followed by values
377
+ for (let j = 0; j < keyCount; j++) {
378
+ const keyRef = this._readObjectRef(obj.startOffset + j * this._objectRefSize);
379
+ const valueRef = this._readObjectRef(obj.startOffset + (keyCount + j) * this._objectRefSize);
380
+ const key = this._objectTable[keyRef];
381
+ const value = this._objectTable[valueRef];
382
+ if (typeof key !== 'string') {
383
+ throw new TypeError(`Dictionary key must be a string, got ${typeof key}`);
384
+ }
385
+ // Ensure we're not adding a TempObject to the dictionary
386
+ if (!this._isTempObject(value)) {
387
+ dict[key] = value;
388
+ }
389
+ }
390
+ this._objectTable[index] = dict;
391
+ }
392
+ /**
393
+ * Handles special case for the top object
394
+ * @returns The final parsed value
395
+ */
396
+ _handleTopObject() {
397
+ // If the top object is an empty object but we have key-value pairs in the array format,
398
+ // convert it to a proper object
399
+ if (this._topObject === 0 &&
400
+ this._objectTable[0] &&
401
+ typeof this._objectTable[0] === 'object' &&
402
+ !this._isTempObject(this._objectTable[0]) &&
403
+ Object.keys(this._objectTable[0]).length === 0 &&
404
+ this._objectTable.length > 1) {
405
+ return this._convertArrayToDict();
406
+ }
407
+ // Ensure the top object is a PlistValue and not a TempObject
408
+ const topValue = this._objectTable[this._topObject];
409
+ if (this._isTempObject(topValue)) {
410
+ return topValue.value;
411
+ }
412
+ return topValue;
413
+ }
414
+ /**
415
+ * Converts an array format to a dictionary
416
+ * @returns The converted dictionary
417
+ */
418
+ _convertArrayToDict() {
419
+ const result = {};
420
+ // Process the array in key-value pairs
421
+ for (let i = 1; i < this._objectTable.length; i += 2) {
422
+ const key = this._objectTable[i];
423
+ if (i + 1 < this._objectTable.length && typeof key === 'string') {
424
+ const value = this._objectTable[i + 1];
425
+ if (!this._isTempObject(value)) {
426
+ result[key] = value;
427
+ }
428
+ }
429
+ }
430
+ return result;
431
+ }
432
+ }
433
+ /**
434
+ * Parses a binary plist buffer into a JavaScript object
435
+ * @param buffer - The binary plist data as a Buffer
436
+ * @returns The parsed JavaScript object
437
+ */
438
+ export function parseBinaryPlist(buffer) {
439
+ const parser = new BinaryPlistParser(buffer);
440
+ return parser.parse();
441
+ }
442
+ /**
443
+ * Determines if a buffer is a binary plist
444
+ * @param buffer - The buffer to check
445
+ * @returns True if the buffer is a binary plist
446
+ */
447
+ export function isBinaryPlist(buffer) {
448
+ return (buffer.length >= 8 && buffer.slice(0, 8).equals(BPLIST_MAGIC_AND_VERSION));
449
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Common constants for plist operations
3
+ */
4
+ export declare const BPLIST_MAGIC = "bplist";
5
+ export declare const BPLIST_VERSION = "00";
6
+ export declare const BPLIST_MAGIC_AND_VERSION: Buffer<ArrayBuffer>;
7
+ export declare const BINARY_PLIST_MAGIC = "bplist00";
8
+ export declare const IBINARY_PLIST_MAGIC = "Ibplist00";
9
+ export declare const BINARY_PLIST_HEADER_LENGTH = 9;
10
+ export declare const XML_DECLARATION = "<?xml";
11
+ export declare const PLIST_CLOSING_TAG = "</plist>";
12
+ export declare const LENGTH_FIELD_1_BYTE = 1;
13
+ export declare const LENGTH_FIELD_2_BYTES = 2;
14
+ export declare const LENGTH_FIELD_4_BYTES = 4;
15
+ export declare const LENGTH_FIELD_8_BYTES = 8;
16
+ export declare const UINT32_HIGH_MULTIPLIER = 4294967296;
17
+ export declare const UTF8_ENCODING = "utf8";
18
+ export declare const APPLE_EPOCH_OFFSET = 978307200;
19
+ export declare const BPLIST_TRAILER_SIZE = 32;
20
+ export declare const BPLIST_TYPE: {
21
+ NULL: number;
22
+ FALSE: number;
23
+ TRUE: number;
24
+ FILL: number;
25
+ INT: number;
26
+ REAL: number;
27
+ DATE: number;
28
+ DATA: number;
29
+ STRING_ASCII: number;
30
+ STRING_UNICODE: number;
31
+ UID: number;
32
+ ARRAY: number;
33
+ SET: number;
34
+ DICT: number;
35
+ };
36
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,cAAc,OAAO,CAAC;AACnC,eAAO,MAAM,wBAAwB,qBAEpC,CAAC;AAGF,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAC/C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAG5C,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAG5C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,sBAAsB,aAAc,CAAC;AAGlD,eAAO,MAAM,aAAa,SAAS,CAAC;AAGpC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAG5C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAGtC,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;CAevB,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Common constants for plist operations
3
+ */
4
+ // Constants for binary plist format
5
+ export const BPLIST_MAGIC = 'bplist';
6
+ export const BPLIST_VERSION = '00';
7
+ export const BPLIST_MAGIC_AND_VERSION = Buffer.from(`${BPLIST_MAGIC}${BPLIST_VERSION}`);
8
+ // Binary plist header constants
9
+ export const BINARY_PLIST_MAGIC = 'bplist00';
10
+ export const IBINARY_PLIST_MAGIC = 'Ibplist00';
11
+ export const BINARY_PLIST_HEADER_LENGTH = 9;
12
+ // XML plist constants
13
+ export const XML_DECLARATION = '<?xml';
14
+ export const PLIST_CLOSING_TAG = '</plist>';
15
+ // Length field constants
16
+ export const LENGTH_FIELD_1_BYTE = 1;
17
+ export const LENGTH_FIELD_2_BYTES = 2;
18
+ export const LENGTH_FIELD_4_BYTES = 4;
19
+ export const LENGTH_FIELD_8_BYTES = 8;
20
+ export const UINT32_HIGH_MULTIPLIER = 0x100000000;
21
+ // Encoding constants
22
+ export const UTF8_ENCODING = 'utf8';
23
+ // Apple epoch offset (seconds between Unix epoch 1970-01-01 and Apple epoch 2001-01-01)
24
+ export const APPLE_EPOCH_OFFSET = 978307200;
25
+ // Binary plist trailer size (last 32 bytes of the file)
26
+ export const BPLIST_TRAILER_SIZE = 32;
27
+ // Object types in binary plist
28
+ export const BPLIST_TYPE = {
29
+ NULL: 0x00,
30
+ FALSE: 0x08,
31
+ TRUE: 0x09,
32
+ FILL: 0x0f,
33
+ INT: 0x10,
34
+ REAL: 0x20,
35
+ DATE: 0x30,
36
+ DATA: 0x40,
37
+ STRING_ASCII: 0x50,
38
+ STRING_UNICODE: 0x60,
39
+ UID: 0x80,
40
+ ARRAY: 0xa0,
41
+ SET: 0xc0,
42
+ DICT: 0xd0,
43
+ };
@@ -0,0 +1,14 @@
1
+ import { createBinaryPlist } from './binary-plist-creator.js';
2
+ import { isBinaryPlist, parseBinaryPlist } from './binary-plist-parser.js';
3
+ import { APPLE_EPOCH_OFFSET, BPLIST_MAGIC_AND_VERSION, BPLIST_TYPE, UTF8_ENCODING } from './constants.js';
4
+ import { LengthBasedSplitter } from './length-based-splitter.js';
5
+ import { createPlist as createXmlPlist } from './plist-creator.js';
6
+ import { PlistServiceDecoder } from './plist-decoder.js';
7
+ import { PlistServiceEncoder } from './plist-encoder.js';
8
+ import { parsePlist as parseXmlPlist } from './plist-parser.js';
9
+ import { PlistService } from './plist-service.js';
10
+ import { createPlist } from './unified-plist-creator.js';
11
+ import { parsePlist } from './unified-plist-parser.js';
12
+ import { ensureString, escapeXml, findFirstReplacementCharacter, fixMultipleXmlDeclarations, hasUnicodeReplacementCharacter, isValidXml, isXmlPlistContent, trimBeforeXmlDeclaration } from './utils.js';
13
+ export { createPlist, createXmlPlist, createBinaryPlist, LengthBasedSplitter, parsePlist, parseXmlPlist, parseBinaryPlist, isBinaryPlist, PlistService, PlistServiceDecoder, PlistServiceEncoder, APPLE_EPOCH_OFFSET, BPLIST_MAGIC_AND_VERSION, BPLIST_TYPE, UTF8_ENCODING, hasUnicodeReplacementCharacter, findFirstReplacementCharacter, ensureString, trimBeforeXmlDeclaration, fixMultipleXmlDeclarations, isValidXml, escapeXml, isXmlPlistContent, };
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,WAAW,EACX,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,SAAS,EACT,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,WAAW,EACX,aAAa,EAEb,8BAA8B,EAC9B,6BAA6B,EAC7B,YAAY,EACZ,wBAAwB,EACxB,0BAA0B,EAC1B,UAAU,EACV,SAAS,EACT,iBAAiB,GAClB,CAAC"}
@@ -0,0 +1,16 @@
1
+ // Export all components for easy imports
2
+ import { createBinaryPlist } from './binary-plist-creator.js';
3
+ import { isBinaryPlist, parseBinaryPlist } from './binary-plist-parser.js';
4
+ import { APPLE_EPOCH_OFFSET, BPLIST_MAGIC_AND_VERSION, BPLIST_TYPE, UTF8_ENCODING, } from './constants.js';
5
+ import { LengthBasedSplitter } from './length-based-splitter.js';
6
+ import { createPlist as createXmlPlist } from './plist-creator.js';
7
+ import { PlistServiceDecoder } from './plist-decoder.js';
8
+ import { PlistServiceEncoder } from './plist-encoder.js';
9
+ import { parsePlist as parseXmlPlist } from './plist-parser.js';
10
+ import { PlistService } from './plist-service.js';
11
+ import { createPlist } from './unified-plist-creator.js';
12
+ import { parsePlist } from './unified-plist-parser.js';
13
+ import { ensureString, escapeXml, findFirstReplacementCharacter, fixMultipleXmlDeclarations, hasUnicodeReplacementCharacter, isValidXml, isXmlPlistContent, trimBeforeXmlDeclaration, } from './utils.js';
14
+ export { createPlist, createXmlPlist, createBinaryPlist, LengthBasedSplitter, parsePlist, parseXmlPlist, parseBinaryPlist, isBinaryPlist, PlistService, PlistServiceDecoder, PlistServiceEncoder, APPLE_EPOCH_OFFSET, BPLIST_MAGIC_AND_VERSION, BPLIST_TYPE, UTF8_ENCODING,
15
+ // Utility functions
16
+ hasUnicodeReplacementCharacter, findFirstReplacementCharacter, ensureString, trimBeforeXmlDeclaration, fixMultipleXmlDeclarations, isValidXml, escapeXml, isXmlPlistContent, };
@@ -0,0 +1,43 @@
1
+ import { Transform, type TransformCallback } from 'stream';
2
+ /**
3
+ * Options for LengthBasedSplitter
4
+ */
5
+ export interface LengthBasedSplitterOptions {
6
+ readableStream?: NodeJS.ReadableStream;
7
+ littleEndian?: boolean;
8
+ maxFrameLength?: number;
9
+ lengthFieldOffset?: number;
10
+ lengthFieldLength?: number;
11
+ lengthAdjustment?: number;
12
+ }
13
+ /**
14
+ * Splits incoming data into length-prefixed chunks
15
+ */
16
+ export declare class LengthBasedSplitter extends Transform {
17
+ private buffer;
18
+ private readonly littleEndian;
19
+ private readonly maxFrameLength;
20
+ private readonly lengthFieldOffset;
21
+ private readonly lengthFieldLength;
22
+ private readonly lengthAdjustment;
23
+ private isXmlMode;
24
+ /**
25
+ * Creates a new LengthBasedSplitter
26
+ * @param options Configuration options
27
+ */
28
+ constructor(options?: LengthBasedSplitterOptions);
29
+ /**
30
+ * Shutdown the splitter and remove all listeners
31
+ */
32
+ shutdown(): void;
33
+ _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
34
+ /**
35
+ * Process data as XML
36
+ */
37
+ private processXmlData;
38
+ /**
39
+ * Process data as binary with length prefix
40
+ */
41
+ private processBinaryData;
42
+ }
43
+ //# sourceMappingURL=length-based-splitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"length-based-splitter.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/length-based-splitter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AA0B3D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IAChD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,SAAS,CAAkB;IAEnC;;;OAGG;gBACS,OAAO,GAAE,0BAA+B;IAkBpD;;OAEG;IACH,QAAQ,IAAI,IAAI;IAUhB,UAAU,CACR,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,iBAAiB,GAC1B,IAAI;IAuDP;;OAEG;IACH,OAAO,CAAC,cAAc;IA+CtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CA+H1B"}