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,1435 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xplist.c
|
|
3
|
+
* XML plist implementation
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2010-2017 Nikias Bassen All Rights Reserved.
|
|
6
|
+
* Copyright (c) 2010-2015 Martin Szulecki All Rights Reserved.
|
|
7
|
+
* Copyright (c) 2008 Jonathan Beck All Rights Reserved.
|
|
8
|
+
*
|
|
9
|
+
* This library is free software; you can redistribute it and/or
|
|
10
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
11
|
+
* License as published by the Free Software Foundation; either
|
|
12
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
13
|
+
*
|
|
14
|
+
* This library is distributed in the hope that it will be useful,
|
|
15
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
17
|
+
* Lesser General Public License for more details.
|
|
18
|
+
*
|
|
19
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
20
|
+
* License along with this library; if not, write to the Free Software
|
|
21
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
#ifdef HAVE_CONFIG_H
|
|
25
|
+
#include <config.h>
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#ifdef HAVE_STRPTIME
|
|
29
|
+
#define _XOPEN_SOURCE 600
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
#include <string.h>
|
|
33
|
+
#include <assert.h>
|
|
34
|
+
#include <stdlib.h>
|
|
35
|
+
#include <stdio.h>
|
|
36
|
+
#include <time.h>
|
|
37
|
+
|
|
38
|
+
#include <inttypes.h>
|
|
39
|
+
#include <float.h>
|
|
40
|
+
#include <math.h>
|
|
41
|
+
#include <limits.h>
|
|
42
|
+
|
|
43
|
+
#include <node.h>
|
|
44
|
+
#include <node_list.h>
|
|
45
|
+
|
|
46
|
+
#include "plist.h"
|
|
47
|
+
#include "base64.h"
|
|
48
|
+
#include "strbuf.h"
|
|
49
|
+
#include "time64.h"
|
|
50
|
+
|
|
51
|
+
#define XPLIST_KEY "key"
|
|
52
|
+
#define XPLIST_KEY_LEN 3
|
|
53
|
+
#define XPLIST_FALSE "false"
|
|
54
|
+
#define XPLIST_FALSE_LEN 5
|
|
55
|
+
#define XPLIST_TRUE "true"
|
|
56
|
+
#define XPLIST_TRUE_LEN 4
|
|
57
|
+
#define XPLIST_INT "integer"
|
|
58
|
+
#define XPLIST_INT_LEN 7
|
|
59
|
+
#define XPLIST_REAL "real"
|
|
60
|
+
#define XPLIST_REAL_LEN 4
|
|
61
|
+
#define XPLIST_DATE "date"
|
|
62
|
+
#define XPLIST_DATE_LEN 4
|
|
63
|
+
#define XPLIST_DATA "data"
|
|
64
|
+
#define XPLIST_DATA_LEN 4
|
|
65
|
+
#define XPLIST_STRING "string"
|
|
66
|
+
#define XPLIST_STRING_LEN 6
|
|
67
|
+
#define XPLIST_ARRAY "array"
|
|
68
|
+
#define XPLIST_ARRAY_LEN 5
|
|
69
|
+
#define XPLIST_DICT "dict"
|
|
70
|
+
#define XPLIST_DICT_LEN 4
|
|
71
|
+
|
|
72
|
+
#define MAC_EPOCH 978307200
|
|
73
|
+
|
|
74
|
+
#define MAX_DATA_BYTES_PER_LINE(__i) (((76 - (__i << 3)) >> 2) * 3)
|
|
75
|
+
|
|
76
|
+
static const char XML_PLIST_PROLOG[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
|
|
77
|
+
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n\
|
|
78
|
+
<plist version=\"1.0\">\n";
|
|
79
|
+
static const char XML_PLIST_EPILOG[] = "</plist>\n";
|
|
80
|
+
|
|
81
|
+
#ifdef DEBUG
|
|
82
|
+
static int plist_xml_debug = 0;
|
|
83
|
+
#define PLIST_XML_ERR(...) if (plist_xml_debug) { fprintf(stderr, "libplist[xmlparser] ERROR: " __VA_ARGS__); }
|
|
84
|
+
#else
|
|
85
|
+
#define PLIST_XML_ERR(...)
|
|
86
|
+
#endif
|
|
87
|
+
|
|
88
|
+
void plist_xml_init(void)
|
|
89
|
+
{
|
|
90
|
+
/* init XML stuff */
|
|
91
|
+
#ifdef DEBUG
|
|
92
|
+
char *env_debug = getenv("PLIST_XML_DEBUG");
|
|
93
|
+
if (env_debug && !strcmp(env_debug, "1")) {
|
|
94
|
+
plist_xml_debug = 1;
|
|
95
|
+
}
|
|
96
|
+
#endif
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
void plist_xml_deinit(void)
|
|
100
|
+
{
|
|
101
|
+
/* deinit XML stuff */
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static size_t dtostr(char *buf, size_t bufsize, double realval)
|
|
105
|
+
{
|
|
106
|
+
size_t len = 0;
|
|
107
|
+
if (isnan(realval)) {
|
|
108
|
+
len = snprintf(buf, bufsize, "nan");
|
|
109
|
+
} else if (isinf(realval)) {
|
|
110
|
+
len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
|
|
111
|
+
} else if (realval == 0.0f) {
|
|
112
|
+
len = snprintf(buf, bufsize, "0.0");
|
|
113
|
+
} else {
|
|
114
|
+
size_t i = 0;
|
|
115
|
+
len = snprintf(buf, bufsize, "%.*g", 17, realval);
|
|
116
|
+
for (i = 0; i < len; i++) {
|
|
117
|
+
if (buf[i] == ',') {
|
|
118
|
+
buf[i] = '.';
|
|
119
|
+
break;
|
|
120
|
+
} else if (buf[i] == '.') {
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return len;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static void node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)
|
|
129
|
+
{
|
|
130
|
+
plist_data_t node_data = NULL;
|
|
131
|
+
|
|
132
|
+
char isStruct = FALSE;
|
|
133
|
+
char tagOpen = FALSE;
|
|
134
|
+
|
|
135
|
+
const char *tag = NULL;
|
|
136
|
+
size_t tag_len = 0;
|
|
137
|
+
char *val = NULL;
|
|
138
|
+
size_t val_len = 0;
|
|
139
|
+
|
|
140
|
+
uint32_t i = 0;
|
|
141
|
+
|
|
142
|
+
if (!node)
|
|
143
|
+
return;
|
|
144
|
+
|
|
145
|
+
node_data = plist_get_data(node);
|
|
146
|
+
|
|
147
|
+
switch (node_data->type)
|
|
148
|
+
{
|
|
149
|
+
case PLIST_BOOLEAN:
|
|
150
|
+
{
|
|
151
|
+
if (node_data->boolval) {
|
|
152
|
+
tag = XPLIST_TRUE;
|
|
153
|
+
tag_len = XPLIST_TRUE_LEN;
|
|
154
|
+
} else {
|
|
155
|
+
tag = XPLIST_FALSE;
|
|
156
|
+
tag_len = XPLIST_FALSE_LEN;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
|
|
161
|
+
case PLIST_UINT:
|
|
162
|
+
tag = XPLIST_INT;
|
|
163
|
+
tag_len = XPLIST_INT_LEN;
|
|
164
|
+
val = (char*)malloc(64);
|
|
165
|
+
if (node_data->length == 16) {
|
|
166
|
+
val_len = snprintf(val, 64, "%"PRIu64, node_data->intval);
|
|
167
|
+
} else {
|
|
168
|
+
val_len = snprintf(val, 64, "%"PRIi64, node_data->intval);
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
|
|
172
|
+
case PLIST_REAL:
|
|
173
|
+
tag = XPLIST_REAL;
|
|
174
|
+
tag_len = XPLIST_REAL_LEN;
|
|
175
|
+
val = (char*)malloc(64);
|
|
176
|
+
val_len = dtostr(val, 64, node_data->realval);
|
|
177
|
+
break;
|
|
178
|
+
|
|
179
|
+
case PLIST_STRING:
|
|
180
|
+
tag = XPLIST_STRING;
|
|
181
|
+
tag_len = XPLIST_STRING_LEN;
|
|
182
|
+
/* contents processed directly below */
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
case PLIST_KEY:
|
|
186
|
+
tag = XPLIST_KEY;
|
|
187
|
+
tag_len = XPLIST_KEY_LEN;
|
|
188
|
+
/* contents processed directly below */
|
|
189
|
+
break;
|
|
190
|
+
|
|
191
|
+
case PLIST_DATA:
|
|
192
|
+
tag = XPLIST_DATA;
|
|
193
|
+
tag_len = XPLIST_DATA_LEN;
|
|
194
|
+
/* contents processed directly below */
|
|
195
|
+
break;
|
|
196
|
+
case PLIST_ARRAY:
|
|
197
|
+
tag = XPLIST_ARRAY;
|
|
198
|
+
tag_len = XPLIST_ARRAY_LEN;
|
|
199
|
+
isStruct = (node->children) ? TRUE : FALSE;
|
|
200
|
+
break;
|
|
201
|
+
case PLIST_DICT:
|
|
202
|
+
tag = XPLIST_DICT;
|
|
203
|
+
tag_len = XPLIST_DICT_LEN;
|
|
204
|
+
isStruct = (node->children) ? TRUE : FALSE;
|
|
205
|
+
break;
|
|
206
|
+
case PLIST_DATE:
|
|
207
|
+
tag = XPLIST_DATE;
|
|
208
|
+
tag_len = XPLIST_DATE_LEN;
|
|
209
|
+
{
|
|
210
|
+
Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
|
|
211
|
+
struct TM _btime;
|
|
212
|
+
struct TM *btime = gmtime64_r(&timev, &_btime);
|
|
213
|
+
if (btime) {
|
|
214
|
+
val = (char*)malloc(24);
|
|
215
|
+
memset(val, 0, 24);
|
|
216
|
+
struct tm _tmcopy;
|
|
217
|
+
copy_TM64_to_tm(btime, &_tmcopy);
|
|
218
|
+
val_len = strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", &_tmcopy);
|
|
219
|
+
if (val_len <= 0) {
|
|
220
|
+
free (val);
|
|
221
|
+
val = NULL;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
case PLIST_UID:
|
|
227
|
+
tag = XPLIST_DICT;
|
|
228
|
+
tag_len = XPLIST_DICT_LEN;
|
|
229
|
+
val = (char*)malloc(64);
|
|
230
|
+
if (node_data->length == 16) {
|
|
231
|
+
val_len = snprintf(val, 64, "%"PRIu64, node_data->intval);
|
|
232
|
+
} else {
|
|
233
|
+
val_len = snprintf(val, 64, "%"PRIi64, node_data->intval);
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
default:
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
for (i = 0; i < depth; i++) {
|
|
241
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* append tag */
|
|
245
|
+
str_buf_append(*outbuf, "<", 1);
|
|
246
|
+
str_buf_append(*outbuf, tag, tag_len);
|
|
247
|
+
if (node_data->type == PLIST_STRING || node_data->type == PLIST_KEY) {
|
|
248
|
+
size_t j;
|
|
249
|
+
size_t len;
|
|
250
|
+
off_t start = 0;
|
|
251
|
+
off_t cur = 0;
|
|
252
|
+
|
|
253
|
+
str_buf_append(*outbuf, ">", 1);
|
|
254
|
+
tagOpen = TRUE;
|
|
255
|
+
|
|
256
|
+
/* make sure we convert the following predefined xml entities */
|
|
257
|
+
/* < = < > = > & = & */
|
|
258
|
+
len = node_data->length;
|
|
259
|
+
for (j = 0; j < len; j++) {
|
|
260
|
+
switch (node_data->strval[j]) {
|
|
261
|
+
case '<':
|
|
262
|
+
str_buf_append(*outbuf, node_data->strval + start, cur - start);
|
|
263
|
+
str_buf_append(*outbuf, "<", 4);
|
|
264
|
+
start = cur+1;
|
|
265
|
+
break;
|
|
266
|
+
case '>':
|
|
267
|
+
str_buf_append(*outbuf, node_data->strval + start, cur - start);
|
|
268
|
+
str_buf_append(*outbuf, ">", 4);
|
|
269
|
+
start = cur+1;
|
|
270
|
+
break;
|
|
271
|
+
case '&':
|
|
272
|
+
str_buf_append(*outbuf, node_data->strval + start, cur - start);
|
|
273
|
+
str_buf_append(*outbuf, "&", 5);
|
|
274
|
+
start = cur+1;
|
|
275
|
+
break;
|
|
276
|
+
default:
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
cur++;
|
|
280
|
+
}
|
|
281
|
+
str_buf_append(*outbuf, node_data->strval + start, cur - start);
|
|
282
|
+
} else if (node_data->type == PLIST_DATA) {
|
|
283
|
+
str_buf_append(*outbuf, ">", 1);
|
|
284
|
+
tagOpen = TRUE;
|
|
285
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
286
|
+
if (node_data->length > 0) {
|
|
287
|
+
uint32_t j = 0;
|
|
288
|
+
uint32_t indent = (depth > 8) ? 8 : depth;
|
|
289
|
+
uint32_t maxread = MAX_DATA_BYTES_PER_LINE(indent);
|
|
290
|
+
size_t count = 0;
|
|
291
|
+
size_t amount = (node_data->length / 3 * 4) + 4 + (((node_data->length / maxread) + 1) * (indent+1));
|
|
292
|
+
if ((*outbuf)->len + amount > (*outbuf)->capacity) {
|
|
293
|
+
str_buf_grow(*outbuf, amount);
|
|
294
|
+
}
|
|
295
|
+
while (j < node_data->length) {
|
|
296
|
+
for (i = 0; i < indent; i++) {
|
|
297
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
298
|
+
}
|
|
299
|
+
count = (node_data->length-j < maxread) ? node_data->length-j : maxread;
|
|
300
|
+
assert((*outbuf)->len + count < (*outbuf)->capacity);
|
|
301
|
+
(*outbuf)->len += base64encode((char*)(*outbuf)->data + (*outbuf)->len, node_data->buff + j, count);
|
|
302
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
303
|
+
j+=count;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
for (i = 0; i < depth; i++) {
|
|
307
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
308
|
+
}
|
|
309
|
+
} else if (node_data->type == PLIST_UID) {
|
|
310
|
+
/* special case for UID nodes: create a DICT */
|
|
311
|
+
str_buf_append(*outbuf, ">", 1);
|
|
312
|
+
tagOpen = TRUE;
|
|
313
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
314
|
+
|
|
315
|
+
/* add CF$UID key */
|
|
316
|
+
for (i = 0; i < depth+1; i++) {
|
|
317
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
318
|
+
}
|
|
319
|
+
str_buf_append(*outbuf, "<key>CF$UID</key>", 17);
|
|
320
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
321
|
+
|
|
322
|
+
/* add UID value */
|
|
323
|
+
for (i = 0; i < depth+1; i++) {
|
|
324
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
325
|
+
}
|
|
326
|
+
str_buf_append(*outbuf, "<integer>", 9);
|
|
327
|
+
str_buf_append(*outbuf, val, val_len);
|
|
328
|
+
str_buf_append(*outbuf, "</integer>", 10);
|
|
329
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
330
|
+
|
|
331
|
+
for (i = 0; i < depth; i++) {
|
|
332
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
333
|
+
}
|
|
334
|
+
} else if (val) {
|
|
335
|
+
str_buf_append(*outbuf, ">", 1);
|
|
336
|
+
tagOpen = TRUE;
|
|
337
|
+
str_buf_append(*outbuf, val, val_len);
|
|
338
|
+
} else if (isStruct) {
|
|
339
|
+
tagOpen = TRUE;
|
|
340
|
+
str_buf_append(*outbuf, ">", 1);
|
|
341
|
+
} else {
|
|
342
|
+
tagOpen = FALSE;
|
|
343
|
+
str_buf_append(*outbuf, "/>", 2);
|
|
344
|
+
}
|
|
345
|
+
free(val);
|
|
346
|
+
|
|
347
|
+
if (isStruct) {
|
|
348
|
+
/* add newline for structured types */
|
|
349
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
350
|
+
|
|
351
|
+
/* add child nodes */
|
|
352
|
+
if (node_data->type == PLIST_DICT && node->children) {
|
|
353
|
+
assert((node->children->count % 2) == 0);
|
|
354
|
+
}
|
|
355
|
+
node_t *ch;
|
|
356
|
+
for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
|
|
357
|
+
node_to_xml(ch, outbuf, depth+1);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/* fix indent for structured types */
|
|
361
|
+
for (i = 0; i < depth; i++) {
|
|
362
|
+
str_buf_append(*outbuf, "\t", 1);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (tagOpen) {
|
|
367
|
+
/* add closing tag */
|
|
368
|
+
str_buf_append(*outbuf, "</", 2);
|
|
369
|
+
str_buf_append(*outbuf, tag, tag_len);
|
|
370
|
+
str_buf_append(*outbuf, ">", 1);
|
|
371
|
+
}
|
|
372
|
+
str_buf_append(*outbuf, "\n", 1);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
static void parse_date(const char *strval, struct TM *btime)
|
|
376
|
+
{
|
|
377
|
+
if (!btime) return;
|
|
378
|
+
memset(btime, 0, sizeof(struct tm));
|
|
379
|
+
if (!strval) return;
|
|
380
|
+
#ifdef HAVE_STRPTIME
|
|
381
|
+
strptime((char*)strval, "%Y-%m-%dT%H:%M:%SZ", btime);
|
|
382
|
+
#else
|
|
383
|
+
#ifdef USE_TM64
|
|
384
|
+
#define PLIST_SSCANF_FORMAT "%lld-%d-%dT%d:%d:%dZ"
|
|
385
|
+
#else
|
|
386
|
+
#define PLIST_SSCANF_FORMAT "%d-%d-%dT%d:%d:%dZ"
|
|
387
|
+
#endif
|
|
388
|
+
sscanf(strval, PLIST_SSCANF_FORMAT, &btime->tm_year, &btime->tm_mon, &btime->tm_mday, &btime->tm_hour, &btime->tm_min, &btime->tm_sec);
|
|
389
|
+
btime->tm_year-=1900;
|
|
390
|
+
btime->tm_mon--;
|
|
391
|
+
#endif
|
|
392
|
+
btime->tm_isdst=0;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
#define PO10i_LIMIT (INT64_MAX/10)
|
|
396
|
+
|
|
397
|
+
/* based on https://stackoverflow.com/a/4143288 */
|
|
398
|
+
static int num_digits_i(int64_t i)
|
|
399
|
+
{
|
|
400
|
+
int n;
|
|
401
|
+
int64_t po10;
|
|
402
|
+
n=1;
|
|
403
|
+
if (i < 0) {
|
|
404
|
+
i = -i;
|
|
405
|
+
n++;
|
|
406
|
+
}
|
|
407
|
+
po10=10;
|
|
408
|
+
while (i>=po10) {
|
|
409
|
+
n++;
|
|
410
|
+
if (po10 > PO10i_LIMIT) break;
|
|
411
|
+
po10*=10;
|
|
412
|
+
}
|
|
413
|
+
return n;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
#define PO10u_LIMIT (UINT64_MAX/10)
|
|
417
|
+
|
|
418
|
+
/* based on https://stackoverflow.com/a/4143288 */
|
|
419
|
+
static int num_digits_u(uint64_t i)
|
|
420
|
+
{
|
|
421
|
+
int n;
|
|
422
|
+
uint64_t po10;
|
|
423
|
+
n=1;
|
|
424
|
+
po10=10;
|
|
425
|
+
while (i>=po10) {
|
|
426
|
+
n++;
|
|
427
|
+
if (po10 > PO10u_LIMIT) break;
|
|
428
|
+
po10*=10;
|
|
429
|
+
}
|
|
430
|
+
return n;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
static void node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)
|
|
434
|
+
{
|
|
435
|
+
plist_data_t data;
|
|
436
|
+
if (!node) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
data = plist_get_data(node);
|
|
440
|
+
if (node->children) {
|
|
441
|
+
node_t *ch;
|
|
442
|
+
for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
|
|
443
|
+
node_estimate_size(ch, size, depth + 1);
|
|
444
|
+
}
|
|
445
|
+
switch (data->type) {
|
|
446
|
+
case PLIST_DICT:
|
|
447
|
+
*size += (XPLIST_DICT_LEN << 1) + 7;
|
|
448
|
+
break;
|
|
449
|
+
case PLIST_ARRAY:
|
|
450
|
+
*size += (XPLIST_ARRAY_LEN << 1) + 7;
|
|
451
|
+
break;
|
|
452
|
+
default:
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
*size += (depth << 1);
|
|
456
|
+
} else {
|
|
457
|
+
uint32_t indent = (depth > 8) ? 8 : depth;
|
|
458
|
+
switch (data->type) {
|
|
459
|
+
case PLIST_DATA: {
|
|
460
|
+
uint32_t req_lines = (data->length / MAX_DATA_BYTES_PER_LINE(indent)) + 1;
|
|
461
|
+
uint32_t b64len = data->length + (data->length / 3);
|
|
462
|
+
b64len += b64len % 4;
|
|
463
|
+
*size += b64len;
|
|
464
|
+
*size += (XPLIST_DATA_LEN << 1) + 5 + (indent+1) * (req_lines+1) + 1;
|
|
465
|
+
} break;
|
|
466
|
+
case PLIST_STRING:
|
|
467
|
+
*size += data->length;
|
|
468
|
+
*size += (XPLIST_STRING_LEN << 1) + 6;
|
|
469
|
+
break;
|
|
470
|
+
case PLIST_KEY:
|
|
471
|
+
*size += data->length;
|
|
472
|
+
*size += (XPLIST_KEY_LEN << 1) + 6;
|
|
473
|
+
break;
|
|
474
|
+
case PLIST_UINT:
|
|
475
|
+
if (data->length == 16) {
|
|
476
|
+
*size += num_digits_u(data->intval);
|
|
477
|
+
} else {
|
|
478
|
+
*size += num_digits_i((int64_t)data->intval);
|
|
479
|
+
}
|
|
480
|
+
*size += (XPLIST_INT_LEN << 1) + 6;
|
|
481
|
+
break;
|
|
482
|
+
case PLIST_REAL:
|
|
483
|
+
*size += num_digits_i((int64_t)data->realval) + 7;
|
|
484
|
+
*size += (XPLIST_REAL_LEN << 1) + 6;
|
|
485
|
+
break;
|
|
486
|
+
case PLIST_DATE:
|
|
487
|
+
*size += 20; /* YYYY-MM-DDThh:mm:ssZ */
|
|
488
|
+
*size += (XPLIST_DATE_LEN << 1) + 6;
|
|
489
|
+
break;
|
|
490
|
+
case PLIST_BOOLEAN:
|
|
491
|
+
*size += ((data->boolval) ? XPLIST_TRUE_LEN : XPLIST_FALSE_LEN) + 4;
|
|
492
|
+
break;
|
|
493
|
+
case PLIST_DICT:
|
|
494
|
+
*size += XPLIST_DICT_LEN + 4; /* <dict/> */
|
|
495
|
+
break;
|
|
496
|
+
case PLIST_ARRAY:
|
|
497
|
+
*size += XPLIST_ARRAY_LEN + 4; /* <array/> */
|
|
498
|
+
break;
|
|
499
|
+
case PLIST_UID:
|
|
500
|
+
*size += num_digits_i((int64_t)data->intval);
|
|
501
|
+
*size += (XPLIST_DICT_LEN << 1) + 7;
|
|
502
|
+
*size += indent + ((indent+1) << 1);
|
|
503
|
+
*size += 18; /* <key>CF$UID</key> */
|
|
504
|
+
*size += (XPLIST_INT_LEN << 1) + 6;
|
|
505
|
+
break;
|
|
506
|
+
default:
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
*size += indent;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
PLIST_API void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
|
|
514
|
+
{
|
|
515
|
+
uint64_t size = 0;
|
|
516
|
+
node_estimate_size(plist, &size, 0);
|
|
517
|
+
size += sizeof(XML_PLIST_PROLOG) + sizeof(XML_PLIST_EPILOG) - 1;
|
|
518
|
+
|
|
519
|
+
strbuf_t *outbuf = str_buf_new(size);
|
|
520
|
+
|
|
521
|
+
str_buf_append(outbuf, XML_PLIST_PROLOG, sizeof(XML_PLIST_PROLOG)-1);
|
|
522
|
+
|
|
523
|
+
node_to_xml(plist, &outbuf, 0);
|
|
524
|
+
|
|
525
|
+
str_buf_append(outbuf, XML_PLIST_EPILOG, sizeof(XML_PLIST_EPILOG));
|
|
526
|
+
|
|
527
|
+
*plist_xml = outbuf->data;
|
|
528
|
+
*length = outbuf->len - 1;
|
|
529
|
+
|
|
530
|
+
outbuf->data = NULL;
|
|
531
|
+
str_buf_free(outbuf);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
PLIST_API void plist_to_xml_free(char *plist_xml)
|
|
535
|
+
{
|
|
536
|
+
free(plist_xml);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
struct _parse_ctx {
|
|
540
|
+
const char *pos;
|
|
541
|
+
const char *end;
|
|
542
|
+
int err;
|
|
543
|
+
};
|
|
544
|
+
typedef struct _parse_ctx* parse_ctx;
|
|
545
|
+
|
|
546
|
+
static void parse_skip_ws(parse_ctx ctx)
|
|
547
|
+
{
|
|
548
|
+
while (ctx->pos < ctx->end && ((*(ctx->pos) == ' ') || (*(ctx->pos) == '\t') || (*(ctx->pos) == '\r') || (*(ctx->pos) == '\n'))) {
|
|
549
|
+
ctx->pos++;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
static void find_char(parse_ctx ctx, char c, int skip_quotes)
|
|
554
|
+
{
|
|
555
|
+
while (ctx->pos < ctx->end && (*(ctx->pos) != c)) {
|
|
556
|
+
if (skip_quotes && (c != '"') && (*(ctx->pos) == '"')) {
|
|
557
|
+
ctx->pos++;
|
|
558
|
+
find_char(ctx, '"', 0);
|
|
559
|
+
if (ctx->pos >= ctx->end) {
|
|
560
|
+
PLIST_XML_ERR("EOF while looking for matching double quote\n");
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (*(ctx->pos) != '"') {
|
|
564
|
+
PLIST_XML_ERR("Unmatched double quote\n");
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
ctx->pos++;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
static void find_str(parse_ctx ctx, const char *str, size_t len, int skip_quotes)
|
|
573
|
+
{
|
|
574
|
+
while (ctx->pos < (ctx->end - len)) {
|
|
575
|
+
if (!strncmp(ctx->pos, str, len)) {
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
if (skip_quotes && (*(ctx->pos) == '"')) {
|
|
579
|
+
ctx->pos++;
|
|
580
|
+
find_char(ctx, '"', 0);
|
|
581
|
+
if (ctx->pos >= ctx->end) {
|
|
582
|
+
PLIST_XML_ERR("EOF while looking for matching double quote\n");
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
if (*(ctx->pos) != '"') {
|
|
586
|
+
PLIST_XML_ERR("Unmatched double quote\n");
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
ctx->pos++;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
static void find_next(parse_ctx ctx, const char *nextchars, int numchars, int skip_quotes)
|
|
595
|
+
{
|
|
596
|
+
int i = 0;
|
|
597
|
+
while (ctx->pos < ctx->end) {
|
|
598
|
+
if (skip_quotes && (*(ctx->pos) == '"')) {
|
|
599
|
+
ctx->pos++;
|
|
600
|
+
find_char(ctx, '"', 0);
|
|
601
|
+
if (ctx->pos >= ctx->end) {
|
|
602
|
+
PLIST_XML_ERR("EOF while looking for matching double quote\n");
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
if (*(ctx->pos) != '"') {
|
|
606
|
+
PLIST_XML_ERR("Unmatched double quote\n");
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
for (i = 0; i < numchars; i++) {
|
|
611
|
+
if (*(ctx->pos) == nextchars[i]) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
ctx->pos++;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
typedef struct {
|
|
620
|
+
const char *begin;
|
|
621
|
+
size_t length;
|
|
622
|
+
int is_cdata;
|
|
623
|
+
void *next;
|
|
624
|
+
} text_part_t;
|
|
625
|
+
|
|
626
|
+
static text_part_t* text_part_init(text_part_t* part, const char *begin, size_t length, int is_cdata)
|
|
627
|
+
{
|
|
628
|
+
part->begin = begin;
|
|
629
|
+
part->length = length;
|
|
630
|
+
part->is_cdata = is_cdata;
|
|
631
|
+
part->next = NULL;
|
|
632
|
+
return part;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
static void text_parts_free(text_part_t *tp)
|
|
636
|
+
{
|
|
637
|
+
while (tp) {
|
|
638
|
+
text_part_t *tmp = tp;
|
|
639
|
+
tp = tp->next;
|
|
640
|
+
free(tmp);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
static text_part_t* text_part_append(text_part_t* parts, const char *begin, size_t length, int is_cdata)
|
|
645
|
+
{
|
|
646
|
+
text_part_t* newpart = malloc(sizeof(text_part_t));
|
|
647
|
+
assert(newpart);
|
|
648
|
+
parts->next = text_part_init(newpart, begin, length, is_cdata);
|
|
649
|
+
return newpart;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
static text_part_t* get_text_parts(parse_ctx ctx, const char* tag, size_t tag_len, int skip_ws, text_part_t *parts)
|
|
653
|
+
{
|
|
654
|
+
const char *p = NULL;
|
|
655
|
+
const char *q = NULL;
|
|
656
|
+
text_part_t *last = NULL;
|
|
657
|
+
|
|
658
|
+
if (skip_ws) {
|
|
659
|
+
parse_skip_ws(ctx);
|
|
660
|
+
}
|
|
661
|
+
do {
|
|
662
|
+
p = ctx->pos;
|
|
663
|
+
find_char(ctx, '<', 0);
|
|
664
|
+
if (ctx->pos >= ctx->end || *ctx->pos != '<') {
|
|
665
|
+
PLIST_XML_ERR("EOF while looking for closing tag\n");
|
|
666
|
+
ctx->err++;
|
|
667
|
+
return NULL;
|
|
668
|
+
}
|
|
669
|
+
q = ctx->pos;
|
|
670
|
+
ctx->pos++;
|
|
671
|
+
if (ctx->pos >= ctx->end) {
|
|
672
|
+
PLIST_XML_ERR("EOF while parsing '%s'\n", p);
|
|
673
|
+
ctx->err++;
|
|
674
|
+
return NULL;
|
|
675
|
+
}
|
|
676
|
+
if (*ctx->pos == '!') {
|
|
677
|
+
ctx->pos++;
|
|
678
|
+
if (ctx->pos >= ctx->end-1) {
|
|
679
|
+
PLIST_XML_ERR("EOF while parsing <! special tag\n");
|
|
680
|
+
ctx->err++;
|
|
681
|
+
return NULL;
|
|
682
|
+
}
|
|
683
|
+
if (*ctx->pos == '-' && *(ctx->pos+1) == '-') {
|
|
684
|
+
if (last) {
|
|
685
|
+
last = text_part_append(last, p, q-p, 0);
|
|
686
|
+
} else if (parts) {
|
|
687
|
+
last = text_part_init(parts, p, q-p, 0);
|
|
688
|
+
}
|
|
689
|
+
ctx->pos += 2;
|
|
690
|
+
find_str(ctx, "-->", 3, 0);
|
|
691
|
+
if (ctx->pos > ctx->end-3 || strncmp(ctx->pos, "-->", 3) != 0) {
|
|
692
|
+
PLIST_XML_ERR("EOF while looking for end of comment\n");
|
|
693
|
+
ctx->err++;
|
|
694
|
+
return NULL;
|
|
695
|
+
}
|
|
696
|
+
ctx->pos += 3;
|
|
697
|
+
} else if (*ctx->pos == '[') {
|
|
698
|
+
ctx->pos++;
|
|
699
|
+
if (ctx->pos >= ctx->end - 8) {
|
|
700
|
+
PLIST_XML_ERR("EOF while parsing <[ tag\n");
|
|
701
|
+
ctx->err++;
|
|
702
|
+
return NULL;
|
|
703
|
+
}
|
|
704
|
+
if (strncmp(ctx->pos, "CDATA[", 6) == 0) {
|
|
705
|
+
if (q-p > 0) {
|
|
706
|
+
if (last) {
|
|
707
|
+
last = text_part_append(last, p, q-p, 0);
|
|
708
|
+
} else if (parts) {
|
|
709
|
+
last = text_part_init(parts, p, q-p, 0);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
ctx->pos+=6;
|
|
713
|
+
p = ctx->pos;
|
|
714
|
+
find_str(ctx, "]]>", 3, 0);
|
|
715
|
+
if (ctx->pos > ctx->end-3 || strncmp(ctx->pos, "]]>", 3) != 0) {
|
|
716
|
+
PLIST_XML_ERR("EOF while looking for end of CDATA block\n");
|
|
717
|
+
ctx->err++;
|
|
718
|
+
return NULL;
|
|
719
|
+
}
|
|
720
|
+
q = ctx->pos;
|
|
721
|
+
if (last) {
|
|
722
|
+
last = text_part_append(last, p, q-p, 1);
|
|
723
|
+
} else if (parts) {
|
|
724
|
+
last = text_part_init(parts, p, q-p, 1);
|
|
725
|
+
}
|
|
726
|
+
ctx->pos += 3;
|
|
727
|
+
} else {
|
|
728
|
+
p = ctx->pos;
|
|
729
|
+
find_next(ctx, " \r\n\t>", 5, 1);
|
|
730
|
+
PLIST_XML_ERR("Invalid special tag <[%.*s> encountered inside <%s> tag\n", (int)(ctx->pos - p), p, tag);
|
|
731
|
+
ctx->err++;
|
|
732
|
+
return NULL;
|
|
733
|
+
}
|
|
734
|
+
} else {
|
|
735
|
+
p = ctx->pos;
|
|
736
|
+
find_next(ctx, " \r\n\t>", 5, 1);
|
|
737
|
+
PLIST_XML_ERR("Invalid special tag <!%.*s> encountered inside <%s> tag\n", (int)(ctx->pos - p), p, tag);
|
|
738
|
+
ctx->err++;
|
|
739
|
+
return NULL;
|
|
740
|
+
}
|
|
741
|
+
} else if (*ctx->pos == '/') {
|
|
742
|
+
break;
|
|
743
|
+
} else {
|
|
744
|
+
p = ctx->pos;
|
|
745
|
+
find_next(ctx, " \r\n\t>", 5, 1);
|
|
746
|
+
PLIST_XML_ERR("Invalid tag <%.*s> encountered inside <%s> tag\n", (int)(ctx->pos - p), p, tag);
|
|
747
|
+
ctx->err++;
|
|
748
|
+
return NULL;
|
|
749
|
+
}
|
|
750
|
+
} while (1);
|
|
751
|
+
ctx->pos++;
|
|
752
|
+
if (ctx->pos >= ctx->end-tag_len || strncmp(ctx->pos, tag, tag_len)) {
|
|
753
|
+
PLIST_XML_ERR("EOF or end tag mismatch\n");
|
|
754
|
+
ctx->err++;
|
|
755
|
+
return NULL;
|
|
756
|
+
}
|
|
757
|
+
ctx->pos+=tag_len;
|
|
758
|
+
parse_skip_ws(ctx);
|
|
759
|
+
if (ctx->pos >= ctx->end) {
|
|
760
|
+
PLIST_XML_ERR("EOF while parsing closing tag\n");
|
|
761
|
+
ctx->err++;
|
|
762
|
+
return NULL;
|
|
763
|
+
} else if (*ctx->pos != '>') {
|
|
764
|
+
PLIST_XML_ERR("Invalid closing tag; expected '>', found '%c'\n", *ctx->pos);
|
|
765
|
+
ctx->err++;
|
|
766
|
+
return NULL;
|
|
767
|
+
}
|
|
768
|
+
ctx->pos++;
|
|
769
|
+
|
|
770
|
+
if (q-p > 0) {
|
|
771
|
+
if (last) {
|
|
772
|
+
last = text_part_append(last, p, q-p, 0);
|
|
773
|
+
} else if (parts) {
|
|
774
|
+
last = text_part_init(parts, p, q-p, 0);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return parts;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
static int unescape_entities(char *str, size_t *length)
|
|
781
|
+
{
|
|
782
|
+
size_t i = 0;
|
|
783
|
+
size_t len = *length;
|
|
784
|
+
while (len > 0 && i < len-1) {
|
|
785
|
+
if (str[i] == '&') {
|
|
786
|
+
char *entp = str + i + 1;
|
|
787
|
+
while (i < len && str[i] != ';') {
|
|
788
|
+
i++;
|
|
789
|
+
}
|
|
790
|
+
if (i >= len) {
|
|
791
|
+
PLIST_XML_ERR("Invalid entity sequence encountered (missing terminating ';')\n");
|
|
792
|
+
return -1;
|
|
793
|
+
}
|
|
794
|
+
if (str+i >= entp+1) {
|
|
795
|
+
int entlen = str+i - entp;
|
|
796
|
+
int bytelen = 1;
|
|
797
|
+
if (!strncmp(entp, "amp", 3)) {
|
|
798
|
+
/* the '&' is already there */
|
|
799
|
+
} else if (!strncmp(entp, "apos", 4)) {
|
|
800
|
+
*(entp-1) = '\'';
|
|
801
|
+
} else if (!strncmp(entp, "quot", 4)) {
|
|
802
|
+
*(entp-1) = '"';
|
|
803
|
+
} else if (!strncmp(entp, "lt", 2)) {
|
|
804
|
+
*(entp-1) = '<';
|
|
805
|
+
} else if (!strncmp(entp, "gt", 2)) {
|
|
806
|
+
*(entp-1) = '>';
|
|
807
|
+
} else if (*entp == '#') {
|
|
808
|
+
/* numerical character reference */
|
|
809
|
+
uint64_t val = 0;
|
|
810
|
+
char* ep = NULL;
|
|
811
|
+
if (entlen > 8) {
|
|
812
|
+
PLIST_XML_ERR("Invalid numerical character reference encountered, sequence too long: &%.*s;\n", entlen, entp);
|
|
813
|
+
return -1;
|
|
814
|
+
}
|
|
815
|
+
if (*(entp+1) == 'x' || *(entp+1) == 'X') {
|
|
816
|
+
if (entlen < 3) {
|
|
817
|
+
PLIST_XML_ERR("Invalid numerical character reference encountered, sequence too short: &%.*s;\n", entlen, entp);
|
|
818
|
+
return -1;
|
|
819
|
+
}
|
|
820
|
+
val = strtoull(entp+2, &ep, 16);
|
|
821
|
+
} else {
|
|
822
|
+
if (entlen < 2) {
|
|
823
|
+
PLIST_XML_ERR("Invalid numerical character reference encountered, sequence too short: &%.*s;\n", entlen, entp);
|
|
824
|
+
return -1;
|
|
825
|
+
}
|
|
826
|
+
val = strtoull(entp+1, &ep, 10);
|
|
827
|
+
}
|
|
828
|
+
if (val == 0 || val > 0x10FFFF || ep-entp != entlen) {
|
|
829
|
+
PLIST_XML_ERR("Invalid numerical character reference found: &%.*s;\n", entlen, entp);
|
|
830
|
+
return -1;
|
|
831
|
+
}
|
|
832
|
+
/* convert to UTF8 */
|
|
833
|
+
if (val >= 0x10000) {
|
|
834
|
+
/* four bytes */
|
|
835
|
+
*(entp-1) = (char)(0xF0 + ((val >> 18) & 0x7));
|
|
836
|
+
*(entp+0) = (char)(0x80 + ((val >> 12) & 0x3F));
|
|
837
|
+
*(entp+1) = (char)(0x80 + ((val >> 6) & 0x3F));
|
|
838
|
+
*(entp+2) = (char)(0x80 + (val & 0x3F));
|
|
839
|
+
entp+=3;
|
|
840
|
+
bytelen = 4;
|
|
841
|
+
} else if (val >= 0x800) {
|
|
842
|
+
/* three bytes */
|
|
843
|
+
*(entp-1) = (char)(0xE0 + ((val >> 12) & 0xF));
|
|
844
|
+
*(entp+0) = (char)(0x80 + ((val >> 6) & 0x3F));
|
|
845
|
+
*(entp+1) = (char)(0x80 + (val & 0x3F));
|
|
846
|
+
entp+=2;
|
|
847
|
+
bytelen = 3;
|
|
848
|
+
} else if (val >= 0x80) {
|
|
849
|
+
/* two bytes */
|
|
850
|
+
*(entp-1) = (char)(0xC0 + ((val >> 6) & 0x1F));
|
|
851
|
+
*(entp+0) = (char)(0x80 + (val & 0x3F));
|
|
852
|
+
entp++;
|
|
853
|
+
bytelen = 2;
|
|
854
|
+
} else {
|
|
855
|
+
/* one byte */
|
|
856
|
+
*(entp-1) = (char)(val & 0x7F);
|
|
857
|
+
}
|
|
858
|
+
} else {
|
|
859
|
+
PLIST_XML_ERR("Invalid entity encountered: &%.*s;\n", entlen, entp);
|
|
860
|
+
return -1;
|
|
861
|
+
}
|
|
862
|
+
memmove(entp, str+i+1, len - i);
|
|
863
|
+
i -= entlen+1 - bytelen;
|
|
864
|
+
len -= entlen+2 - bytelen;
|
|
865
|
+
continue;
|
|
866
|
+
} else {
|
|
867
|
+
PLIST_XML_ERR("Invalid empty entity sequence &;\n");
|
|
868
|
+
return -1;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
i++;
|
|
872
|
+
}
|
|
873
|
+
*length = len;
|
|
874
|
+
return 0;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
static char* text_parts_get_content(text_part_t *tp, int unesc_entities, size_t *length, int *requires_free)
|
|
878
|
+
{
|
|
879
|
+
char *str = NULL;
|
|
880
|
+
size_t total_length = 0;
|
|
881
|
+
|
|
882
|
+
if (!tp) {
|
|
883
|
+
return NULL;
|
|
884
|
+
}
|
|
885
|
+
char *p;
|
|
886
|
+
if (requires_free && !tp->next) {
|
|
887
|
+
if (tp->is_cdata || !unesc_entities) {
|
|
888
|
+
*requires_free = 0;
|
|
889
|
+
if (length) {
|
|
890
|
+
*length = tp->length;
|
|
891
|
+
}
|
|
892
|
+
return (char*)tp->begin;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
text_part_t *tmp = tp;
|
|
896
|
+
while (tp && tp->begin) {
|
|
897
|
+
total_length += tp->length;
|
|
898
|
+
tp = tp->next;
|
|
899
|
+
}
|
|
900
|
+
str = malloc(total_length + 1);
|
|
901
|
+
assert(str);
|
|
902
|
+
p = str;
|
|
903
|
+
tp = tmp;
|
|
904
|
+
while (tp && tp->begin) {
|
|
905
|
+
size_t len = tp->length;
|
|
906
|
+
strncpy(p, tp->begin, len);
|
|
907
|
+
p[len] = '\0';
|
|
908
|
+
if (!tp->is_cdata && unesc_entities) {
|
|
909
|
+
if (unescape_entities(p, &len) < 0) {
|
|
910
|
+
free(str);
|
|
911
|
+
return NULL;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
p += len;
|
|
915
|
+
tp = tp->next;
|
|
916
|
+
}
|
|
917
|
+
*p = '\0';
|
|
918
|
+
if (length) {
|
|
919
|
+
*length = p - str;
|
|
920
|
+
}
|
|
921
|
+
if (requires_free) {
|
|
922
|
+
*requires_free = 1;
|
|
923
|
+
}
|
|
924
|
+
return str;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
static void node_from_xml(parse_ctx ctx, plist_t *plist)
|
|
928
|
+
{
|
|
929
|
+
char *tag = NULL;
|
|
930
|
+
char *keyname = NULL;
|
|
931
|
+
plist_t subnode = NULL;
|
|
932
|
+
const char *p = NULL;
|
|
933
|
+
plist_t parent = NULL;
|
|
934
|
+
int has_content = 0;
|
|
935
|
+
|
|
936
|
+
struct node_path_item {
|
|
937
|
+
const char *type;
|
|
938
|
+
void *prev;
|
|
939
|
+
};
|
|
940
|
+
struct node_path_item* node_path = NULL;
|
|
941
|
+
|
|
942
|
+
while (ctx->pos < ctx->end && !ctx->err) {
|
|
943
|
+
parse_skip_ws(ctx);
|
|
944
|
+
if (ctx->pos >= ctx->end) {
|
|
945
|
+
break;
|
|
946
|
+
}
|
|
947
|
+
if (*ctx->pos != '<') {
|
|
948
|
+
p = ctx->pos;
|
|
949
|
+
find_next(ctx, " \t\r\n", 4, 0);
|
|
950
|
+
PLIST_XML_ERR("Expected: opening tag, found: %.*s\n", (int)(ctx->pos - p), p);
|
|
951
|
+
ctx->err++;
|
|
952
|
+
goto err_out;
|
|
953
|
+
}
|
|
954
|
+
ctx->pos++;
|
|
955
|
+
if (ctx->pos >= ctx->end) {
|
|
956
|
+
PLIST_XML_ERR("EOF while parsing tag\n");
|
|
957
|
+
ctx->err++;
|
|
958
|
+
goto err_out;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (*(ctx->pos) == '?') {
|
|
962
|
+
find_str(ctx, "?>", 2, 1);
|
|
963
|
+
if (ctx->pos > ctx->end-2) {
|
|
964
|
+
PLIST_XML_ERR("EOF while looking for <? tag closing marker\n");
|
|
965
|
+
ctx->err++;
|
|
966
|
+
goto err_out;
|
|
967
|
+
}
|
|
968
|
+
if (strncmp(ctx->pos, "?>", 2)) {
|
|
969
|
+
PLIST_XML_ERR("Couldn't find <? tag closing marker\n");
|
|
970
|
+
ctx->err++;
|
|
971
|
+
goto err_out;
|
|
972
|
+
}
|
|
973
|
+
ctx->pos += 2;
|
|
974
|
+
continue;
|
|
975
|
+
} else if (*(ctx->pos) == '!') {
|
|
976
|
+
/* comment or DTD */
|
|
977
|
+
if (((ctx->end - ctx->pos) > 3) && !strncmp(ctx->pos, "!--", 3)) {
|
|
978
|
+
ctx->pos += 3;
|
|
979
|
+
find_str(ctx,"-->", 3, 0);
|
|
980
|
+
if (ctx->pos > ctx->end-3 || strncmp(ctx->pos, "-->", 3)) {
|
|
981
|
+
PLIST_XML_ERR("Couldn't find end of comment\n");
|
|
982
|
+
ctx->err++;
|
|
983
|
+
goto err_out;
|
|
984
|
+
}
|
|
985
|
+
ctx->pos+=3;
|
|
986
|
+
} else if (((ctx->end - ctx->pos) > 8) && !strncmp(ctx->pos, "!DOCTYPE", 8)) {
|
|
987
|
+
int embedded_dtd = 0;
|
|
988
|
+
ctx->pos+=8;
|
|
989
|
+
while (ctx->pos < ctx->end) {
|
|
990
|
+
find_next(ctx, " \t\r\n[>", 6, 1);
|
|
991
|
+
if (ctx->pos >= ctx->end) {
|
|
992
|
+
PLIST_XML_ERR("EOF while parsing !DOCTYPE\n");
|
|
993
|
+
ctx->err++;
|
|
994
|
+
goto err_out;
|
|
995
|
+
}
|
|
996
|
+
if (*ctx->pos == '[') {
|
|
997
|
+
embedded_dtd = 1;
|
|
998
|
+
break;
|
|
999
|
+
} else if (*ctx->pos == '>') {
|
|
1000
|
+
/* end of DOCTYPE found already */
|
|
1001
|
+
ctx->pos++;
|
|
1002
|
+
break;
|
|
1003
|
+
} else {
|
|
1004
|
+
parse_skip_ws(ctx);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
if (embedded_dtd) {
|
|
1008
|
+
find_str(ctx, "]>", 2, 1);
|
|
1009
|
+
if (ctx->pos > ctx->end-2 || strncmp(ctx->pos, "]>", 2)) {
|
|
1010
|
+
PLIST_XML_ERR("Couldn't find end of DOCTYPE\n");
|
|
1011
|
+
ctx->err++;
|
|
1012
|
+
goto err_out;
|
|
1013
|
+
}
|
|
1014
|
+
ctx->pos += 2;
|
|
1015
|
+
}
|
|
1016
|
+
} else {
|
|
1017
|
+
p = ctx->pos;
|
|
1018
|
+
find_next(ctx, " \r\n\t>", 5, 1);
|
|
1019
|
+
PLIST_XML_ERR("Invalid or incomplete special tag <%.*s> encountered\n", (int)(ctx->pos - p), p);
|
|
1020
|
+
ctx->err++;
|
|
1021
|
+
goto err_out;
|
|
1022
|
+
}
|
|
1023
|
+
continue;
|
|
1024
|
+
} else {
|
|
1025
|
+
int is_empty = 0;
|
|
1026
|
+
int closing_tag = 0;
|
|
1027
|
+
p = ctx->pos;
|
|
1028
|
+
find_next(ctx," \r\n\t<>", 6, 0);
|
|
1029
|
+
if (ctx->pos >= ctx->end) {
|
|
1030
|
+
PLIST_XML_ERR("Unexpected EOF while parsing XML\n");
|
|
1031
|
+
ctx->err++;
|
|
1032
|
+
goto err_out;
|
|
1033
|
+
}
|
|
1034
|
+
int taglen = ctx->pos - p;
|
|
1035
|
+
tag = malloc(taglen + 1);
|
|
1036
|
+
strncpy(tag, p, taglen);
|
|
1037
|
+
tag[taglen] = '\0';
|
|
1038
|
+
if (*ctx->pos != '>') {
|
|
1039
|
+
find_next(ctx, "<>", 2, 1);
|
|
1040
|
+
}
|
|
1041
|
+
if (ctx->pos >= ctx->end) {
|
|
1042
|
+
PLIST_XML_ERR("Unexpected EOF while parsing XML\n");
|
|
1043
|
+
ctx->err++;
|
|
1044
|
+
goto err_out;
|
|
1045
|
+
}
|
|
1046
|
+
if (*ctx->pos != '>') {
|
|
1047
|
+
PLIST_XML_ERR("Missing '>' for tag <%s\n", tag);
|
|
1048
|
+
ctx->err++;
|
|
1049
|
+
goto err_out;
|
|
1050
|
+
}
|
|
1051
|
+
if (*(ctx->pos-1) == '/') {
|
|
1052
|
+
int idx = ctx->pos - p - 1;
|
|
1053
|
+
if (idx < taglen)
|
|
1054
|
+
tag[idx] = '\0';
|
|
1055
|
+
is_empty = 1;
|
|
1056
|
+
}
|
|
1057
|
+
ctx->pos++;
|
|
1058
|
+
if (!strcmp(tag, "plist")) {
|
|
1059
|
+
free(tag);
|
|
1060
|
+
tag = NULL;
|
|
1061
|
+
has_content = 0;
|
|
1062
|
+
|
|
1063
|
+
if (!node_path && *plist) {
|
|
1064
|
+
/* we don't allow another top-level <plist> */
|
|
1065
|
+
break;
|
|
1066
|
+
}
|
|
1067
|
+
if (is_empty) {
|
|
1068
|
+
PLIST_XML_ERR("Empty plist tag\n");
|
|
1069
|
+
ctx->err++;
|
|
1070
|
+
goto err_out;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
struct node_path_item *path_item = malloc(sizeof(struct node_path_item));
|
|
1074
|
+
if (!path_item) {
|
|
1075
|
+
PLIST_XML_ERR("out of memory when allocating node path item\n");
|
|
1076
|
+
ctx->err++;
|
|
1077
|
+
goto err_out;
|
|
1078
|
+
}
|
|
1079
|
+
path_item->type = "plist";
|
|
1080
|
+
path_item->prev = node_path;
|
|
1081
|
+
node_path = path_item;
|
|
1082
|
+
|
|
1083
|
+
continue;
|
|
1084
|
+
} else if (!strcmp(tag, "/plist")) {
|
|
1085
|
+
if (!has_content) {
|
|
1086
|
+
PLIST_XML_ERR("encountered empty plist tag\n");
|
|
1087
|
+
ctx->err++;
|
|
1088
|
+
goto err_out;
|
|
1089
|
+
}
|
|
1090
|
+
if (!node_path) {
|
|
1091
|
+
PLIST_XML_ERR("node path is empty while trying to match closing tag with opening tag\n");
|
|
1092
|
+
ctx->err++;
|
|
1093
|
+
goto err_out;
|
|
1094
|
+
}
|
|
1095
|
+
if (strcmp(node_path->type, tag+1) != 0) {
|
|
1096
|
+
PLIST_XML_ERR("mismatching closing tag <%s> found for opening tag <%s>\n", tag, node_path->type);
|
|
1097
|
+
ctx->err++;
|
|
1098
|
+
goto err_out;
|
|
1099
|
+
}
|
|
1100
|
+
struct node_path_item *path_item = node_path;
|
|
1101
|
+
node_path = node_path->prev;
|
|
1102
|
+
free(path_item);
|
|
1103
|
+
|
|
1104
|
+
free(tag);
|
|
1105
|
+
tag = NULL;
|
|
1106
|
+
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
plist_data_t data = plist_new_plist_data();
|
|
1111
|
+
subnode = plist_new_node(data);
|
|
1112
|
+
has_content = 1;
|
|
1113
|
+
|
|
1114
|
+
if (!strcmp(tag, XPLIST_DICT)) {
|
|
1115
|
+
data->type = PLIST_DICT;
|
|
1116
|
+
} else if (!strcmp(tag, XPLIST_ARRAY)) {
|
|
1117
|
+
data->type = PLIST_ARRAY;
|
|
1118
|
+
} else if (!strcmp(tag, XPLIST_INT)) {
|
|
1119
|
+
if (!is_empty) {
|
|
1120
|
+
text_part_t first_part = { NULL, 0, 0, NULL };
|
|
1121
|
+
text_part_t *tp = get_text_parts(ctx, tag, taglen, 1, &first_part);
|
|
1122
|
+
if (!tp) {
|
|
1123
|
+
PLIST_XML_ERR("Could not parse text content for '%s' node\n", tag);
|
|
1124
|
+
text_parts_free(first_part.next);
|
|
1125
|
+
ctx->err++;
|
|
1126
|
+
goto err_out;
|
|
1127
|
+
}
|
|
1128
|
+
if (tp->begin) {
|
|
1129
|
+
int requires_free = 0;
|
|
1130
|
+
char *str_content = text_parts_get_content(tp, 0, NULL, &requires_free);
|
|
1131
|
+
if (!str_content) {
|
|
1132
|
+
PLIST_XML_ERR("Could not get text content for '%s' node\n", tag);
|
|
1133
|
+
text_parts_free(first_part.next);
|
|
1134
|
+
ctx->err++;
|
|
1135
|
+
goto err_out;
|
|
1136
|
+
}
|
|
1137
|
+
char *str = str_content;
|
|
1138
|
+
int is_negative = 0;
|
|
1139
|
+
if ((str[0] == '-') || (str[0] == '+')) {
|
|
1140
|
+
if (str[0] == '-') {
|
|
1141
|
+
is_negative = 1;
|
|
1142
|
+
}
|
|
1143
|
+
str++;
|
|
1144
|
+
}
|
|
1145
|
+
data->intval = strtoull((char*)str, NULL, 0);
|
|
1146
|
+
if (is_negative || (data->intval <= INT64_MAX)) {
|
|
1147
|
+
uint64_t v = data->intval;
|
|
1148
|
+
if (is_negative) {
|
|
1149
|
+
v = -v;
|
|
1150
|
+
}
|
|
1151
|
+
data->intval = v;
|
|
1152
|
+
data->length = 8;
|
|
1153
|
+
} else {
|
|
1154
|
+
data->length = 16;
|
|
1155
|
+
}
|
|
1156
|
+
if (requires_free) {
|
|
1157
|
+
free(str_content);
|
|
1158
|
+
}
|
|
1159
|
+
} else {
|
|
1160
|
+
is_empty = 1;
|
|
1161
|
+
}
|
|
1162
|
+
text_parts_free(tp->next);
|
|
1163
|
+
}
|
|
1164
|
+
if (is_empty) {
|
|
1165
|
+
data->intval = 0;
|
|
1166
|
+
data->length = 8;
|
|
1167
|
+
}
|
|
1168
|
+
data->type = PLIST_UINT;
|
|
1169
|
+
} else if (!strcmp(tag, XPLIST_REAL)) {
|
|
1170
|
+
if (!is_empty) {
|
|
1171
|
+
text_part_t first_part = { NULL, 0, 0, NULL };
|
|
1172
|
+
text_part_t *tp = get_text_parts(ctx, tag, taglen, 1, &first_part);
|
|
1173
|
+
if (!tp) {
|
|
1174
|
+
PLIST_XML_ERR("Could not parse text content for '%s' node\n", tag);
|
|
1175
|
+
text_parts_free(first_part.next);
|
|
1176
|
+
ctx->err++;
|
|
1177
|
+
goto err_out;
|
|
1178
|
+
}
|
|
1179
|
+
if (tp->begin) {
|
|
1180
|
+
int requires_free = 0;
|
|
1181
|
+
char *str_content = text_parts_get_content(tp, 0, NULL, &requires_free);
|
|
1182
|
+
if (!str_content) {
|
|
1183
|
+
PLIST_XML_ERR("Could not get text content for '%s' node\n", tag);
|
|
1184
|
+
text_parts_free(first_part.next);
|
|
1185
|
+
ctx->err++;
|
|
1186
|
+
goto err_out;
|
|
1187
|
+
}
|
|
1188
|
+
data->realval = atof(str_content);
|
|
1189
|
+
if (requires_free) {
|
|
1190
|
+
free(str_content);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
text_parts_free(tp->next);
|
|
1194
|
+
}
|
|
1195
|
+
data->type = PLIST_REAL;
|
|
1196
|
+
data->length = 8;
|
|
1197
|
+
} else if (!strcmp(tag, XPLIST_TRUE)) {
|
|
1198
|
+
if (!is_empty) {
|
|
1199
|
+
get_text_parts(ctx, tag, taglen, 1, NULL);
|
|
1200
|
+
}
|
|
1201
|
+
data->type = PLIST_BOOLEAN;
|
|
1202
|
+
data->boolval = 1;
|
|
1203
|
+
data->length = 1;
|
|
1204
|
+
} else if (!strcmp(tag, XPLIST_FALSE)) {
|
|
1205
|
+
if (!is_empty) {
|
|
1206
|
+
get_text_parts(ctx, tag, taglen, 1, NULL);
|
|
1207
|
+
}
|
|
1208
|
+
data->type = PLIST_BOOLEAN;
|
|
1209
|
+
data->boolval = 0;
|
|
1210
|
+
data->length = 1;
|
|
1211
|
+
} else if (!strcmp(tag, XPLIST_STRING) || !strcmp(tag, XPLIST_KEY)) {
|
|
1212
|
+
if (!is_empty) {
|
|
1213
|
+
text_part_t first_part = { NULL, 0, 0, NULL };
|
|
1214
|
+
text_part_t *tp = get_text_parts(ctx, tag, taglen, 0, &first_part);
|
|
1215
|
+
char *str = NULL;
|
|
1216
|
+
size_t length = 0;
|
|
1217
|
+
if (!tp) {
|
|
1218
|
+
PLIST_XML_ERR("Could not parse text content for '%s' node\n", tag);
|
|
1219
|
+
text_parts_free(first_part.next);
|
|
1220
|
+
ctx->err++;
|
|
1221
|
+
goto err_out;
|
|
1222
|
+
}
|
|
1223
|
+
str = text_parts_get_content(tp, 1, &length, NULL);
|
|
1224
|
+
text_parts_free(first_part.next);
|
|
1225
|
+
if (!str) {
|
|
1226
|
+
PLIST_XML_ERR("Could not get text content for '%s' node\n", tag);
|
|
1227
|
+
ctx->err++;
|
|
1228
|
+
goto err_out;
|
|
1229
|
+
}
|
|
1230
|
+
if (!strcmp(tag, "key") && !keyname && parent && (plist_get_node_type(parent) == PLIST_DICT)) {
|
|
1231
|
+
keyname = str;
|
|
1232
|
+
free(tag);
|
|
1233
|
+
tag = NULL;
|
|
1234
|
+
plist_free(subnode);
|
|
1235
|
+
subnode = NULL;
|
|
1236
|
+
continue;
|
|
1237
|
+
} else {
|
|
1238
|
+
data->strval = str;
|
|
1239
|
+
data->length = length;
|
|
1240
|
+
}
|
|
1241
|
+
} else {
|
|
1242
|
+
data->strval = strdup("");
|
|
1243
|
+
data->length = 0;
|
|
1244
|
+
}
|
|
1245
|
+
data->type = PLIST_STRING;
|
|
1246
|
+
} else if (!strcmp(tag, XPLIST_DATA)) {
|
|
1247
|
+
if (!is_empty) {
|
|
1248
|
+
text_part_t first_part = { NULL, 0, 0, NULL };
|
|
1249
|
+
text_part_t *tp = get_text_parts(ctx, tag, taglen, 1, &first_part);
|
|
1250
|
+
if (!tp) {
|
|
1251
|
+
PLIST_XML_ERR("Could not parse text content for '%s' node\n", tag);
|
|
1252
|
+
text_parts_free(first_part.next);
|
|
1253
|
+
ctx->err++;
|
|
1254
|
+
goto err_out;
|
|
1255
|
+
}
|
|
1256
|
+
if (tp->begin) {
|
|
1257
|
+
int requires_free = 0;
|
|
1258
|
+
char *str_content = text_parts_get_content(tp, 0, NULL, &requires_free);
|
|
1259
|
+
if (!str_content) {
|
|
1260
|
+
PLIST_XML_ERR("Could not get text content for '%s' node\n", tag);
|
|
1261
|
+
text_parts_free(first_part.next);
|
|
1262
|
+
ctx->err++;
|
|
1263
|
+
goto err_out;
|
|
1264
|
+
}
|
|
1265
|
+
size_t size = tp->length;
|
|
1266
|
+
if (size > 0) {
|
|
1267
|
+
data->buff = base64decode(str_content, &size);
|
|
1268
|
+
data->length = size;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
if (requires_free) {
|
|
1272
|
+
free(str_content);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
text_parts_free(tp->next);
|
|
1276
|
+
}
|
|
1277
|
+
data->type = PLIST_DATA;
|
|
1278
|
+
} else if (!strcmp(tag, XPLIST_DATE)) {
|
|
1279
|
+
if (!is_empty) {
|
|
1280
|
+
text_part_t first_part = { NULL, 0, 0, NULL };
|
|
1281
|
+
text_part_t *tp = get_text_parts(ctx, tag, taglen, 1, &first_part);
|
|
1282
|
+
if (!tp) {
|
|
1283
|
+
PLIST_XML_ERR("Could not parse text content for '%s' node\n", tag);
|
|
1284
|
+
text_parts_free(first_part.next);
|
|
1285
|
+
ctx->err++;
|
|
1286
|
+
goto err_out;
|
|
1287
|
+
}
|
|
1288
|
+
Time64_T timev = 0;
|
|
1289
|
+
if (tp->begin) {
|
|
1290
|
+
int requires_free = 0;
|
|
1291
|
+
size_t length = 0;
|
|
1292
|
+
char *str_content = text_parts_get_content(tp, 0, &length, &requires_free);
|
|
1293
|
+
if (!str_content) {
|
|
1294
|
+
PLIST_XML_ERR("Could not get text content for '%s' node\n", tag);
|
|
1295
|
+
text_parts_free(first_part.next);
|
|
1296
|
+
ctx->err++;
|
|
1297
|
+
goto err_out;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
if ((length >= 11) && (length < 32)) {
|
|
1301
|
+
/* we need to copy here and 0-terminate because sscanf will read the entire string (whole rest of XML data) which can be huge */
|
|
1302
|
+
char strval[32];
|
|
1303
|
+
struct TM btime;
|
|
1304
|
+
strncpy(strval, str_content, length);
|
|
1305
|
+
strval[tp->length] = '\0';
|
|
1306
|
+
parse_date(strval, &btime);
|
|
1307
|
+
timev = timegm64(&btime);
|
|
1308
|
+
} else {
|
|
1309
|
+
PLIST_XML_ERR("Invalid text content in date node\n");
|
|
1310
|
+
}
|
|
1311
|
+
if (requires_free) {
|
|
1312
|
+
free(str_content);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
text_parts_free(tp->next);
|
|
1316
|
+
data->realval = (double)(timev - MAC_EPOCH);
|
|
1317
|
+
}
|
|
1318
|
+
data->length = sizeof(double);
|
|
1319
|
+
data->type = PLIST_DATE;
|
|
1320
|
+
} else if (tag[0] == '/') {
|
|
1321
|
+
closing_tag = 1;
|
|
1322
|
+
} else {
|
|
1323
|
+
PLIST_XML_ERR("Unexpected tag <%s%s> encountered\n", tag, (is_empty) ? "/" : "");
|
|
1324
|
+
ctx->pos = ctx->end;
|
|
1325
|
+
ctx->err++;
|
|
1326
|
+
goto err_out;
|
|
1327
|
+
}
|
|
1328
|
+
if (subnode && !closing_tag) {
|
|
1329
|
+
if (!*plist) {
|
|
1330
|
+
/* first node, make this node the parent node */
|
|
1331
|
+
*plist = subnode;
|
|
1332
|
+
if (data->type != PLIST_DICT && data->type != PLIST_ARRAY) {
|
|
1333
|
+
/* if the first node is not a structered node, we're done */
|
|
1334
|
+
subnode = NULL;
|
|
1335
|
+
goto err_out;
|
|
1336
|
+
}
|
|
1337
|
+
parent = subnode;
|
|
1338
|
+
} else if (parent) {
|
|
1339
|
+
switch (plist_get_node_type(parent)) {
|
|
1340
|
+
case PLIST_DICT:
|
|
1341
|
+
if (!keyname) {
|
|
1342
|
+
PLIST_XML_ERR("missing key name while adding dict item\n");
|
|
1343
|
+
ctx->err++;
|
|
1344
|
+
goto err_out;
|
|
1345
|
+
}
|
|
1346
|
+
plist_dict_set_item(parent, keyname, subnode);
|
|
1347
|
+
break;
|
|
1348
|
+
case PLIST_ARRAY:
|
|
1349
|
+
plist_array_append_item(parent, subnode);
|
|
1350
|
+
break;
|
|
1351
|
+
default:
|
|
1352
|
+
/* should not happen */
|
|
1353
|
+
PLIST_XML_ERR("parent is not a structured node\n");
|
|
1354
|
+
ctx->err++;
|
|
1355
|
+
goto err_out;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
if (!is_empty && (data->type == PLIST_DICT || data->type == PLIST_ARRAY)) {
|
|
1359
|
+
struct node_path_item *path_item = malloc(sizeof(struct node_path_item));
|
|
1360
|
+
if (!path_item) {
|
|
1361
|
+
PLIST_XML_ERR("out of memory when allocating node path item\n");
|
|
1362
|
+
ctx->err++;
|
|
1363
|
+
goto err_out;
|
|
1364
|
+
}
|
|
1365
|
+
path_item->type = (data->type == PLIST_DICT) ? XPLIST_DICT : XPLIST_ARRAY;
|
|
1366
|
+
path_item->prev = node_path;
|
|
1367
|
+
node_path = path_item;
|
|
1368
|
+
|
|
1369
|
+
parent = subnode;
|
|
1370
|
+
}
|
|
1371
|
+
subnode = NULL;
|
|
1372
|
+
} else if (closing_tag) {
|
|
1373
|
+
if (!node_path) {
|
|
1374
|
+
PLIST_XML_ERR("node path is empty while trying to match closing tag with opening tag\n");
|
|
1375
|
+
ctx->err++;
|
|
1376
|
+
goto err_out;
|
|
1377
|
+
}
|
|
1378
|
+
if (strcmp(node_path->type, tag+1) != 0) {
|
|
1379
|
+
PLIST_XML_ERR("unexpected %s found (for opening %s)\n", tag, node_path->type);
|
|
1380
|
+
ctx->err++;
|
|
1381
|
+
goto err_out;
|
|
1382
|
+
}
|
|
1383
|
+
struct node_path_item *path_item = node_path;
|
|
1384
|
+
node_path = node_path->prev;
|
|
1385
|
+
free(path_item);
|
|
1386
|
+
|
|
1387
|
+
parent = ((node_t*)parent)->parent;
|
|
1388
|
+
if (!parent) {
|
|
1389
|
+
goto err_out;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
free(tag);
|
|
1394
|
+
tag = NULL;
|
|
1395
|
+
free(keyname);
|
|
1396
|
+
keyname = NULL;
|
|
1397
|
+
plist_free(subnode);
|
|
1398
|
+
subnode = NULL;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
if (node_path) {
|
|
1403
|
+
PLIST_XML_ERR("EOF encountered while </%s> was expected\n", node_path->type);
|
|
1404
|
+
ctx->err++;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
err_out:
|
|
1408
|
+
free(tag);
|
|
1409
|
+
free(keyname);
|
|
1410
|
+
plist_free(subnode);
|
|
1411
|
+
|
|
1412
|
+
/* clean up node_path if required */
|
|
1413
|
+
while (node_path) {
|
|
1414
|
+
struct node_path_item *path_item = node_path;
|
|
1415
|
+
node_path = path_item->prev;
|
|
1416
|
+
free(path_item);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
if (ctx->err) {
|
|
1420
|
+
plist_free(*plist);
|
|
1421
|
+
*plist = NULL;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
PLIST_API void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist)
|
|
1426
|
+
{
|
|
1427
|
+
if (!plist_xml || (length == 0)) {
|
|
1428
|
+
*plist = NULL;
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
struct _parse_ctx ctx = { plist_xml, plist_xml + length, 0 };
|
|
1433
|
+
|
|
1434
|
+
node_from_xml(&ctx, plist);
|
|
1435
|
+
}
|