appwrite-cli 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/.github/workflows/npm-publish.yml +41 -0
  2. package/Formula/appwrite.rb +19 -0
  3. package/LICENSE.md +12 -0
  4. package/README.md +102 -0
  5. package/docs/examples/account/create-anonymous-session.md +1 -0
  6. package/docs/examples/account/create-j-w-t.md +1 -0
  7. package/docs/examples/account/create-magic-u-r-l-session.md +4 -0
  8. package/docs/examples/account/create-o-auth2session.md +5 -0
  9. package/docs/examples/account/create-recovery.md +3 -0
  10. package/docs/examples/account/create-session.md +3 -0
  11. package/docs/examples/account/create-verification.md +2 -0
  12. package/docs/examples/account/create.md +5 -0
  13. package/docs/examples/account/delete-session.md +2 -0
  14. package/docs/examples/account/delete-sessions.md +1 -0
  15. package/docs/examples/account/delete.md +1 -0
  16. package/docs/examples/account/get-logs.md +3 -0
  17. package/docs/examples/account/get-prefs.md +1 -0
  18. package/docs/examples/account/get-session.md +2 -0
  19. package/docs/examples/account/get-sessions.md +1 -0
  20. package/docs/examples/account/get.md +1 -0
  21. package/docs/examples/account/update-email.md +3 -0
  22. package/docs/examples/account/update-magic-u-r-l-session.md +3 -0
  23. package/docs/examples/account/update-name.md +2 -0
  24. package/docs/examples/account/update-password.md +3 -0
  25. package/docs/examples/account/update-prefs.md +2 -0
  26. package/docs/examples/account/update-recovery.md +5 -0
  27. package/docs/examples/account/update-session.md +2 -0
  28. package/docs/examples/account/update-verification.md +3 -0
  29. package/docs/examples/avatars/get-browser.md +5 -0
  30. package/docs/examples/avatars/get-credit-card.md +5 -0
  31. package/docs/examples/avatars/get-favicon.md +2 -0
  32. package/docs/examples/avatars/get-flag.md +5 -0
  33. package/docs/examples/avatars/get-image.md +4 -0
  34. package/docs/examples/avatars/get-initials.md +6 -0
  35. package/docs/examples/avatars/get-q-r.md +5 -0
  36. package/docs/examples/database/create-boolean-attribute.md +6 -0
  37. package/docs/examples/database/create-collection.md +6 -0
  38. package/docs/examples/database/create-document.md +6 -0
  39. package/docs/examples/database/create-email-attribute.md +6 -0
  40. package/docs/examples/database/create-enum-attribute.md +7 -0
  41. package/docs/examples/database/create-float-attribute.md +8 -0
  42. package/docs/examples/database/create-index.md +6 -0
  43. package/docs/examples/database/create-integer-attribute.md +8 -0
  44. package/docs/examples/database/create-ip-attribute.md +6 -0
  45. package/docs/examples/database/create-string-attribute.md +7 -0
  46. package/docs/examples/database/create-url-attribute.md +6 -0
  47. package/docs/examples/database/delete-attribute.md +3 -0
  48. package/docs/examples/database/delete-collection.md +2 -0
  49. package/docs/examples/database/delete-document.md +3 -0
  50. package/docs/examples/database/delete-index.md +3 -0
  51. package/docs/examples/database/get-attribute.md +3 -0
  52. package/docs/examples/database/get-collection-usage.md +3 -0
  53. package/docs/examples/database/get-collection.md +2 -0
  54. package/docs/examples/database/get-document.md +3 -0
  55. package/docs/examples/database/get-index.md +3 -0
  56. package/docs/examples/database/get-usage.md +2 -0
  57. package/docs/examples/database/list-attributes.md +2 -0
  58. package/docs/examples/database/list-collection-logs.md +4 -0
  59. package/docs/examples/database/list-collections.md +7 -0
  60. package/docs/examples/database/list-document-logs.md +5 -0
  61. package/docs/examples/database/list-documents.md +9 -0
  62. package/docs/examples/database/list-indexes.md +2 -0
  63. package/docs/examples/database/update-collection.md +7 -0
  64. package/docs/examples/database/update-document.md +6 -0
  65. package/docs/examples/functions/create-deployment.md +5 -0
  66. package/docs/examples/functions/create-execution.md +4 -0
  67. package/docs/examples/functions/create.md +9 -0
  68. package/docs/examples/functions/delete-deployment.md +3 -0
  69. package/docs/examples/functions/delete.md +2 -0
  70. package/docs/examples/functions/get-deployment.md +3 -0
  71. package/docs/examples/functions/get-execution.md +3 -0
  72. package/docs/examples/functions/get-usage.md +3 -0
  73. package/docs/examples/functions/get.md +2 -0
  74. package/docs/examples/functions/list-deployments.md +8 -0
  75. package/docs/examples/functions/list-executions.md +7 -0
  76. package/docs/examples/functions/list-runtimes.md +1 -0
  77. package/docs/examples/functions/list.md +7 -0
  78. package/docs/examples/functions/retry-build.md +4 -0
  79. package/docs/examples/functions/update-deployment.md +3 -0
  80. package/docs/examples/functions/update.md +8 -0
  81. package/docs/examples/health/get-antivirus.md +1 -0
  82. package/docs/examples/health/get-cache.md +1 -0
  83. package/docs/examples/health/get-d-b.md +1 -0
  84. package/docs/examples/health/get-queue-certificates.md +1 -0
  85. package/docs/examples/health/get-queue-functions.md +1 -0
  86. package/docs/examples/health/get-queue-logs.md +1 -0
  87. package/docs/examples/health/get-queue-usage.md +1 -0
  88. package/docs/examples/health/get-queue-webhooks.md +1 -0
  89. package/docs/examples/health/get-storage-local.md +1 -0
  90. package/docs/examples/health/get-time.md +1 -0
  91. package/docs/examples/health/get.md +1 -0
  92. package/docs/examples/locale/get-continents.md +1 -0
  93. package/docs/examples/locale/get-countries-e-u.md +1 -0
  94. package/docs/examples/locale/get-countries-phones.md +1 -0
  95. package/docs/examples/locale/get-countries.md +1 -0
  96. package/docs/examples/locale/get-currencies.md +1 -0
  97. package/docs/examples/locale/get-languages.md +1 -0
  98. package/docs/examples/locale/get.md +1 -0
  99. package/docs/examples/projects/create-domain.md +3 -0
  100. package/docs/examples/projects/create-key.md +4 -0
  101. package/docs/examples/projects/create-platform.md +7 -0
  102. package/docs/examples/projects/create-webhook.md +8 -0
  103. package/docs/examples/projects/create.md +13 -0
  104. package/docs/examples/projects/delete-domain.md +3 -0
  105. package/docs/examples/projects/delete-key.md +3 -0
  106. package/docs/examples/projects/delete-platform.md +3 -0
  107. package/docs/examples/projects/delete-webhook.md +3 -0
  108. package/docs/examples/projects/delete.md +3 -0
  109. package/docs/examples/projects/get-domain.md +3 -0
  110. package/docs/examples/projects/get-key.md +3 -0
  111. package/docs/examples/projects/get-platform.md +3 -0
  112. package/docs/examples/projects/get-usage.md +3 -0
  113. package/docs/examples/projects/get-webhook.md +3 -0
  114. package/docs/examples/projects/get.md +2 -0
  115. package/docs/examples/projects/list-domains.md +2 -0
  116. package/docs/examples/projects/list-keys.md +2 -0
  117. package/docs/examples/projects/list-platforms.md +2 -0
  118. package/docs/examples/projects/list-webhooks.md +2 -0
  119. package/docs/examples/projects/list.md +7 -0
  120. package/docs/examples/projects/update-auth-limit.md +3 -0
  121. package/docs/examples/projects/update-auth-status.md +4 -0
  122. package/docs/examples/projects/update-domain-verification.md +3 -0
  123. package/docs/examples/projects/update-key.md +5 -0
  124. package/docs/examples/projects/update-o-auth2.md +5 -0
  125. package/docs/examples/projects/update-platform.md +7 -0
  126. package/docs/examples/projects/update-service-status.md +4 -0
  127. package/docs/examples/projects/update-webhook.md +9 -0
  128. package/docs/examples/projects/update.md +12 -0
  129. package/docs/examples/storage/create-bucket.md +11 -0
  130. package/docs/examples/storage/create-file.md +6 -0
  131. package/docs/examples/storage/delete-bucket.md +2 -0
  132. package/docs/examples/storage/delete-file.md +3 -0
  133. package/docs/examples/storage/get-bucket-usage.md +3 -0
  134. package/docs/examples/storage/get-bucket.md +2 -0
  135. package/docs/examples/storage/get-file-download.md +3 -0
  136. package/docs/examples/storage/get-file-preview.md +14 -0
  137. package/docs/examples/storage/get-file-view.md +3 -0
  138. package/docs/examples/storage/get-file.md +3 -0
  139. package/docs/examples/storage/get-usage.md +2 -0
  140. package/docs/examples/storage/list-buckets.md +7 -0
  141. package/docs/examples/storage/list-files.md +8 -0
  142. package/docs/examples/storage/update-bucket.md +11 -0
  143. package/docs/examples/storage/update-file.md +5 -0
  144. package/docs/examples/teams/create-membership.md +6 -0
  145. package/docs/examples/teams/create.md +4 -0
  146. package/docs/examples/teams/delete-membership.md +3 -0
  147. package/docs/examples/teams/delete.md +2 -0
  148. package/docs/examples/teams/get-membership.md +3 -0
  149. package/docs/examples/teams/get-memberships.md +8 -0
  150. package/docs/examples/teams/get.md +2 -0
  151. package/docs/examples/teams/list.md +7 -0
  152. package/docs/examples/teams/update-membership-roles.md +4 -0
  153. package/docs/examples/teams/update-membership-status.md +5 -0
  154. package/docs/examples/teams/update.md +3 -0
  155. package/docs/examples/users/create.md +5 -0
  156. package/docs/examples/users/delete-session.md +3 -0
  157. package/docs/examples/users/delete-sessions.md +2 -0
  158. package/docs/examples/users/delete.md +2 -0
  159. package/docs/examples/users/get-logs.md +4 -0
  160. package/docs/examples/users/get-prefs.md +2 -0
  161. package/docs/examples/users/get-sessions.md +2 -0
  162. package/docs/examples/users/get-usage.md +3 -0
  163. package/docs/examples/users/get.md +2 -0
  164. package/docs/examples/users/list.md +7 -0
  165. package/docs/examples/users/update-email.md +3 -0
  166. package/docs/examples/users/update-name.md +3 -0
  167. package/docs/examples/users/update-password.md +3 -0
  168. package/docs/examples/users/update-prefs.md +3 -0
  169. package/docs/examples/users/update-status.md +3 -0
  170. package/docs/examples/users/update-verification.md +3 -0
  171. package/index.js +49 -0
  172. package/install.sh +165 -0
  173. package/ldid/COPYING +661 -0
  174. package/ldid/Makefile +51 -0
  175. package/ldid/control +12 -0
  176. package/ldid/control.sh +5 -0
  177. package/ldid/deb.sh +10 -0
  178. package/ldid/ios.sh +2 -0
  179. package/ldid/ldid.cpp +3253 -0
  180. package/ldid/ldid.hpp +164 -0
  181. package/ldid/libplist/.github/workflows/build.yml +62 -0
  182. package/ldid/libplist/.github/workflows/codeql-analysis.yml +71 -0
  183. package/ldid/libplist/AUTHORS +28 -0
  184. package/ldid/libplist/COPYING +340 -0
  185. package/ldid/libplist/COPYING.LESSER +502 -0
  186. package/ldid/libplist/Makefile.am +20 -0
  187. package/ldid/libplist/NEWS +252 -0
  188. package/ldid/libplist/README.md +114 -0
  189. package/ldid/libplist/aclocal.m4 +1729 -0
  190. package/ldid/libplist/autogen.sh +26 -0
  191. package/ldid/libplist/configure.ac +292 -0
  192. package/ldid/libplist/cython/Makefile.am +53 -0
  193. package/ldid/libplist/cython/plist.pxd +78 -0
  194. package/ldid/libplist/cython/plist.pyx +947 -0
  195. package/ldid/libplist/cython/plist_util.c +40 -0
  196. package/ldid/libplist/cython/plist_util.h +5 -0
  197. package/ldid/libplist/docs/Makefile.am +3 -0
  198. package/ldid/libplist/docs/plistutil.1 +62 -0
  199. package/ldid/libplist/fuzz/Makefile.am +43 -0
  200. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-4766291097288704 +0 -0
  201. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-4930725262393344 +0 -0
  202. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-5421965105954816 +0 -0
  203. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-5556177727389696 +0 -0
  204. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-6557963011489792 +0 -0
  205. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-6605859144597504 +0 -0
  206. package/ldid/libplist/fuzz/bplist-crashes/crash-0ce4dd483b645bc05ec45a97d285dcf1933ee840 +0 -0
  207. package/ldid/libplist/fuzz/bplist-crashes/crash-0d59cdcb5c3416c2790612b78a631ce9f5622800 +0 -0
  208. package/ldid/libplist/fuzz/bplist-crashes/crash-17d635ab460fef74df1ac7561f1253533a6359c5 +0 -0
  209. package/ldid/libplist/fuzz/bplist-crashes/crash-33a67313fa7864cd627ef92d12017a127d342f28 +0 -0
  210. package/ldid/libplist/fuzz/bplist-crashes/crash-39f1347115f8fe9ac25cdc9332e3fc5cd32c7f7b +0 -0
  211. package/ldid/libplist/fuzz/bplist-crashes/crash-4bd78175fe01d07c5ee90104fbc68d95dd092210 +0 -0
  212. package/ldid/libplist/fuzz/bplist-crashes/crash-4c5404453bb7425aef9b953a5f6f3f0afcc48392 +0 -0
  213. package/ldid/libplist/fuzz/bplist-crashes/crash-52775e25f6af20af351cd616834e602fc988a032 +0 -0
  214. package/ldid/libplist/fuzz/bplist-crashes/crash-6d1399685b745d3d49fadc91072fabcdde8d16fa +0 -0
  215. package/ldid/libplist/fuzz/bplist-crashes/crash-94b3725900d63c6258448fd757559c81002de9c9 +0 -0
  216. package/ldid/libplist/fuzz/bplist-crashes/crash-a47195acbabc3f5b2cda9c6ebda42f2afc1cc5af +0 -0
  217. package/ldid/libplist/fuzz/bplist-crashes/crash-ce852bae6aeeffc4698a93660236f1b995ce966e +0 -0
  218. package/ldid/libplist/fuzz/bplist-crashes/crash-daddb6e82e3d1ed76e20e4131462f5247a6fb131 +0 -0
  219. package/ldid/libplist/fuzz/bplist-crashes/crash-f21be4ebce7f9c337bf96b93cec7e252f5c75a21 +0 -0
  220. package/ldid/libplist/fuzz/bplist-crashes/crash-f779dafccc0164684d1a264976e56037188b40e2 +0 -0
  221. package/ldid/libplist/fuzz/bplist-leaks/leak-96fb453b3ba18d31e164831795a708183b5a0dac +0 -0
  222. package/ldid/libplist/fuzz/bplist-leaks/leak-acb3c00a83d7635638a476a4e70fc1f1caa1a5b1 +0 -0
  223. package/ldid/libplist/fuzz/bplist-leaks/leak-fe2cd4b1f67e0c9b21e6225a4fb4ca19eab80074 +0 -0
  224. package/ldid/libplist/fuzz/bplist.dict +1 -0
  225. package/ldid/libplist/fuzz/bplist_fuzzer.cc +32 -0
  226. package/ldid/libplist/fuzz/bplist_fuzzer.options +3 -0
  227. package/ldid/libplist/fuzz/fuzzers.test +8 -0
  228. package/ldid/libplist/fuzz/init-fuzzers.sh +23 -0
  229. package/ldid/libplist/fuzz/test-fuzzers.sh +33 -0
  230. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-4516959125241856 +0 -0
  231. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-4663876528373760 +5 -0
  232. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-5799076113154048 +45 -0
  233. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-5922404220010496 +0 -0
  234. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6015098361479168 +0 -0
  235. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6043836860071936 +0 -0
  236. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6047509906456576 +10050 -0
  237. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6482601374121984 +0 -0
  238. package/ldid/libplist/fuzz/xplist-crashes/crash-09788d7acb46b4b177422f9c4ee54556a3ad1f17 +53 -0
  239. package/ldid/libplist/fuzz/xplist-crashes/crash-155c60d5c4b2778110fb4a633caa7d64eb9b99c1 +9 -0
  240. package/ldid/libplist/fuzz/xplist-crashes/crash-348c909a0b3532977185f551eb5d2ed04e694883 +11 -0
  241. package/ldid/libplist/fuzz/xplist-crashes/crash-7bc172e27a2b1d4fcaf031f59d1f08fb83081e4a +8 -0
  242. package/ldid/libplist/fuzz/xplist-crashes/crash-80c28b0e2a446665e68927dd4441c10c9a68e64e +0 -0
  243. package/ldid/libplist/fuzz/xplist-crashes/crash-8acf177da60ecf13c36d0da1b8e25de891980ea6 +5 -0
  244. package/ldid/libplist/fuzz/xplist-crashes/crash-94276cf69a50e78dd6cdf079c208cb80f357cd33 +0 -0
  245. package/ldid/libplist/fuzz/xplist-crashes/crash-9ddb891a0ec42401eb4629e6b99e01aef7909eb9 +0 -0
  246. package/ldid/libplist/fuzz/xplist-crashes/crash-a8b44e1f5be4f75f00a937016ec5405bce77a0f9 +0 -0
  247. package/ldid/libplist/fuzz/xplist-crashes/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 +0 -0
  248. package/ldid/libplist/fuzz/xplist-crashes/crash-f03c680ee1c4d84c28e731752df77a61e213a24d +72 -0
  249. package/ldid/libplist/fuzz/xplist-leaks/clusterfuzz-testcase-4634751103139840 +187 -0
  250. package/ldid/libplist/fuzz/xplist-leaks/clusterfuzz-testcase-6056412121661440 +12 -0
  251. package/ldid/libplist/fuzz/xplist-leaks/leak-47b0a9f21d3affab6cfc898e5140bb53265ada07 +0 -0
  252. package/ldid/libplist/fuzz/xplist-leaks/leak-4c81aae70b20d9b9408b78d40999a54205bdcfb7 +0 -0
  253. package/ldid/libplist/fuzz/xplist-leaks/leak-53bc466851eda790bd891733da5db0a7482886bf +6 -0
  254. package/ldid/libplist/fuzz/xplist.dict +51 -0
  255. package/ldid/libplist/fuzz/xplist_fuzzer.cc +32 -0
  256. package/ldid/libplist/fuzz/xplist_fuzzer.options +3 -0
  257. package/ldid/libplist/include/Makefile.am +15 -0
  258. package/ldid/libplist/include/plist/Array.h +55 -0
  259. package/ldid/libplist/include/plist/Boolean.h +48 -0
  260. package/ldid/libplist/include/plist/Data.h +49 -0
  261. package/ldid/libplist/include/plist/Date.h +50 -0
  262. package/ldid/libplist/include/plist/Dictionary.h +68 -0
  263. package/ldid/libplist/include/plist/Integer.h +48 -0
  264. package/ldid/libplist/include/plist/Key.h +49 -0
  265. package/ldid/libplist/include/plist/Node.h +57 -0
  266. package/ldid/libplist/include/plist/Real.h +48 -0
  267. package/ldid/libplist/include/plist/String.h +49 -0
  268. package/ldid/libplist/include/plist/Structure.h +59 -0
  269. package/ldid/libplist/include/plist/Uid.h +48 -0
  270. package/ldid/libplist/include/plist/plist++.h +39 -0
  271. package/ldid/libplist/include/plist/plist.h +953 -0
  272. package/ldid/libplist/libcnary/COPYING +502 -0
  273. package/ldid/libplist/libcnary/Makefile.am +15 -0
  274. package/ldid/libplist/libcnary/README +5 -0
  275. package/ldid/libplist/libcnary/cnary.c +46 -0
  276. package/ldid/libplist/libcnary/include/node.h +65 -0
  277. package/ldid/libplist/libcnary/include/node_list.h +47 -0
  278. package/ldid/libplist/libcnary/include/object.h +41 -0
  279. package/ldid/libplist/libcnary/node.c +216 -0
  280. package/ldid/libplist/libcnary/node_list.c +157 -0
  281. package/ldid/libplist/m4/ac_pkg_cython.m4 +67 -0
  282. package/ldid/libplist/m4/as-compiler-flag.m4 +62 -0
  283. package/ldid/libplist/m4/ax_pthread.m4 +485 -0
  284. package/ldid/libplist/m4/ax_python_devel.m4 +327 -0
  285. package/ldid/libplist/m4/cython_python.m4 +7 -0
  286. package/ldid/libplist/src/Array.cpp +148 -0
  287. package/ldid/libplist/src/Boolean.cpp +73 -0
  288. package/ldid/libplist/src/Data.cpp +79 -0
  289. package/ldid/libplist/src/Date.cpp +76 -0
  290. package/ldid/libplist/src/Dictionary.cpp +182 -0
  291. package/ldid/libplist/src/Integer.cpp +73 -0
  292. package/ldid/libplist/src/Key.cpp +80 -0
  293. package/ldid/libplist/src/Makefile.am +63 -0
  294. package/ldid/libplist/src/Node.cpp +166 -0
  295. package/ldid/libplist/src/Real.cpp +73 -0
  296. package/ldid/libplist/src/String.cpp +80 -0
  297. package/ldid/libplist/src/Structure.cpp +123 -0
  298. package/ldid/libplist/src/Uid.cpp +73 -0
  299. package/ldid/libplist/src/base64.c +119 -0
  300. package/ldid/libplist/src/base64.h +28 -0
  301. package/ldid/libplist/src/bplist.c +1381 -0
  302. package/ldid/libplist/src/bytearray.c +61 -0
  303. package/ldid/libplist/src/bytearray.h +36 -0
  304. package/ldid/libplist/src/hashtable.c +140 -0
  305. package/ldid/libplist/src/hashtable.h +50 -0
  306. package/ldid/libplist/src/plist.c +1356 -0
  307. package/ldid/libplist/src/plist.h +74 -0
  308. package/ldid/libplist/src/ptrarray.c +96 -0
  309. package/ldid/libplist/src/ptrarray.h +40 -0
  310. package/ldid/libplist/src/strbuf.h +34 -0
  311. package/ldid/libplist/src/time64.c +814 -0
  312. package/ldid/libplist/src/time64.h +81 -0
  313. package/ldid/libplist/src/time64_limits.h +97 -0
  314. package/ldid/libplist/src/xplist.c +1435 -0
  315. package/ldid/libplist/test/Makefile.am +93 -0
  316. package/ldid/libplist/test/amp.test +14 -0
  317. package/ldid/libplist/test/bigarray.test +15 -0
  318. package/ldid/libplist/test/cdata.test +12 -0
  319. package/ldid/libplist/test/data/1.plist +35 -0
  320. package/ldid/libplist/test/data/2.plist +100 -0
  321. package/ldid/libplist/test/data/3.plist +420 -0
  322. package/ldid/libplist/test/data/4.plist +5037 -0
  323. package/ldid/libplist/test/data/5.plist +55053 -0
  324. package/ldid/libplist/test/data/6.plist +4006 -0
  325. package/ldid/libplist/test/data/7.plist +14 -0
  326. package/ldid/libplist/test/data/amp.plist +6 -0
  327. package/ldid/libplist/test/data/cdata.plist +6 -0
  328. package/ldid/libplist/test/data/dictref1byte.bplist +0 -0
  329. package/ldid/libplist/test/data/dictref2bytes.bplist +0 -0
  330. package/ldid/libplist/test/data/dictref3bytes.bplist +0 -0
  331. package/ldid/libplist/test/data/dictref4bytes.bplist +0 -0
  332. package/ldid/libplist/test/data/dictref5bytes.bplist +0 -0
  333. package/ldid/libplist/test/data/dictref6bytes.bplist +0 -0
  334. package/ldid/libplist/test/data/dictref7bytes.bplist +0 -0
  335. package/ldid/libplist/test/data/dictref8bytes.bplist +0 -0
  336. package/ldid/libplist/test/data/empty_keys.plist +8 -0
  337. package/ldid/libplist/test/data/entities.plist +57 -0
  338. package/ldid/libplist/test/data/hex.plist +5 -0
  339. package/ldid/libplist/test/data/invalid_tag.plist +6 -0
  340. package/ldid/libplist/test/data/malformed_dict.bplist +0 -0
  341. package/ldid/libplist/test/data/off1byte.bplist +0 -0
  342. package/ldid/libplist/test/data/off2bytes.bplist +0 -0
  343. package/ldid/libplist/test/data/off3bytes.bplist +0 -0
  344. package/ldid/libplist/test/data/off4bytes.bplist +0 -0
  345. package/ldid/libplist/test/data/off5bytes.bplist +0 -0
  346. package/ldid/libplist/test/data/off6bytes.bplist +0 -0
  347. package/ldid/libplist/test/data/off7bytes.bplist +0 -0
  348. package/ldid/libplist/test/data/off8bytes.bplist +0 -0
  349. package/ldid/libplist/test/data/offxml.plist +8 -0
  350. package/ldid/libplist/test/data/order.bplist +0 -0
  351. package/ldid/libplist/test/data/order.plist +27 -0
  352. package/ldid/libplist/test/data/recursion.bplist +0 -0
  353. package/ldid/libplist/test/data/signed.bplist +0 -0
  354. package/ldid/libplist/test/data/signed.plist +5 -0
  355. package/ldid/libplist/test/data/signedunsigned.bplist +0 -0
  356. package/ldid/libplist/test/data/signedunsigned.plist +11 -0
  357. package/ldid/libplist/test/data/unsigned.bplist +0 -0
  358. package/ldid/libplist/test/data/unsigned.plist +5 -0
  359. package/ldid/libplist/test/dates.test +15 -0
  360. package/ldid/libplist/test/empty.test +15 -0
  361. package/ldid/libplist/test/empty_keys.test +12 -0
  362. package/ldid/libplist/test/entities.test +12 -0
  363. package/ldid/libplist/test/hex.test +12 -0
  364. package/ldid/libplist/test/huge.test +15 -0
  365. package/ldid/libplist/test/invalid_tag.test +14 -0
  366. package/ldid/libplist/test/large.test +15 -0
  367. package/ldid/libplist/test/malformed_dict.test +11 -0
  368. package/ldid/libplist/test/medium.test +15 -0
  369. package/ldid/libplist/test/offsetsize.test +12 -0
  370. package/ldid/libplist/test/order.test +13 -0
  371. package/ldid/libplist/test/plist_cmp.c +158 -0
  372. package/ldid/libplist/test/plist_test.c +135 -0
  373. package/ldid/libplist/test/recursion.test +11 -0
  374. package/ldid/libplist/test/refsize.test +12 -0
  375. package/ldid/libplist/test/signedunsigned1.test +23 -0
  376. package/ldid/libplist/test/signedunsigned2.test +23 -0
  377. package/ldid/libplist/test/signedunsigned3.test +23 -0
  378. package/ldid/libplist/test/small.test +15 -0
  379. package/ldid/libplist/test/timezone1.test +17 -0
  380. package/ldid/libplist/test/timezone2.test +21 -0
  381. package/ldid/libplist/tools/Makefile.am +10 -0
  382. package/ldid/libplist/tools/plistutil.c +299 -0
  383. package/ldid/lookup2.c +416 -0
  384. package/ldid/make.sh +90 -0
  385. package/ldid/minimal/hexdump.h +76 -0
  386. package/ldid/minimal/mapping.h +72 -0
  387. package/ldid/minimal/sqlite3.h +71 -0
  388. package/ldid/minimal/stdlib.h +129 -0
  389. package/ldid/minimal/string.h +51 -0
  390. package/ldid/plist.sh +2 -0
  391. package/ldid/sha1.h +64 -0
  392. package/ldid/sysroot.sh +31 -0
  393. package/ldid/version.sh +2 -0
  394. package/lib/client.js +243 -0
  395. package/lib/commands/account.js +785 -0
  396. package/lib/commands/avatars.js +349 -0
  397. package/lib/commands/database.js +1238 -0
  398. package/lib/commands/deploy.js +477 -0
  399. package/lib/commands/functions.js +689 -0
  400. package/lib/commands/generic.js +106 -0
  401. package/lib/commands/health.js +269 -0
  402. package/lib/commands/init.js +148 -0
  403. package/lib/commands/locale.js +177 -0
  404. package/lib/commands/projects.js +1191 -0
  405. package/lib/commands/storage.js +743 -0
  406. package/lib/commands/teams.js +435 -0
  407. package/lib/commands/users.js +542 -0
  408. package/lib/config.js +264 -0
  409. package/lib/exception.js +9 -0
  410. package/lib/parser.js +179 -0
  411. package/lib/questions.js +223 -0
  412. package/lib/sdks.js +82 -0
  413. package/package.json +41 -0
