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.
- package/.github/workflows/npm-publish.yml +41 -0
- package/Formula/appwrite.rb +19 -0
- package/LICENSE.md +12 -0
- package/README.md +102 -0
- package/docs/examples/account/create-anonymous-session.md +1 -0
- package/docs/examples/account/create-j-w-t.md +1 -0
- package/docs/examples/account/create-magic-u-r-l-session.md +4 -0
- package/docs/examples/account/create-o-auth2session.md +5 -0
- package/docs/examples/account/create-recovery.md +3 -0
- package/docs/examples/account/create-session.md +3 -0
- package/docs/examples/account/create-verification.md +2 -0
- package/docs/examples/account/create.md +5 -0
- package/docs/examples/account/delete-session.md +2 -0
- package/docs/examples/account/delete-sessions.md +1 -0
- package/docs/examples/account/delete.md +1 -0
- package/docs/examples/account/get-logs.md +3 -0
- package/docs/examples/account/get-prefs.md +1 -0
- package/docs/examples/account/get-session.md +2 -0
- package/docs/examples/account/get-sessions.md +1 -0
- package/docs/examples/account/get.md +1 -0
- package/docs/examples/account/update-email.md +3 -0
- package/docs/examples/account/update-magic-u-r-l-session.md +3 -0
- package/docs/examples/account/update-name.md +2 -0
- package/docs/examples/account/update-password.md +3 -0
- package/docs/examples/account/update-prefs.md +2 -0
- package/docs/examples/account/update-recovery.md +5 -0
- package/docs/examples/account/update-session.md +2 -0
- package/docs/examples/account/update-verification.md +3 -0
- package/docs/examples/avatars/get-browser.md +5 -0
- package/docs/examples/avatars/get-credit-card.md +5 -0
- package/docs/examples/avatars/get-favicon.md +2 -0
- package/docs/examples/avatars/get-flag.md +5 -0
- package/docs/examples/avatars/get-image.md +4 -0
- package/docs/examples/avatars/get-initials.md +6 -0
- package/docs/examples/avatars/get-q-r.md +5 -0
- package/docs/examples/database/create-boolean-attribute.md +6 -0
- package/docs/examples/database/create-collection.md +6 -0
- package/docs/examples/database/create-document.md +6 -0
- package/docs/examples/database/create-email-attribute.md +6 -0
- package/docs/examples/database/create-enum-attribute.md +7 -0
- package/docs/examples/database/create-float-attribute.md +8 -0
- package/docs/examples/database/create-index.md +6 -0
- package/docs/examples/database/create-integer-attribute.md +8 -0
- package/docs/examples/database/create-ip-attribute.md +6 -0
- package/docs/examples/database/create-string-attribute.md +7 -0
- package/docs/examples/database/create-url-attribute.md +6 -0
- package/docs/examples/database/delete-attribute.md +3 -0
- package/docs/examples/database/delete-collection.md +2 -0
- package/docs/examples/database/delete-document.md +3 -0
- package/docs/examples/database/delete-index.md +3 -0
- package/docs/examples/database/get-attribute.md +3 -0
- package/docs/examples/database/get-collection-usage.md +3 -0
- package/docs/examples/database/get-collection.md +2 -0
- package/docs/examples/database/get-document.md +3 -0
- package/docs/examples/database/get-index.md +3 -0
- package/docs/examples/database/get-usage.md +2 -0
- package/docs/examples/database/list-attributes.md +2 -0
- package/docs/examples/database/list-collection-logs.md +4 -0
- package/docs/examples/database/list-collections.md +7 -0
- package/docs/examples/database/list-document-logs.md +5 -0
- package/docs/examples/database/list-documents.md +9 -0
- package/docs/examples/database/list-indexes.md +2 -0
- package/docs/examples/database/update-collection.md +7 -0
- package/docs/examples/database/update-document.md +6 -0
- package/docs/examples/functions/create-deployment.md +5 -0
- package/docs/examples/functions/create-execution.md +4 -0
- package/docs/examples/functions/create.md +9 -0
- package/docs/examples/functions/delete-deployment.md +3 -0
- package/docs/examples/functions/delete.md +2 -0
- package/docs/examples/functions/get-deployment.md +3 -0
- package/docs/examples/functions/get-execution.md +3 -0
- package/docs/examples/functions/get-usage.md +3 -0
- package/docs/examples/functions/get.md +2 -0
- package/docs/examples/functions/list-deployments.md +8 -0
- package/docs/examples/functions/list-executions.md +7 -0
- package/docs/examples/functions/list-runtimes.md +1 -0
- package/docs/examples/functions/list.md +7 -0
- package/docs/examples/functions/retry-build.md +4 -0
- package/docs/examples/functions/update-deployment.md +3 -0
- package/docs/examples/functions/update.md +8 -0
- package/docs/examples/health/get-antivirus.md +1 -0
- package/docs/examples/health/get-cache.md +1 -0
- package/docs/examples/health/get-d-b.md +1 -0
- package/docs/examples/health/get-queue-certificates.md +1 -0
- package/docs/examples/health/get-queue-functions.md +1 -0
- package/docs/examples/health/get-queue-logs.md +1 -0
- package/docs/examples/health/get-queue-usage.md +1 -0
- package/docs/examples/health/get-queue-webhooks.md +1 -0
- package/docs/examples/health/get-storage-local.md +1 -0
- package/docs/examples/health/get-time.md +1 -0
- package/docs/examples/health/get.md +1 -0
- package/docs/examples/locale/get-continents.md +1 -0
- package/docs/examples/locale/get-countries-e-u.md +1 -0
- package/docs/examples/locale/get-countries-phones.md +1 -0
- package/docs/examples/locale/get-countries.md +1 -0
- package/docs/examples/locale/get-currencies.md +1 -0
- package/docs/examples/locale/get-languages.md +1 -0
- package/docs/examples/locale/get.md +1 -0
- package/docs/examples/projects/create-domain.md +3 -0
- package/docs/examples/projects/create-key.md +4 -0
- package/docs/examples/projects/create-platform.md +7 -0
- package/docs/examples/projects/create-webhook.md +8 -0
- package/docs/examples/projects/create.md +13 -0
- package/docs/examples/projects/delete-domain.md +3 -0
- package/docs/examples/projects/delete-key.md +3 -0
- package/docs/examples/projects/delete-platform.md +3 -0
- package/docs/examples/projects/delete-webhook.md +3 -0
- package/docs/examples/projects/delete.md +3 -0
- package/docs/examples/projects/get-domain.md +3 -0
- package/docs/examples/projects/get-key.md +3 -0
- package/docs/examples/projects/get-platform.md +3 -0
- package/docs/examples/projects/get-usage.md +3 -0
- package/docs/examples/projects/get-webhook.md +3 -0
- package/docs/examples/projects/get.md +2 -0
- package/docs/examples/projects/list-domains.md +2 -0
- package/docs/examples/projects/list-keys.md +2 -0
- package/docs/examples/projects/list-platforms.md +2 -0
- package/docs/examples/projects/list-webhooks.md +2 -0
- package/docs/examples/projects/list.md +7 -0
- package/docs/examples/projects/update-auth-limit.md +3 -0
- package/docs/examples/projects/update-auth-status.md +4 -0
- package/docs/examples/projects/update-domain-verification.md +3 -0
- package/docs/examples/projects/update-key.md +5 -0
- package/docs/examples/projects/update-o-auth2.md +5 -0
- package/docs/examples/projects/update-platform.md +7 -0
- package/docs/examples/projects/update-service-status.md +4 -0
- package/docs/examples/projects/update-webhook.md +9 -0
- package/docs/examples/projects/update.md +12 -0
- package/docs/examples/storage/create-bucket.md +11 -0
- package/docs/examples/storage/create-file.md +6 -0
- package/docs/examples/storage/delete-bucket.md +2 -0
- package/docs/examples/storage/delete-file.md +3 -0
- package/docs/examples/storage/get-bucket-usage.md +3 -0
- package/docs/examples/storage/get-bucket.md +2 -0
- package/docs/examples/storage/get-file-download.md +3 -0
- package/docs/examples/storage/get-file-preview.md +14 -0
- package/docs/examples/storage/get-file-view.md +3 -0
- package/docs/examples/storage/get-file.md +3 -0
- package/docs/examples/storage/get-usage.md +2 -0
- package/docs/examples/storage/list-buckets.md +7 -0
- package/docs/examples/storage/list-files.md +8 -0
- package/docs/examples/storage/update-bucket.md +11 -0
- package/docs/examples/storage/update-file.md +5 -0
- package/docs/examples/teams/create-membership.md +6 -0
- package/docs/examples/teams/create.md +4 -0
- package/docs/examples/teams/delete-membership.md +3 -0
- package/docs/examples/teams/delete.md +2 -0
- package/docs/examples/teams/get-membership.md +3 -0
- package/docs/examples/teams/get-memberships.md +8 -0
- package/docs/examples/teams/get.md +2 -0
- package/docs/examples/teams/list.md +7 -0
- package/docs/examples/teams/update-membership-roles.md +4 -0
- package/docs/examples/teams/update-membership-status.md +5 -0
- package/docs/examples/teams/update.md +3 -0
- package/docs/examples/users/create.md +5 -0
- package/docs/examples/users/delete-session.md +3 -0
- package/docs/examples/users/delete-sessions.md +2 -0
- package/docs/examples/users/delete.md +2 -0
- package/docs/examples/users/get-logs.md +4 -0
- package/docs/examples/users/get-prefs.md +2 -0
- package/docs/examples/users/get-sessions.md +2 -0
- package/docs/examples/users/get-usage.md +3 -0
- package/docs/examples/users/get.md +2 -0
- package/docs/examples/users/list.md +7 -0
- package/docs/examples/users/update-email.md +3 -0
- package/docs/examples/users/update-name.md +3 -0
- package/docs/examples/users/update-password.md +3 -0
- package/docs/examples/users/update-prefs.md +3 -0
- package/docs/examples/users/update-status.md +3 -0
- package/docs/examples/users/update-verification.md +3 -0
- package/index.js +49 -0
- package/install.sh +165 -0
- package/ldid/COPYING +661 -0
- package/ldid/Makefile +51 -0
- package/ldid/control +12 -0
- package/ldid/control.sh +5 -0
- package/ldid/deb.sh +10 -0
- package/ldid/ios.sh +2 -0
- package/ldid/ldid.cpp +3253 -0
- package/ldid/ldid.hpp +164 -0
- package/ldid/libplist/.github/workflows/build.yml +62 -0
- package/ldid/libplist/.github/workflows/codeql-analysis.yml +71 -0
- package/ldid/libplist/AUTHORS +28 -0
- package/ldid/libplist/COPYING +340 -0
- package/ldid/libplist/COPYING.LESSER +502 -0
- package/ldid/libplist/Makefile.am +20 -0
- package/ldid/libplist/NEWS +252 -0
- package/ldid/libplist/README.md +114 -0
- package/ldid/libplist/aclocal.m4 +1729 -0
- package/ldid/libplist/autogen.sh +26 -0
- package/ldid/libplist/configure.ac +292 -0
- package/ldid/libplist/cython/Makefile.am +53 -0
- package/ldid/libplist/cython/plist.pxd +78 -0
- package/ldid/libplist/cython/plist.pyx +947 -0
- package/ldid/libplist/cython/plist_util.c +40 -0
- package/ldid/libplist/cython/plist_util.h +5 -0
- package/ldid/libplist/docs/Makefile.am +3 -0
- package/ldid/libplist/docs/plistutil.1 +62 -0
- package/ldid/libplist/fuzz/Makefile.am +43 -0
- package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-4766291097288704 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-4930725262393344 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-5421965105954816 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-5556177727389696 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-6557963011489792 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-6605859144597504 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-0ce4dd483b645bc05ec45a97d285dcf1933ee840 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-0d59cdcb5c3416c2790612b78a631ce9f5622800 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-17d635ab460fef74df1ac7561f1253533a6359c5 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-33a67313fa7864cd627ef92d12017a127d342f28 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-39f1347115f8fe9ac25cdc9332e3fc5cd32c7f7b +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-4bd78175fe01d07c5ee90104fbc68d95dd092210 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-4c5404453bb7425aef9b953a5f6f3f0afcc48392 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-52775e25f6af20af351cd616834e602fc988a032 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-6d1399685b745d3d49fadc91072fabcdde8d16fa +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-94b3725900d63c6258448fd757559c81002de9c9 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-a47195acbabc3f5b2cda9c6ebda42f2afc1cc5af +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-ce852bae6aeeffc4698a93660236f1b995ce966e +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-daddb6e82e3d1ed76e20e4131462f5247a6fb131 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-f21be4ebce7f9c337bf96b93cec7e252f5c75a21 +0 -0
- package/ldid/libplist/fuzz/bplist-crashes/crash-f779dafccc0164684d1a264976e56037188b40e2 +0 -0
- package/ldid/libplist/fuzz/bplist-leaks/leak-96fb453b3ba18d31e164831795a708183b5a0dac +0 -0
- package/ldid/libplist/fuzz/bplist-leaks/leak-acb3c00a83d7635638a476a4e70fc1f1caa1a5b1 +0 -0
- package/ldid/libplist/fuzz/bplist-leaks/leak-fe2cd4b1f67e0c9b21e6225a4fb4ca19eab80074 +0 -0
- package/ldid/libplist/fuzz/bplist.dict +1 -0
- package/ldid/libplist/fuzz/bplist_fuzzer.cc +32 -0
- package/ldid/libplist/fuzz/bplist_fuzzer.options +3 -0
- package/ldid/libplist/fuzz/fuzzers.test +8 -0
- package/ldid/libplist/fuzz/init-fuzzers.sh +23 -0
- package/ldid/libplist/fuzz/test-fuzzers.sh +33 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-4516959125241856 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-4663876528373760 +5 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-5799076113154048 +45 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-5922404220010496 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6015098361479168 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6043836860071936 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6047509906456576 +10050 -0
- package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6482601374121984 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-09788d7acb46b4b177422f9c4ee54556a3ad1f17 +53 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-155c60d5c4b2778110fb4a633caa7d64eb9b99c1 +9 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-348c909a0b3532977185f551eb5d2ed04e694883 +11 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-7bc172e27a2b1d4fcaf031f59d1f08fb83081e4a +8 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-80c28b0e2a446665e68927dd4441c10c9a68e64e +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-8acf177da60ecf13c36d0da1b8e25de891980ea6 +5 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-94276cf69a50e78dd6cdf079c208cb80f357cd33 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-9ddb891a0ec42401eb4629e6b99e01aef7909eb9 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-a8b44e1f5be4f75f00a937016ec5405bce77a0f9 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 +0 -0
- package/ldid/libplist/fuzz/xplist-crashes/crash-f03c680ee1c4d84c28e731752df77a61e213a24d +72 -0
- package/ldid/libplist/fuzz/xplist-leaks/clusterfuzz-testcase-4634751103139840 +187 -0
- package/ldid/libplist/fuzz/xplist-leaks/clusterfuzz-testcase-6056412121661440 +12 -0
- package/ldid/libplist/fuzz/xplist-leaks/leak-47b0a9f21d3affab6cfc898e5140bb53265ada07 +0 -0
- package/ldid/libplist/fuzz/xplist-leaks/leak-4c81aae70b20d9b9408b78d40999a54205bdcfb7 +0 -0
- package/ldid/libplist/fuzz/xplist-leaks/leak-53bc466851eda790bd891733da5db0a7482886bf +6 -0
- package/ldid/libplist/fuzz/xplist.dict +51 -0
- package/ldid/libplist/fuzz/xplist_fuzzer.cc +32 -0
- package/ldid/libplist/fuzz/xplist_fuzzer.options +3 -0
- package/ldid/libplist/include/Makefile.am +15 -0
- package/ldid/libplist/include/plist/Array.h +55 -0
- package/ldid/libplist/include/plist/Boolean.h +48 -0
- package/ldid/libplist/include/plist/Data.h +49 -0
- package/ldid/libplist/include/plist/Date.h +50 -0
- package/ldid/libplist/include/plist/Dictionary.h +68 -0
- package/ldid/libplist/include/plist/Integer.h +48 -0
- package/ldid/libplist/include/plist/Key.h +49 -0
- package/ldid/libplist/include/plist/Node.h +57 -0
- package/ldid/libplist/include/plist/Real.h +48 -0
- package/ldid/libplist/include/plist/String.h +49 -0
- package/ldid/libplist/include/plist/Structure.h +59 -0
- package/ldid/libplist/include/plist/Uid.h +48 -0
- package/ldid/libplist/include/plist/plist++.h +39 -0
- package/ldid/libplist/include/plist/plist.h +953 -0
- package/ldid/libplist/libcnary/COPYING +502 -0
- package/ldid/libplist/libcnary/Makefile.am +15 -0
- package/ldid/libplist/libcnary/README +5 -0
- package/ldid/libplist/libcnary/cnary.c +46 -0
- package/ldid/libplist/libcnary/include/node.h +65 -0
- package/ldid/libplist/libcnary/include/node_list.h +47 -0
- package/ldid/libplist/libcnary/include/object.h +41 -0
- package/ldid/libplist/libcnary/node.c +216 -0
- package/ldid/libplist/libcnary/node_list.c +157 -0
- package/ldid/libplist/m4/ac_pkg_cython.m4 +67 -0
- package/ldid/libplist/m4/as-compiler-flag.m4 +62 -0
- package/ldid/libplist/m4/ax_pthread.m4 +485 -0
- package/ldid/libplist/m4/ax_python_devel.m4 +327 -0
- package/ldid/libplist/m4/cython_python.m4 +7 -0
- package/ldid/libplist/src/Array.cpp +148 -0
- package/ldid/libplist/src/Boolean.cpp +73 -0
- package/ldid/libplist/src/Data.cpp +79 -0
- package/ldid/libplist/src/Date.cpp +76 -0
- package/ldid/libplist/src/Dictionary.cpp +182 -0
- package/ldid/libplist/src/Integer.cpp +73 -0
- package/ldid/libplist/src/Key.cpp +80 -0
- package/ldid/libplist/src/Makefile.am +63 -0
- package/ldid/libplist/src/Node.cpp +166 -0
- package/ldid/libplist/src/Real.cpp +73 -0
- package/ldid/libplist/src/String.cpp +80 -0
- package/ldid/libplist/src/Structure.cpp +123 -0
- package/ldid/libplist/src/Uid.cpp +73 -0
- package/ldid/libplist/src/base64.c +119 -0
- package/ldid/libplist/src/base64.h +28 -0
- package/ldid/libplist/src/bplist.c +1381 -0
- package/ldid/libplist/src/bytearray.c +61 -0
- package/ldid/libplist/src/bytearray.h +36 -0
- package/ldid/libplist/src/hashtable.c +140 -0
- package/ldid/libplist/src/hashtable.h +50 -0
- package/ldid/libplist/src/plist.c +1356 -0
- package/ldid/libplist/src/plist.h +74 -0
- package/ldid/libplist/src/ptrarray.c +96 -0
- package/ldid/libplist/src/ptrarray.h +40 -0
- package/ldid/libplist/src/strbuf.h +34 -0
- package/ldid/libplist/src/time64.c +814 -0
- package/ldid/libplist/src/time64.h +81 -0
- package/ldid/libplist/src/time64_limits.h +97 -0
- package/ldid/libplist/src/xplist.c +1435 -0
- package/ldid/libplist/test/Makefile.am +93 -0
- package/ldid/libplist/test/amp.test +14 -0
- package/ldid/libplist/test/bigarray.test +15 -0
- package/ldid/libplist/test/cdata.test +12 -0
- package/ldid/libplist/test/data/1.plist +35 -0
- package/ldid/libplist/test/data/2.plist +100 -0
- package/ldid/libplist/test/data/3.plist +420 -0
- package/ldid/libplist/test/data/4.plist +5037 -0
- package/ldid/libplist/test/data/5.plist +55053 -0
- package/ldid/libplist/test/data/6.plist +4006 -0
- package/ldid/libplist/test/data/7.plist +14 -0
- package/ldid/libplist/test/data/amp.plist +6 -0
- package/ldid/libplist/test/data/cdata.plist +6 -0
- package/ldid/libplist/test/data/dictref1byte.bplist +0 -0
- package/ldid/libplist/test/data/dictref2bytes.bplist +0 -0
- package/ldid/libplist/test/data/dictref3bytes.bplist +0 -0
- package/ldid/libplist/test/data/dictref4bytes.bplist +0 -0
- package/ldid/libplist/test/data/dictref5bytes.bplist +0 -0
- package/ldid/libplist/test/data/dictref6bytes.bplist +0 -0
- package/ldid/libplist/test/data/dictref7bytes.bplist +0 -0
- package/ldid/libplist/test/data/dictref8bytes.bplist +0 -0
- package/ldid/libplist/test/data/empty_keys.plist +8 -0
- package/ldid/libplist/test/data/entities.plist +57 -0
- package/ldid/libplist/test/data/hex.plist +5 -0
- package/ldid/libplist/test/data/invalid_tag.plist +6 -0
- package/ldid/libplist/test/data/malformed_dict.bplist +0 -0
- package/ldid/libplist/test/data/off1byte.bplist +0 -0
- package/ldid/libplist/test/data/off2bytes.bplist +0 -0
- package/ldid/libplist/test/data/off3bytes.bplist +0 -0
- package/ldid/libplist/test/data/off4bytes.bplist +0 -0
- package/ldid/libplist/test/data/off5bytes.bplist +0 -0
- package/ldid/libplist/test/data/off6bytes.bplist +0 -0
- package/ldid/libplist/test/data/off7bytes.bplist +0 -0
- package/ldid/libplist/test/data/off8bytes.bplist +0 -0
- package/ldid/libplist/test/data/offxml.plist +8 -0
- package/ldid/libplist/test/data/order.bplist +0 -0
- package/ldid/libplist/test/data/order.plist +27 -0
- package/ldid/libplist/test/data/recursion.bplist +0 -0
- package/ldid/libplist/test/data/signed.bplist +0 -0
- package/ldid/libplist/test/data/signed.plist +5 -0
- package/ldid/libplist/test/data/signedunsigned.bplist +0 -0
- package/ldid/libplist/test/data/signedunsigned.plist +11 -0
- package/ldid/libplist/test/data/unsigned.bplist +0 -0
- package/ldid/libplist/test/data/unsigned.plist +5 -0
- package/ldid/libplist/test/dates.test +15 -0
- package/ldid/libplist/test/empty.test +15 -0
- package/ldid/libplist/test/empty_keys.test +12 -0
- package/ldid/libplist/test/entities.test +12 -0
- package/ldid/libplist/test/hex.test +12 -0
- package/ldid/libplist/test/huge.test +15 -0
- package/ldid/libplist/test/invalid_tag.test +14 -0
- package/ldid/libplist/test/large.test +15 -0
- package/ldid/libplist/test/malformed_dict.test +11 -0
- package/ldid/libplist/test/medium.test +15 -0
- package/ldid/libplist/test/offsetsize.test +12 -0
- package/ldid/libplist/test/order.test +13 -0
- package/ldid/libplist/test/plist_cmp.c +158 -0
- package/ldid/libplist/test/plist_test.c +135 -0
- package/ldid/libplist/test/recursion.test +11 -0
- package/ldid/libplist/test/refsize.test +12 -0
- package/ldid/libplist/test/signedunsigned1.test +23 -0
- package/ldid/libplist/test/signedunsigned2.test +23 -0
- package/ldid/libplist/test/signedunsigned3.test +23 -0
- package/ldid/libplist/test/small.test +15 -0
- package/ldid/libplist/test/timezone1.test +17 -0
- package/ldid/libplist/test/timezone2.test +21 -0
- package/ldid/libplist/tools/Makefile.am +10 -0
- package/ldid/libplist/tools/plistutil.c +299 -0
- package/ldid/lookup2.c +416 -0
- package/ldid/make.sh +90 -0
- package/ldid/minimal/hexdump.h +76 -0
- package/ldid/minimal/mapping.h +72 -0
- package/ldid/minimal/sqlite3.h +71 -0
- package/ldid/minimal/stdlib.h +129 -0
- package/ldid/minimal/string.h +51 -0
- package/ldid/plist.sh +2 -0
- package/ldid/sha1.h +64 -0
- package/ldid/sysroot.sh +31 -0
- package/ldid/version.sh +2 -0
- package/lib/client.js +243 -0
- package/lib/commands/account.js +785 -0
- package/lib/commands/avatars.js +349 -0
- package/lib/commands/database.js +1238 -0
- package/lib/commands/deploy.js +477 -0
- package/lib/commands/functions.js +689 -0
- package/lib/commands/generic.js +106 -0
- package/lib/commands/health.js +269 -0
- package/lib/commands/init.js +148 -0
- package/lib/commands/locale.js +177 -0
- package/lib/commands/projects.js +1191 -0
- package/lib/commands/storage.js +743 -0
- package/lib/commands/teams.js +435 -0
- package/lib/commands/users.js +542 -0
- package/lib/config.js +264 -0
- package/lib/exception.js +9 -0
- package/lib/parser.js +179 -0
- package/lib/questions.js +223 -0
- package/lib/sdks.js +82 -0
- 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
|
+
}
|