@@ -0,0 +1,1381 @@
1
+ /*
2
+ * bplist.c
3
+ * Binary plist implementation
4
+ *
5
+ * Copyright (c) 2011-2017 Nikias Bassen, All Rights Reserved.
6
+ * Copyright (c) 2008-2010 Jonathan Beck, All Rights Reserved.
7
+ *
8
+ * This library is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * This library is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with this library; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+ */
22
+
23
+ #ifdef HAVE_CONFIG_H
24
+ #include <config.h>
25
+ #endif
26
+
27
+ #include <stdlib.h>
28
+ #include <stdio.h>
29
+ #include <string.h>
30
+ #include <assert.h>
31
+
32
+ #include <ctype.h>
33
+ #include <inttypes.h>
34
+
35
+ #include <plist/plist.h>
36
+ #include "plist.h"
37
+ #include "hashtable.h"
38
+ #include "bytearray.h"
39
+ #include "ptrarray.h"
40
+
41
+ #include <node.h>
42
+
43
+ /* Magic marker and size. */
44
+ #define BPLIST_MAGIC ((uint8_t*)"bplist")
45
+ #define BPLIST_MAGIC_SIZE 6
46
+
47
+ #define BPLIST_VERSION ((uint8_t*)"00")
48
+ #define BPLIST_VERSION_SIZE 2
49
+
50
+ typedef struct __attribute__((packed)) {
51
+ uint8_t unused[6];
52
+ uint8_t offset_size;
53
+ uint8_t ref_size;
54
+ uint64_t num_objects;
55
+ uint64_t root_object_index;
56
+ uint64_t offset_table_offset;
57
+ } bplist_trailer_t;
58
+
59
+ enum
60
+ {
61
+ BPLIST_NULL = 0x00,
62
+ BPLIST_FALSE = 0x08,
63
+ BPLIST_TRUE = 0x09,
64
+ BPLIST_FILL = 0x0F, /* will be used for length grabbing */
65
+ BPLIST_UINT = 0x10,
66
+ BPLIST_REAL = 0x20,
67
+ BPLIST_DATE = 0x30,
68
+ BPLIST_DATA = 0x40,
69
+ BPLIST_STRING = 0x50,
70
+ BPLIST_UNICODE = 0x60,
71
+ BPLIST_UNK_0x70 = 0x70,
72
+ BPLIST_UID = 0x80,
73
+ BPLIST_ARRAY = 0xA0,
74
+ BPLIST_SET = 0xC0,
75
+ BPLIST_DICT = 0xD0,
76
+ BPLIST_MASK = 0xF0
77
+ };
78
+
79
+ union plist_uint_ptr
80
+ {
81
+ const void *src;
82
+ uint8_t *u8ptr;
83
+ uint16_t *u16ptr;
84
+ uint32_t *u32ptr;
85
+ uint64_t *u64ptr;
86
+ };
87
+
88
+ #define get_unaligned(ptr) \
89
+ ({ \
90
+ struct __attribute__((packed)) { \
91
+ typeof(*(ptr)) __v; \
92
+ } *__p = (void *) (ptr); \
93
+ __p->__v; \
94
+ })
95
+
96
+
97
+ #ifndef bswap16
98
+ #define bswap16(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
99
+ #endif
100
+
101
+ #ifndef bswap32
102
+ #define bswap32(x) ((((x) & 0xFF000000) >> 24) \
103
+ | (((x) & 0x00FF0000) >> 8) \
104
+ | (((x) & 0x0000FF00) << 8) \
105
+ | (((x) & 0x000000FF) << 24))
106
+ #endif
107
+
108
+ #ifndef bswap64
109
+ #define bswap64(x) ((((x) & 0xFF00000000000000ull) >> 56) \
110
+ | (((x) & 0x00FF000000000000ull) >> 40) \
111
+ | (((x) & 0x0000FF0000000000ull) >> 24) \
112
+ | (((x) & 0x000000FF00000000ull) >> 8) \
113
+ | (((x) & 0x00000000FF000000ull) << 8) \
114
+ | (((x) & 0x0000000000FF0000ull) << 24) \
115
+ | (((x) & 0x000000000000FF00ull) << 40) \
116
+ | (((x) & 0x00000000000000FFull) << 56))
117
+ #endif
118
+
119
+ #ifndef be16toh
120
+ #ifdef __BIG_ENDIAN__
121
+ #define be16toh(x) (x)
122
+ #else
123
+ #define be16toh(x) bswap16(x)
124
+ #endif
125
+ #endif
126
+
127
+ #ifndef be32toh
128
+ #ifdef __BIG_ENDIAN__
129
+ #define be32toh(x) (x)
130
+ #else
131
+ #define be32toh(x) bswap32(x)
132
+ #endif
133
+ #endif
134
+
135
+ #ifndef be64toh
136
+ #ifdef __BIG_ENDIAN__
137
+ #define be64toh(x) (x)
138
+ #else
139
+ #define be64toh(x) bswap64(x)
140
+ #endif
141
+ #endif
142
+
143
+ #ifdef __BIG_ENDIAN__
144
+ #define beNtoh(x,n) (x >> ((8-n) << 3))
145
+ #else
146
+ #define beNtoh(x,n) be64toh(x << ((8-n) << 3))
147
+ #endif
148
+
149
+ #define UINT_TO_HOST(x, n) \
150
+ ({ \
151
+ union plist_uint_ptr __up; \
152
+ __up.src = (n > 8) ? x + (n - 8) : x; \
153
+ (n >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
154
+ (n == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
155
+ (n == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
156
+ (n == 1 ? *__up.u8ptr : \
157
+ beNtoh( get_unaligned(__up.u64ptr), n) \
158
+ )))); \
159
+ })
160
+
161
+ #define get_needed_bytes(x) \
162
+ ( ((uint64_t)x) < (1ULL << 8) ? 1 : \
163
+ ( ((uint64_t)x) < (1ULL << 16) ? 2 : \
164
+ ( ((uint64_t)x) < (1ULL << 24) ? 3 : \
165
+ ( ((uint64_t)x) < (1ULL << 32) ? 4 : 8))))
166
+
167
+ #define get_real_bytes(x) (x == (float) x ? sizeof(float) : sizeof(double))
168
+
169
+ #if (defined(__LITTLE_ENDIAN__) \
170
+ && !defined(__FLOAT_WORD_ORDER__)) \
171
+ || (defined(__FLOAT_WORD_ORDER__) \
172
+ && __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
173
+ #define float_bswap64(x) bswap64(x)
174
+ #define float_bswap32(x) bswap32(x)
175
+ #else
176
+ #define float_bswap64(x) (x)
177
+ #define float_bswap32(x) (x)
178
+ #endif
179
+
180
+ #ifndef __has_builtin
181
+ #define __has_builtin(x) 0
182
+ #endif
183
+
184
+ #if __has_builtin(__builtin_umulll_overflow) || __GNUC__ >= 5
185
+ #define uint64_mul_overflow(a, b, r) __builtin_umulll_overflow(a, b, (unsigned long long*)r)
186
+ #else
187
+ static int uint64_mul_overflow(uint64_t a, uint64_t b, uint64_t *res)
188
+ {
189
+ *res = a * b;
190
+ return (a > UINT64_MAX / b);
191
+ }
192
+ #endif
193
+
194
+ #define NODE_IS_ROOT(x) (((node_t*)x)->isRoot)
195
+
196
+ struct bplist_data {
197
+ const char* data;
198
+ uint64_t size;
199
+ uint64_t num_objects;
200
+ uint8_t ref_size;
201
+ uint8_t offset_size;
202
+ const char* offset_table;
203
+ uint32_t level;
204
+ ptrarray_t* used_indexes;
205
+ };
206
+
207
+ #ifdef DEBUG
208
+ static int plist_bin_debug = 0;
209
+ #define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
210
+ #else
211
+ #define PLIST_BIN_ERR(...)
212
+ #endif
213
+
214
+ void plist_bin_init(void)
215
+ {
216
+ /* init binary plist stuff */
217
+ #ifdef DEBUG
218
+ char *env_debug = getenv("PLIST_BIN_DEBUG");
219
+ if (env_debug && !strcmp(env_debug, "1")) {
220
+ plist_bin_debug = 1;
221
+ }
222
+ #endif
223
+ }
224
+
225
+ void plist_bin_deinit(void)
226
+ {
227
+ /* deinit binary plist stuff */
228
+ }
229
+
230
+ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node_index);
231
+
232
+ static plist_t parse_uint_node(const char **bnode, uint8_t size)
233
+ {
234
+ plist_data_t data = plist_new_plist_data();
235
+
236
+ size = 1 << size; // make length less misleading
237
+ switch (size)
238
+ {
239
+ case sizeof(uint8_t):
240
+ case sizeof(uint16_t):
241
+ case sizeof(uint32_t):
242
+ case sizeof(uint64_t):
243
+ data->length = sizeof(uint64_t);
244
+ break;
245
+ case 16:
246
+ data->length = size;
247
+ break;
248
+ default:
249
+ free(data);
250
+ PLIST_BIN_ERR("%s: Invalid byte size for integer node\n", __func__);
251
+ return NULL;
252
+ };
253
+
254
+ data->intval = UINT_TO_HOST(*bnode, size);
255
+
256
+ (*bnode) += size;
257
+ data->type = PLIST_UINT;
258
+
259
+ return node_create(NULL, data);
260
+ }
261
+
262
+ static plist_t parse_real_node(const char **bnode, uint8_t size)
263
+ {
264
+ plist_data_t data = plist_new_plist_data();
265
+ uint8_t buf[8];
266
+
267
+ size = 1 << size; // make length less misleading
268
+ switch (size)
269
+ {
270
+ case sizeof(uint32_t):
271
+ *(uint32_t*)buf = float_bswap32(get_unaligned((uint32_t*)*bnode));
272
+ data->realval = *(float *) buf;
273
+ break;
274
+ case sizeof(uint64_t):
275
+ *(uint64_t*)buf = float_bswap64(get_unaligned((uint64_t*)*bnode));
276
+ data->realval = *(double *) buf;
277
+ break;
278
+ default:
279
+ free(data);
280
+ PLIST_BIN_ERR("%s: Invalid byte size for real node\n", __func__);
281
+ return NULL;
282
+ }
283
+ data->type = PLIST_REAL;
284
+ data->length = sizeof(double);
285
+
286
+ return node_create(NULL, data);
287
+ }
288
+
289
+ static plist_t parse_date_node(const char **bnode, uint8_t size)
290
+ {
291
+ plist_t node = parse_real_node(bnode, size);
292
+ plist_data_t data = plist_get_data(node);
293
+
294
+ data->type = PLIST_DATE;
295
+
296
+ return node;
297
+ }
298
+
299
+ static plist_t parse_string_node(const char **bnode, uint64_t size)
300
+ {
301
+ plist_data_t data = plist_new_plist_data();
302
+
303
+ data->type = PLIST_STRING;
304
+ data->strval = (char *) malloc(sizeof(char) * (size + 1));
305
+ if (!data->strval) {
306
+ plist_free_data(data);
307
+ PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, sizeof(char) * (size + 1));
308
+ return NULL;
309
+ }
310
+ memcpy(data->strval, *bnode, size);
311
+ data->strval[size] = '\0';
312
+ data->length = strlen(data->strval);
313
+
314
+ return node_create(NULL, data);
315
+ }
316
+
317
+ static char *plist_utf16be_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written)
318
+ {
319
+ if (!unistr || (len <= 0)) return NULL;
320
+ char *outbuf;
321
+ int p = 0;
322
+ long i = 0;
323
+
324
+ uint16_t wc;
325
+ uint32_t w;
326
+ int read_lead_surrogate = 0;
327
+
328
+ outbuf = (char*)malloc(4*(len+1));
329
+ if (!outbuf) {
330
+ PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, (uint64_t)(4*(len+1)));
331
+ return NULL;
332
+ }
333
+
334
+ while (i < len) {
335
+ wc = be16toh(get_unaligned(unistr + i));
336
+ i++;
337
+ if (wc >= 0xD800 && wc <= 0xDBFF) {
338
+ if (!read_lead_surrogate) {
339
+ read_lead_surrogate = 1;
340
+ w = 0x010000 + ((wc & 0x3FF) << 10);
341
+ } else {
342
+ // This is invalid, the next 16 bit char should be a trail surrogate.
343
+ // Handling error by skipping.
344
+ read_lead_surrogate = 0;
345
+ }
346
+ } else if (wc >= 0xDC00 && wc <= 0xDFFF) {
347
+ if (read_lead_surrogate) {
348
+ read_lead_surrogate = 0;
349
+ w = w | (wc & 0x3FF);
350
+ outbuf[p++] = (char)(0xF0 + ((w >> 18) & 0x7));
351
+ outbuf[p++] = (char)(0x80 + ((w >> 12) & 0x3F));
352
+ outbuf[p++] = (char)(0x80 + ((w >> 6) & 0x3F));
353
+ outbuf[p++] = (char)(0x80 + (w & 0x3F));
354
+ } else {
355
+ // This is invalid. A trail surrogate should always follow a lead surrogate.
356
+ // Handling error by skipping
357
+ }
358
+ } else if (wc >= 0x800) {
359
+ outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF));
360
+ outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F));
361
+ outbuf[p++] = (char)(0x80 + (wc & 0x3F));
362
+ } else if (wc >= 0x80) {
363
+ outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F));
364
+ outbuf[p++] = (char)(0x80 + (wc & 0x3F));
365
+ } else {
366
+ outbuf[p++] = (char)(wc & 0x7F);
367
+ }
368
+ }
369
+ if (items_read) {
370
+ *items_read = i;
371
+ }
372
+ if (items_written) {
373
+ *items_written = p;
374
+ }
375
+ outbuf[p] = 0;
376
+
377
+ return outbuf;
378
+ }
379
+
380
+ static plist_t parse_unicode_node(const char **bnode, uint64_t size)
381
+ {
382
+ plist_data_t data = plist_new_plist_data();
383
+ char *tmpstr = NULL;
384
+ long items_read = 0;
385
+ long items_written = 0;
386
+
387
+ data->type = PLIST_STRING;
388
+
389
+ tmpstr = plist_utf16be_to_utf8((uint16_t*)(*bnode), size, &items_read, &items_written);
390
+ if (!tmpstr) {
391
+ plist_free_data(data);
392
+ return NULL;
393
+ }
394
+ tmpstr[items_written] = '\0';
395
+
396
+ data->type = PLIST_STRING;
397
+ data->strval = realloc(tmpstr, items_written+1);
398
+ if (!data->strval)
399
+ data->strval = tmpstr;
400
+ data->length = items_written;
401
+ return node_create(NULL, data);
402
+ }
403
+
404
+ static plist_t parse_data_node(const char **bnode, uint64_t size)
405
+ {
406
+ plist_data_t data = plist_new_plist_data();
407
+
408
+ data->type = PLIST_DATA;
409
+ data->length = size;
410
+ data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size);
411
+ if (!data->strval) {
412
+ plist_free_data(data);
413
+ PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, sizeof(uint8_t) * size);
414
+ return NULL;
415
+ }
416
+ memcpy(data->buff, *bnode, sizeof(uint8_t) * size);
417
+
418
+ return node_create(NULL, data);
419
+ }
420
+
421
+ static plist_t parse_dict_node(struct bplist_data *bplist, const char** bnode, uint64_t size)
422
+ {
423
+ uint64_t j;
424
+ uint64_t str_i = 0, str_j = 0;
425
+ uint64_t index1, index2;
426
+ plist_data_t data = plist_new_plist_data();
427
+ const char *index1_ptr = NULL;
428
+ const char *index2_ptr = NULL;
429
+
430
+ data->type = PLIST_DICT;
431
+ data->length = size;
432
+
433
+ plist_t node = node_create(NULL, data);
434
+
435
+ for (j = 0; j < data->length; j++) {
436
+ str_i = j * bplist->ref_size;
437
+ str_j = (j + size) * bplist->ref_size;
438
+ index1_ptr = (*bnode) + str_i;
439
+ index2_ptr = (*bnode) + str_j;
440
+
441
+ if ((index1_ptr < bplist->data || index1_ptr + bplist->ref_size > bplist->offset_table) ||
442
+ (index2_ptr < bplist->data || index2_ptr + bplist->ref_size > bplist->offset_table)) {
443
+ plist_free(node);
444
+ PLIST_BIN_ERR("%s: dict entry %" PRIu64 " is outside of valid range\n", __func__, j);
445
+ return NULL;
446
+ }
447
+
448
+ index1 = UINT_TO_HOST(index1_ptr, bplist->ref_size);
449
+ index2 = UINT_TO_HOST(index2_ptr, bplist->ref_size);
450
+
451
+ if (index1 >= bplist->num_objects) {
452
+ plist_free(node);
453
+ PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": key index (%" PRIu64 ") must be smaller than the number of objects (%" PRIu64 ")\n", __func__, j, index1, bplist->num_objects);
454
+ return NULL;
455
+ }
456
+ if (index2 >= bplist->num_objects) {
457
+ plist_free(node);
458
+ PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": value index (%" PRIu64 ") must be smaller than the number of objects (%" PRIu64 ")\n", __func__, j, index1, bplist->num_objects);
459
+ return NULL;
460
+ }
461
+
462
+ /* process key node */
463
+ plist_t key = parse_bin_node_at_index(bplist, index1);
464
+ if (!key) {
465
+ plist_free(node);
466
+ return NULL;
467
+ }
468
+
469
+ if (plist_get_data(key)->type != PLIST_STRING) {
470
+ PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": invalid node type for key\n", __func__, j);
471
+ plist_free(key);
472
+ plist_free(node);
473
+ return NULL;
474
+ }
475
+
476
+ /* enforce key type */
477
+ plist_get_data(key)->type = PLIST_KEY;
478
+ if (!plist_get_data(key)->strval) {
479
+ PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": key must not be NULL\n", __func__, j);
480
+ plist_free(key);
481
+ plist_free(node);
482
+ return NULL;
483
+ }
484
+
485
+ /* process value node */
486
+ plist_t val = parse_bin_node_at_index(bplist, index2);
487
+ if (!val) {
488
+ plist_free(key);
489
+ plist_free(node);
490
+ return NULL;
491
+ }
492
+
493
+ node_attach(node, key);
494
+ node_attach(node, val);
495
+ }
496
+
497
+ return node;
498
+ }
499
+
500
+ static plist_t parse_array_node(struct bplist_data *bplist, const char** bnode, uint64_t size)
501
+ {
502
+ uint64_t j;
503
+ uint64_t str_j = 0;
504
+ uint64_t index1;
505
+ plist_data_t data = plist_new_plist_data();
506
+ const char *index1_ptr = NULL;
507
+
508
+ data->type = PLIST_ARRAY;
509
+ data->length = size;
510
+
511
+ plist_t node = node_create(NULL, data);
512
+
513
+ for (j = 0; j < data->length; j++) {
514
+ str_j = j * bplist->ref_size;
515
+ index1_ptr = (*bnode) + str_j;
516
+
517
+ if (index1_ptr < bplist->data || index1_ptr + bplist->ref_size > bplist->offset_table) {
518
+ plist_free(node);
519
+ PLIST_BIN_ERR("%s: array item %" PRIu64 " is outside of valid range\n", __func__, j);
520
+ return NULL;
521
+ }
522
+
523
+ index1 = UINT_TO_HOST(index1_ptr, bplist->ref_size);
524
+
525
+ if (index1 >= bplist->num_objects) {
526
+ plist_free(node);
527
+ PLIST_BIN_ERR("%s: array item %" PRIu64 " object index (%" PRIu64 ") must be smaller than the number of objects (%" PRIu64 ")\n", __func__, j, index1, bplist->num_objects);
528
+ return NULL;
529
+ }
530
+
531
+ /* process value node */
532
+ plist_t val = parse_bin_node_at_index(bplist, index1);
533
+ if (!val) {
534
+ plist_free(node);
535
+ return NULL;
536
+ }
537
+
538
+ node_attach(node, val);
539
+ }
540
+
541
+ return node;
542
+ }
543
+
544
+ static plist_t parse_uid_node(const char **bnode, uint8_t size)
545
+ {
546
+ plist_data_t data = plist_new_plist_data();
547
+ size = size + 1;
548
+ data->intval = UINT_TO_HOST(*bnode, size);
549
+ if (data->intval > UINT32_MAX) {
550
+ PLIST_BIN_ERR("%s: value %" PRIu64 " too large for UID node (must be <= %u)\n", __func__, (uint64_t)data->intval, UINT32_MAX);
551
+ free(data);
552
+ return NULL;
553
+ }
554
+
555
+ (*bnode) += size;
556
+ data->type = PLIST_UID;
557
+ data->length = sizeof(uint64_t);
558
+
559
+ return node_create(NULL, data);
560
+ }
561
+
562
+ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object)
563
+ {
564
+ uint16_t type = 0;
565
+ uint64_t size = 0;
566
+ uint64_t pobject = 0;
567
+ uint64_t poffset_table = (uint64_t)(uintptr_t)bplist->offset_table;
568
+
569
+ if (!object)
570
+ return NULL;
571
+
572
+ type = (**object) & BPLIST_MASK;
573
+ size = (**object) & BPLIST_FILL;
574
+ (*object)++;
575
+
576
+ if (size == BPLIST_FILL) {
577
+ switch (type) {
578
+ case BPLIST_DATA:
579
+ case BPLIST_STRING:
580
+ case BPLIST_UNICODE:
581
+ case BPLIST_ARRAY:
582
+ case BPLIST_SET:
583
+ case BPLIST_DICT:
584
+ {
585
+ uint16_t next_size = **object & BPLIST_FILL;
586
+ if ((**object & BPLIST_MASK) != BPLIST_UINT) {
587
+ PLIST_BIN_ERR("%s: invalid size node type for node type 0x%02x: found 0x%02x, expected 0x%02x\n", __func__, type, **object & BPLIST_MASK, BPLIST_UINT);
588
+ return NULL;
589
+ }
590
+ (*object)++;
591
+ next_size = 1 << next_size;
592
+ if (*object + next_size > bplist->offset_table) {
593
+ PLIST_BIN_ERR("%s: size node data bytes for node type 0x%02x point outside of valid range\n", __func__, type);
594
+ return NULL;
595
+ }
596
+ size = UINT_TO_HOST(*object, next_size);
597
+ (*object) += next_size;
598
+ break;
599
+ }
600
+ default:
601
+ break;
602
+ }
603
+ }
604
+
605
+ pobject = (uint64_t)(uintptr_t)*object;
606
+
607
+ switch (type)
608
+ {
609
+
610
+ case BPLIST_NULL:
611
+ switch (size)
612
+ {
613
+
614
+ case BPLIST_TRUE:
615
+ {
616
+ plist_data_t data = plist_new_plist_data();
617
+ data->type = PLIST_BOOLEAN;
618
+ data->boolval = TRUE;
619
+ data->length = 1;
620
+ return node_create(NULL, data);
621
+ }
622
+
623
+ case BPLIST_FALSE:
624
+ {
625
+ plist_data_t data = plist_new_plist_data();
626
+ data->type = PLIST_BOOLEAN;
627
+ data->boolval = FALSE;
628
+ data->length = 1;
629
+ return node_create(NULL, data);
630
+ }
631
+
632
+ case BPLIST_NULL:
633
+ default:
634
+ return NULL;
635
+ }
636
+
637
+ case BPLIST_UINT:
638
+ if (pobject + (uint64_t)(1 << size) > poffset_table) {
639
+ PLIST_BIN_ERR("%s: BPLIST_UINT data bytes point outside of valid range\n", __func__);
640
+ return NULL;
641
+ }
642
+ return parse_uint_node(object, size);
643
+
644
+ case BPLIST_REAL:
645
+ if (pobject + (uint64_t)(1 << size) > poffset_table) {
646
+ PLIST_BIN_ERR("%s: BPLIST_REAL data bytes point outside of valid range\n", __func__);
647
+ return NULL;
648
+ }
649
+ return parse_real_node(object, size);
650
+
651
+ case BPLIST_DATE:
652
+ if (3 != size) {
653
+ PLIST_BIN_ERR("%s: invalid data size for BPLIST_DATE node\n", __func__);
654
+ return NULL;
655
+ }
656
+ if (pobject + (uint64_t)(1 << size) > poffset_table) {
657
+ PLIST_BIN_ERR("%s: BPLIST_DATE data bytes point outside of valid range\n", __func__);
658
+ return NULL;
659
+ }
660
+ return parse_date_node(object, size);
661
+
662
+ case BPLIST_DATA:
663
+ if (pobject + size < pobject || pobject + size > poffset_table) {
664
+ PLIST_BIN_ERR("%s: BPLIST_DATA data bytes point outside of valid range\n", __func__);
665
+ return NULL;
666
+ }
667
+ return parse_data_node(object, size);
668
+
669
+ case BPLIST_STRING:
670
+ if (pobject + size < pobject || pobject + size > poffset_table) {
671
+ PLIST_BIN_ERR("%s: BPLIST_STRING data bytes point outside of valid range\n", __func__);
672
+ return NULL;
673
+ }
674
+ return parse_string_node(object, size);
675
+
676
+ case BPLIST_UNICODE:
677
+ if (size*2 < size) {
678
+ PLIST_BIN_ERR("%s: Integer overflow when calculating BPLIST_UNICODE data size.\n", __func__);
679
+ return NULL;
680
+ }
681
+ if (pobject + size*2 < pobject || pobject + size*2 > poffset_table) {
682
+ PLIST_BIN_ERR("%s: BPLIST_UNICODE data bytes point outside of valid range\n", __func__);
683
+ return NULL;
684
+ }
685
+ return parse_unicode_node(object, size);
686
+
687
+ case BPLIST_SET:
688
+ case BPLIST_ARRAY:
689
+ if (pobject + size < pobject || pobject + size > poffset_table) {
690
+ PLIST_BIN_ERR("%s: BPLIST_ARRAY data bytes point outside of valid range\n", __func__);
691
+ return NULL;
692
+ }
693
+ return parse_array_node(bplist, object, size);
694
+
695
+ case BPLIST_UID:
696
+ if (pobject + size+1 > poffset_table) {
697
+ PLIST_BIN_ERR("%s: BPLIST_UID data bytes point outside of valid range\n", __func__);
698
+ return NULL;
699
+ }
700
+ return parse_uid_node(object, size);
701
+
702
+ case BPLIST_DICT:
703
+ if (pobject + size < pobject || pobject + size > poffset_table) {
704
+ PLIST_BIN_ERR("%s: BPLIST_DICT data bytes point outside of valid range\n", __func__);
705
+ return NULL;
706
+ }
707
+ return parse_dict_node(bplist, object, size);
708
+
709
+ default:
710
+ PLIST_BIN_ERR("%s: unexpected node type 0x%02x\n", __func__, type);
711
+ return NULL;
712
+ }
713
+ return NULL;
714
+ }
715
+
716
+ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node_index)
717
+ {
718
+ int i = 0;
719
+ const char* ptr = NULL;
720
+ plist_t plist = NULL;
721
+ const char* idx_ptr = NULL;
722
+
723
+ if (node_index >= bplist->num_objects) {
724
+ PLIST_BIN_ERR("node index (%u) must be smaller than the number of objects (%" PRIu64 ")\n", node_index, bplist->num_objects);
725
+ return NULL;
726
+ }
727
+
728
+ idx_ptr = bplist->offset_table + node_index * bplist->offset_size;
729
+ if (idx_ptr < bplist->offset_table ||
730
+ idx_ptr >= bplist->offset_table + bplist->num_objects * bplist->offset_size) {
731
+ PLIST_BIN_ERR("node index %u points outside of valid range\n", node_index);
732
+ return NULL;
733
+ }
734
+
735
+ ptr = bplist->data + UINT_TO_HOST(idx_ptr, bplist->offset_size);
736
+ /* make sure the node offset is in a sane range */
737
+ if ((ptr < bplist->data) || (ptr >= bplist->offset_table)) {
738
+ PLIST_BIN_ERR("offset for node index %u points outside of valid range\n", node_index);
739
+ return NULL;
740
+ }
741
+
742
+ /* store node_index for current recursion level */
743
+ if ((uint32_t)ptr_array_size(bplist->used_indexes) < bplist->level+1) {
744
+ while ((uint32_t)ptr_array_size(bplist->used_indexes) < bplist->level+1) {
745
+ ptr_array_add(bplist->used_indexes, (void*)(uintptr_t)node_index);
746
+ }
747
+ } else {
748
+ ptr_array_set(bplist->used_indexes, (void*)(uintptr_t)node_index, bplist->level);
749
+ }
750
+
751
+ /* recursion check */
752
+ if (bplist->level > 0) {
753
+ for (i = bplist->level-1; i >= 0; i--) {
754
+ uint32_t node_i = (uint32_t)(uintptr_t)ptr_array_index(bplist->used_indexes, i);
755
+ uint32_t node_level = (uint32_t)(uintptr_t)ptr_array_index(bplist->used_indexes, bplist->level);
756
+ if (node_i == node_level) {
757
+ PLIST_BIN_ERR("recursion detected in binary plist\n");
758
+ return NULL;
759
+ }
760
+ }
761
+ }
762
+
763
+ /* finally parse node */
764
+ bplist->level++;
765
+ plist = parse_bin_node(bplist, &ptr);
766
+ bplist->level--;
767
+ return plist;
768
+ }
769
+
770
+ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist)
771
+ {
772
+ bplist_trailer_t *trailer = NULL;
773
+ uint8_t offset_size = 0;
774
+ uint8_t ref_size = 0;
775
+ uint64_t num_objects = 0;
776
+ uint64_t root_object = 0;
777
+ const char *offset_table = NULL;
778
+ uint64_t offset_table_size = 0;
779
+ const char *start_data = NULL;
780
+ const char *end_data = NULL;
781
+
782
+ //first check we have enough data
783
+ if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) {
784
+ PLIST_BIN_ERR("plist data is to small to hold a binary plist\n");
785
+ return;
786
+ }
787
+ //check that plist_bin in actually a plist
788
+ if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) {
789
+ PLIST_BIN_ERR("bplist magic mismatch\n");
790
+ return;
791
+ }
792
+ //check for known version
793
+ if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) {
794
+ PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE);
795
+ return;
796
+ }
797
+
798
+ start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE;
799
+ end_data = plist_bin + length - sizeof(bplist_trailer_t);
800
+
801
+ //now parse trailer
802
+ trailer = (bplist_trailer_t*)end_data;
803
+
804
+ offset_size = trailer->offset_size;
805
+ ref_size = trailer->ref_size;
806
+ num_objects = be64toh(trailer->num_objects);
807
+ root_object = be64toh(trailer->root_object_index);
808
+ offset_table = (char *)(plist_bin + be64toh(trailer->offset_table_offset));
809
+
810
+ if (num_objects == 0) {
811
+ PLIST_BIN_ERR("number of objects must be larger than 0\n");
812
+ return;
813
+ }
814
+
815
+ if (offset_size == 0) {
816
+ PLIST_BIN_ERR("offset size in trailer must be larger than 0\n");
817
+ return;
818
+ }
819
+
820
+ if (ref_size == 0) {
821
+ PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n");
822
+ return;
823
+ }
824
+
825
+ if (root_object >= num_objects) {
826
+ PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects);
827
+ return;
828
+ }
829
+
830
+ if (offset_table < start_data || offset_table >= end_data) {
831
+ PLIST_BIN_ERR("offset table offset points outside of valid range\n");
832
+ return;
833
+ }
834
+
835
+ if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) {
836
+ PLIST_BIN_ERR("integer overflow when calculating offset table size\n");
837
+ return;
838
+ }
839
+
840
+ if ((offset_table + offset_table_size < offset_table) || (offset_table + offset_table_size > end_data)) {
841
+ PLIST_BIN_ERR("offset table points outside of valid range\n");
842
+ return;
843
+ }
844
+
845
+ struct bplist_data bplist;
846
+ bplist.data = plist_bin;
847
+ bplist.size = length;
848
+ bplist.num_objects = num_objects;
849
+ bplist.ref_size = ref_size;
850
+ bplist.offset_size = offset_size;
851
+ bplist.offset_table = offset_table;
852
+ bplist.level = 0;
853
+ bplist.used_indexes = ptr_array_new(16);
854
+
855
+ if (!bplist.used_indexes) {
856
+ PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n");
857
+ return;
858
+ }
859
+
860
+ *plist = parse_bin_node_at_index(&bplist, root_object);
861
+
862
+ ptr_array_free(bplist.used_indexes);
863
+ }
864
+
865
+ static unsigned int plist_data_hash(const void* key)
866
+ {
867
+ plist_data_t data = plist_get_data((plist_t) key);
868
+
869
+ unsigned int hash = data->type;
870
+ unsigned int i = 0;
871
+
872
+ char *buff = NULL;
873
+ unsigned int size = 0;
874
+
875
+ switch (data->type)
876
+ {
877
+ case PLIST_BOOLEAN:
878
+ case PLIST_UINT:
879
+ case PLIST_REAL:
880
+ case PLIST_DATE:
881
+ case PLIST_UID:
882
+ buff = (char *) &data->intval; //works also for real as we use an union
883
+ size = 8;
884
+ break;
885
+ case PLIST_KEY:
886
+ case PLIST_STRING:
887
+ buff = data->strval;
888
+ size = data->length;
889
+ break;
890
+ case PLIST_DATA:
891
+ case PLIST_ARRAY:
892
+ case PLIST_DICT:
893
+ //for these types only hash pointer
894
+ buff = (char *) &key;
895
+ size = sizeof(const void*);
896
+ break;
897
+ default:
898
+ break;
899
+ }
900
+
901
+ // now perform hash using djb2 hashing algorithm
902
+ // see: http://www.cse.yorku.ca/~oz/hash.html
903
+ hash += 5381;
904
+ for (i = 0; i < size; buff++, i++) {
905
+ hash = ((hash << 5) + hash) + *buff;
906
+ }
907
+
908
+ return hash;
909
+ }
910
+
911
+ struct serialize_s
912
+ {
913
+ ptrarray_t* objects;
914
+ hashtable_t* ref_table;
915
+ };
916
+
917
+ static void serialize_plist(node_t* node, void* data)
918
+ {
919
+ uint64_t *index_val = NULL;
920
+ struct serialize_s *ser = (struct serialize_s *) data;
921
+ uint64_t current_index = ser->objects->len;
922
+
923
+ //first check that node is not yet in objects
924
+ void* val = hash_table_lookup(ser->ref_table, node);
925
+ if (val)
926
+ {
927
+ //data is already in table
928
+ return;
929
+ }
930
+ //insert new ref
931
+ index_val = (uint64_t *) malloc(sizeof(uint64_t));
932
+ assert(index_val != NULL);
933
+ *index_val = current_index;
934
+ hash_table_insert(ser->ref_table, node, index_val);
935
+
936
+ //now append current node to object array
937
+ ptr_array_add(ser->objects, node);
938
+
939
+ //now recurse on children
940
+ node_t *ch;
941
+ for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
942
+ serialize_plist(ch, data);
943
+ }
944
+ }
945
+
946
+ #define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0)))
947
+
948
+ static void write_int(bytearray_t * bplist, uint64_t val)
949
+ {
950
+ int size = get_needed_bytes(val);
951
+ uint8_t sz;
952
+ //do not write 3bytes int node
953
+ if (size == 3)
954
+ size++;
955
+ sz = BPLIST_UINT | Log2(size);
956
+
957
+ val = be64toh(val);
958
+ byte_array_append(bplist, &sz, 1);
959
+ byte_array_append(bplist, (uint8_t*)&val + (8-size), size);
960
+ }
961
+
962
+ static void write_uint(bytearray_t * bplist, uint64_t val)
963
+ {
964
+ uint8_t sz = BPLIST_UINT | 4;
965
+ uint64_t zero = 0;
966
+
967
+ val = be64toh(val);
968
+ byte_array_append(bplist, &sz, 1);
969
+ byte_array_append(bplist, &zero, sizeof(uint64_t));
970
+ byte_array_append(bplist, &val, sizeof(uint64_t));
971
+ }
972
+
973
+ static void write_real(bytearray_t * bplist, double val)
974
+ {
975
+ int size = get_real_bytes(val); //cheat to know used space
976
+ uint8_t buff[16];
977
+ buff[7] = BPLIST_REAL | Log2(size);
978
+ if (size == sizeof(float)) {
979
+ float floatval = (float)val;
980
+ *(uint32_t*)(buff+8) = float_bswap32(*(uint32_t*)&floatval);
981
+ } else {
982
+ *(uint64_t*)(buff+8) = float_bswap64(*(uint64_t*)&val);
983
+ }
984
+ byte_array_append(bplist, buff+7, size+1);
985
+ }
986
+
987
+ static void write_date(bytearray_t * bplist, double val)
988
+ {
989
+ uint8_t buff[16];
990
+ buff[7] = BPLIST_DATE | 3;
991
+ *(uint64_t*)(buff+8) = float_bswap64(*(uint64_t*)&val);
992
+ byte_array_append(bplist, buff+7, 9);
993
+ }
994
+
995
+ static void write_raw_data(bytearray_t * bplist, uint8_t mark, uint8_t * val, uint64_t size)
996
+ {
997
+ uint8_t marker = mark | (size < 15 ? size : 0xf);
998
+ byte_array_append(bplist, &marker, sizeof(uint8_t));
999
+ if (size >= 15) {
1000
+ write_int(bplist, size);
1001
+ }
1002
+ if (BPLIST_UNICODE==mark) size <<= 1;
1003
+ byte_array_append(bplist, val, size);
1004
+ }
1005
+
1006
+ static void write_data(bytearray_t * bplist, uint8_t * val, uint64_t size)
1007
+ {
1008
+ write_raw_data(bplist, BPLIST_DATA, val, size);
1009
+ }
1010
+
1011
+ static void write_string(bytearray_t * bplist, char *val, uint64_t size)
1012
+ {
1013
+ write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size);
1014
+ }
1015
+
1016
+ static uint16_t *plist_utf8_to_utf16be(char *unistr, long size, long *items_read, long *items_written)
1017
+ {
1018
+ uint16_t *outbuf;
1019
+ int p = 0;
1020
+ long i = 0;
1021
+
1022
+ unsigned char c0;
1023
+ unsigned char c1;
1024
+ unsigned char c2;
1025
+ unsigned char c3;
1026
+
1027
+ uint32_t w;
1028
+
1029
+ outbuf = (uint16_t*)malloc(((size*2)+1)*sizeof(uint16_t));
1030
+ if (!outbuf) {
1031
+ PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, (uint64_t)((size*2)+1)*sizeof(uint16_t));
1032
+ return NULL;
1033
+ }
1034
+
1035
+ while (i < size) {
1036
+ c0 = unistr[i];
1037
+ c1 = (i < size-1) ? unistr[i+1] : 0;
1038
+ c2 = (i < size-2) ? unistr[i+2] : 0;
1039
+ c3 = (i < size-3) ? unistr[i+3] : 0;
1040
+ if ((c0 >= 0xF0) && (i < size-3) && (c1 >= 0x80) && (c2 >= 0x80) && (c3 >= 0x80)) {
1041
+ // 4 byte sequence. Need to generate UTF-16 surrogate pair
1042
+ w = ((((c0 & 7) << 18) + ((c1 & 0x3F) << 12) + ((c2 & 0x3F) << 6) + (c3 & 0x3F)) & 0x1FFFFF) - 0x010000;
1043
+ outbuf[p++] = be16toh(0xD800 + (w >> 10));
1044
+ outbuf[p++] = be16toh(0xDC00 + (w & 0x3FF));
1045
+ i+=4;
1046
+ } else if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) {
1047
+ // 3 byte sequence
1048
+ outbuf[p++] = be16toh(((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12));
1049
+ i+=3;
1050
+ } else if ((c0 >= 0xC0) && (i < size-1) && (c1 >= 0x80)) {
1051
+ // 2 byte sequence
1052
+ outbuf[p++] = be16toh(((c1 & 0x3F) + ((c0 & 3) << 6)) + (((c0 >> 2) & 7) << 8));
1053
+ i+=2;
1054
+ } else if (c0 < 0x80) {
1055
+ // 1 byte sequence
1056
+ outbuf[p++] = be16toh(c0);
1057
+ i+=1;
1058
+ } else {
1059
+ // invalid character
1060
+ PLIST_BIN_ERR("%s: invalid utf8 sequence in string at index %lu\n", __func__, i);
1061
+ break;
1062
+ }
1063
+ }
1064
+ if (items_read) {
1065
+ *items_read = i;
1066
+ }
1067
+ if (items_written) {
1068
+ *items_written = p;
1069
+ }
1070
+ outbuf[p] = 0;
1071
+
1072
+ return outbuf;
1073
+ }
1074
+
1075
+ static void write_unicode(bytearray_t * bplist, char *val, uint64_t size)
1076
+ {
1077
+ long items_read = 0;
1078
+ long items_written = 0;
1079
+ uint16_t *unicodestr = NULL;
1080
+
1081
+ unicodestr = plist_utf8_to_utf16be(val, size, &items_read, &items_written);
1082
+ write_raw_data(bplist, BPLIST_UNICODE, (uint8_t*)unicodestr, items_written);
1083
+ free(unicodestr);
1084
+ }
1085
+
1086
+ static void write_array(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t ref_size)
1087
+ {
1088
+ node_t* cur = NULL;
1089
+ uint64_t i = 0;
1090
+
1091
+ uint64_t size = node_n_children(node);
1092
+ uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf);
1093
+ byte_array_append(bplist, &marker, sizeof(uint8_t));
1094
+ if (size >= 15) {
1095
+ write_int(bplist, size);
1096
+ }
1097
+
1098
+ for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(cur), i++) {
1099
+ uint64_t idx = *(uint64_t *) (hash_table_lookup(ref_table, cur));
1100
+ idx = be64toh(idx);
1101
+ byte_array_append(bplist, (uint8_t*)&idx + (sizeof(uint64_t) - ref_size), ref_size);
1102
+ }
1103
+ }
1104
+
1105
+ static void write_dict(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t ref_size)
1106
+ {
1107
+ node_t* cur = NULL;
1108
+ uint64_t i = 0;
1109
+
1110
+ uint64_t size = node_n_children(node) / 2;
1111
+ uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf);
1112
+ byte_array_append(bplist, &marker, sizeof(uint8_t));
1113
+ if (size >= 15) {
1114
+ write_int(bplist, size);
1115
+ }
1116
+
1117
+ for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(node_next_sibling(cur)), i++) {
1118
+ uint64_t idx1 = *(uint64_t *) (hash_table_lookup(ref_table, cur));
1119
+ idx1 = be64toh(idx1);
1120
+ byte_array_append(bplist, (uint8_t*)&idx1 + (sizeof(uint64_t) - ref_size), ref_size);
1121
+ }
1122
+
1123
+ for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(node_next_sibling(cur)), i++) {
1124
+ uint64_t idx2 = *(uint64_t *) (hash_table_lookup(ref_table, cur->next));
1125
+ idx2 = be64toh(idx2);
1126
+ byte_array_append(bplist, (uint8_t*)&idx2 + (sizeof(uint64_t) - ref_size), ref_size);
1127
+ }
1128
+ }
1129
+
1130
+ static void write_uid(bytearray_t * bplist, uint64_t val)
1131
+ {
1132
+ val = (uint32_t)val;
1133
+ int size = get_needed_bytes(val);
1134
+ uint8_t sz;
1135
+ //do not write 3bytes int node
1136
+ if (size == 3)
1137
+ size++;
1138
+ sz = BPLIST_UID | (size-1); // yes, this is what Apple does...
1139
+
1140
+ val = be64toh(val);
1141
+ byte_array_append(bplist, &sz, 1);
1142
+ byte_array_append(bplist, (uint8_t*)&val + (8-size), size);
1143
+ }
1144
+
1145
+ static int is_ascii_string(char* s, int len)
1146
+ {
1147
+ int ret = 1, i = 0;
1148
+ for(i = 0; i < len; i++)
1149
+ {
1150
+ if ( !isascii( s[i] ) )
1151
+ {
1152
+ ret = 0;
1153
+ break;
1154
+ }
1155
+ }
1156
+ return ret;
1157
+ }
1158
+
1159
+ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1160
+ {
1161
+ ptrarray_t* objects = NULL;
1162
+ hashtable_t* ref_table = NULL;
1163
+ struct serialize_s ser_s;
1164
+ uint8_t offset_size = 0;
1165
+ uint8_t ref_size = 0;
1166
+ uint64_t num_objects = 0;
1167
+ uint64_t root_object = 0;
1168
+ uint64_t offset_table_index = 0;
1169
+ bytearray_t *bplist_buff = NULL;
1170
+ uint64_t i = 0;
1171
+ uint64_t buff_len = 0;
1172
+ uint64_t *offsets = NULL;
1173
+ bplist_trailer_t trailer;
1174
+ uint64_t objects_len = 0;
1175
+
1176
+ //check for valid input
1177
+ if (!plist || !plist_bin || *plist_bin || !length)
1178
+ return;
1179
+
1180
+ //list of objects
1181
+ objects = ptr_array_new(4096);
1182
+ //hashtable to write only once same nodes
1183
+ ref_table = hash_table_new(plist_data_hash, plist_data_compare, free);
1184
+
1185
+ //serialize plist
1186
+ ser_s.objects = objects;
1187
+ ser_s.ref_table = ref_table;
1188
+ serialize_plist(plist, &ser_s);
1189
+
1190
+ //now stream to output buffer
1191
+ offset_size = 0; //unknown yet
1192
+ objects_len = objects->len;
1193
+ ref_size = get_needed_bytes(objects_len);
1194
+ num_objects = objects->len;
1195
+ root_object = 0; //root is first in list
1196
+ offset_table_index = 0; //unknown yet
1197
+
1198
+ //figure out the storage size required
1199
+ uint64_t req = 0;
1200
+ for (i = 0; i < num_objects; i++)
1201
+ {
1202
+ node_t* node = ptr_array_index(objects, i);
1203
+ plist_data_t data = plist_get_data(node);
1204
+ uint64_t size;
1205
+ uint8_t bsize;
1206
+ switch (data->type)
1207
+ {
1208
+ case PLIST_BOOLEAN:
1209
+ req += 1;
1210
+ break;
1211
+ case PLIST_KEY:
1212
+ case PLIST_STRING:
1213
+ req += 1;
1214
+ if (data->length >= 15) {
1215
+ bsize = get_needed_bytes(data->length);
1216
+ if (bsize == 3) bsize = 4;
1217
+ req += 1;
1218
+ req += bsize;
1219
+ }
1220
+ if ( is_ascii_string(data->strval, data->length) )
1221
+ {
1222
+ req += data->length;
1223
+ }
1224
+ else
1225
+ {
1226
+ req += data->length * 2;
1227
+ }
1228
+ break;
1229
+ case PLIST_REAL:
1230
+ size = get_real_bytes(data->realval);
1231
+ req += 1;
1232
+ req += size;
1233
+ break;
1234
+ case PLIST_DATE:
1235
+ req += 9;
1236
+ break;
1237
+ case PLIST_ARRAY:
1238
+ size = node_n_children(node);
1239
+ req += 1;
1240
+ if (size >= 15) {
1241
+ bsize = get_needed_bytes(size);
1242
+ if (bsize == 3) bsize = 4;
1243
+ req += 1;
1244
+ req += bsize;
1245
+ }
1246
+ req += size * ref_size;
1247
+ break;
1248
+ case PLIST_DICT:
1249
+ size = node_n_children(node) / 2;
1250
+ req += 1;
1251
+ if (size >= 15) {
1252
+ bsize = get_needed_bytes(size);
1253
+ if (bsize == 3) bsize = 4;
1254
+ req += 1;
1255
+ req += bsize;
1256
+ }
1257
+ req += size * 2 * ref_size;
1258
+ break;
1259
+ default:
1260
+ size = data->length;
1261
+ req += 1;
1262
+ if (size >= 15) {
1263
+ bsize = get_needed_bytes(size);
1264
+ if (bsize == 3) bsize = 4;
1265
+ req += 1;
1266
+ req += bsize;
1267
+ }
1268
+ req += data->length;
1269
+ break;
1270
+ }
1271
+ }
1272
+ // add size of magic
1273
+ req += BPLIST_MAGIC_SIZE;
1274
+ req += BPLIST_VERSION_SIZE;
1275
+ // add size of offset table
1276
+ req += get_needed_bytes(req) * num_objects;
1277
+ // add size of trailer
1278
+ req += sizeof(bplist_trailer_t);
1279
+
1280
+ //setup a dynamic bytes array to store bplist in
1281
+ bplist_buff = byte_array_new(req);
1282
+
1283
+ //set magic number and version
1284
+ byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE);
1285
+ byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE);
1286
+
1287
+ //write objects and table
1288
+ offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t));
1289
+ assert(offsets != NULL);
1290
+ for (i = 0; i < num_objects; i++)
1291
+ {
1292
+
1293
+ plist_data_t data = plist_get_data(ptr_array_index(objects, i));
1294
+ offsets[i] = bplist_buff->len;
1295
+
1296
+ switch (data->type)
1297
+ {
1298
+ case PLIST_BOOLEAN: {
1299
+ uint8_t b = data->boolval ? BPLIST_TRUE : BPLIST_FALSE;
1300
+ byte_array_append(bplist_buff, &b, 1);
1301
+ break;
1302
+ }
1303
+ case PLIST_UINT:
1304
+ if (data->length == 16) {
1305
+ write_uint(bplist_buff, data->intval);
1306
+ } else {
1307
+ write_int(bplist_buff, data->intval);
1308
+ }
1309
+ break;
1310
+
1311
+ case PLIST_REAL:
1312
+ write_real(bplist_buff, data->realval);
1313
+ break;
1314
+
1315
+ case PLIST_KEY:
1316
+ case PLIST_STRING:
1317
+ if ( is_ascii_string(data->strval, data->length) )
1318
+ {
1319
+ write_string(bplist_buff, data->strval, data->length);
1320
+ }
1321
+ else
1322
+ {
1323
+ write_unicode(bplist_buff, data->strval, data->length);
1324
+ }
1325
+ break;
1326
+ case PLIST_DATA:
1327
+ write_data(bplist_buff, data->buff, data->length);
1328
+ break;
1329
+ case PLIST_ARRAY:
1330
+ write_array(bplist_buff, ptr_array_index(objects, i), ref_table, ref_size);
1331
+ break;
1332
+ case PLIST_DICT:
1333
+ write_dict(bplist_buff, ptr_array_index(objects, i), ref_table, ref_size);
1334
+ break;
1335
+ case PLIST_DATE:
1336
+ write_date(bplist_buff, data->realval);
1337
+ break;
1338
+ case PLIST_UID:
1339
+ write_uid(bplist_buff, data->intval);
1340
+ break;
1341
+ default:
1342
+ break;
1343
+ }
1344
+ }
1345
+
1346
+ //free intermediate objects
1347
+ ptr_array_free(objects);
1348
+ hash_table_destroy(ref_table);
1349
+
1350
+ //write offsets
1351
+ buff_len = bplist_buff->len;
1352
+ offset_size = get_needed_bytes(buff_len);
1353
+ offset_table_index = bplist_buff->len;
1354
+ for (i = 0; i < num_objects; i++) {
1355
+ uint64_t offset = be64toh(offsets[i]);
1356
+ byte_array_append(bplist_buff, (uint8_t*)&offset + (sizeof(uint64_t) - offset_size), offset_size);
1357
+ }
1358
+ free(offsets);
1359
+
1360
+ //setup trailer
1361
+ memset(trailer.unused, '\0', sizeof(trailer.unused));
1362
+ trailer.offset_size = offset_size;
1363
+ trailer.ref_size = ref_size;
1364
+ trailer.num_objects = be64toh(num_objects);
1365
+ trailer.root_object_index = be64toh(root_object);
1366
+ trailer.offset_table_offset = be64toh(offset_table_index);
1367
+
1368
+ byte_array_append(bplist_buff, &trailer, sizeof(bplist_trailer_t));
1369
+
1370
+ //set output buffer and size
1371
+ *plist_bin = bplist_buff->data;
1372
+ *length = bplist_buff->len;
1373
+
1374
+ bplist_buff->data = NULL; // make sure we don't free the output buffer
1375
+ byte_array_free(bplist_buff);
1376
+ }
1377
+
1378
+ PLIST_API void plist_to_bin_free(char *plist_bin)
1379
+ {
1380
+ free(plist_bin);
1381
+ }