├── .asf.yaml ├── .eslintrc.yml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── BUG_REPORT.md │ ├── FEATURE_REQUEST.md │ └── SUPPORT_QUESTION.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── android.yml │ ├── chrome.yml │ ├── ios.yml │ └── lint.yml ├── .gitignore ├── .jshintrc ├── .npmignore ├── .npmrc ├── .ratignore ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── RELEASENOTES.md ├── doc └── plugins.md ├── package-lock.json ├── package.json ├── plugin.xml ├── src ├── android │ ├── AssetFilesystem.java │ ├── ContentFilesystem.java │ ├── DirectoryManager.java │ ├── EncodingException.java │ ├── FileExistsException.java │ ├── FileUtils.java │ ├── Filesystem.java │ ├── InvalidModificationException.java │ ├── LocalFilesystem.java │ ├── LocalFilesystemURL.java │ ├── NoModificationAllowedException.java │ ├── PendingRequests.java │ ├── TypeMismatchException.java │ └── build-extras.gradle ├── browser │ └── FileProxy.js ├── ios │ ├── CDVAssetLibraryFilesystem.h │ ├── CDVAssetLibraryFilesystem.m │ ├── CDVFile.bundle │ │ └── PrivacyInfo.xcprivacy │ ├── CDVFile.h │ ├── CDVFile.m │ ├── CDVLocalFilesystem.h │ └── CDVLocalFilesystem.m ├── osx │ ├── CDVFile.h │ ├── CDVFile.m │ ├── CDVLocalFilesystem.h │ └── CDVLocalFilesystem.m └── windows │ └── FileProxy.js ├── tests ├── package-lock.json ├── package.json ├── plugin.xml ├── src │ └── android │ │ └── TestContentProvider.java ├── tests.js └── www │ └── fixtures │ └── asset-test │ └── asset-test.txt ├── types └── index.d.ts └── www ├── DirectoryEntry.js ├── DirectoryReader.js ├── Entry.js ├── File.js ├── FileEntry.js ├── FileError.js ├── FileReader.js ├── FileSystem.js ├── FileUploadOptions.js ├── FileUploadResult.js ├── FileWriter.js ├── Flags.js ├── LocalFileSystem.js ├── Metadata.js ├── ProgressEvent.js ├── android ├── Entry.js └── FileSystem.js ├── browser ├── FileSystem.js ├── Preparing.js └── isChrome.js ├── fileSystemPaths.js ├── fileSystems-roots.js ├── fileSystems.js ├── ios ├── Entry.js └── FileSystem.js ├── osx └── FileSystem.js ├── requestFileSystem.js └── resolveLocalFileSystemURI.js /.asf.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | github: 19 | description: Apache Cordova File Plugin 20 | homepage: https://cordova.apache.org/ 21 | 22 | labels: 23 | - android 24 | - cordova 25 | - hacktoberfest 26 | - ios 27 | - java 28 | - javascript 29 | - library 30 | - mobile 31 | - nodejs 32 | - objective-c 33 | 34 | features: 35 | wiki: false 36 | issues: true 37 | projects: true 38 | 39 | enabled_merge_buttons: 40 | squash: true 41 | merge: false 42 | rebase: false 43 | 44 | notifications: 45 | commits: commits@cordova.apache.org 46 | issues: issues@cordova.apache.org 47 | pullrequests_status: issues@cordova.apache.org 48 | pullrequests_comment: issues@cordova.apache.org 49 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | root: true 2 | extends: '@cordova/eslint-config/browser' 3 | globals: 4 | cordova: true 5 | LocalFileSystem: true 6 | FileError: true 7 | DirectoryEntry: true 8 | FileWriter: true 9 | Flags: true 10 | Metadata: true 11 | FileSystem: true 12 | resolveLocalFileSystemURL: true 13 | 14 | overrides: 15 | - files: [tests/**/*.js] 16 | extends: '@cordova/eslint-config/node-tests' 17 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | ### Issue Type 7 | 8 | 9 | - [ ] Bug Report 10 | - [ ] Feature Request 11 | - [ ] Support Question 12 | 13 | ## Description 14 | 15 | ## Information 16 | 17 | 18 | ### Command or Code 19 | 20 | 21 | ### Environment, Platform, Device 22 | 23 | 24 | 25 | 26 | ### Version information 27 | 34 | 35 | 36 | 37 | ## Checklist 38 | 39 | 40 | - [ ] I searched for already existing GitHub issues about this 41 | - [ ] I updated all Cordova tooling to their most recent version 42 | - [ ] I included all the necessary information above 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG_REPORT.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: If something isn't working as expected. 4 | 5 | --- 6 | 7 | # Bug Report 8 | 9 | ## Problem 10 | 11 | ### What is expected to happen? 12 | 13 | 14 | 15 | ### What does actually happen? 16 | 17 | 18 | 19 | ## Information 20 | 21 | 22 | 23 | 24 | ### Command or Code 25 | 26 | 27 | 28 | 29 | ### Environment, Platform, Device 30 | 31 | 32 | 33 | 34 | ### Version information 35 | 42 | 43 | 44 | 45 | ## Checklist 46 | 47 | 48 | - [ ] I searched for existing GitHub issues 49 | - [ ] I updated all Cordova tooling to most recent version 50 | - [ ] I included all the necessary information above 51 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: A suggestion for a new functionality 4 | 5 | --- 6 | 7 | # Feature Request 8 | 9 | ## Motivation Behind Feature 10 | 11 | 12 | 13 | 14 | ## Feature Description 15 | 20 | 21 | 22 | 23 | ## Alternatives or Workarounds 24 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💬 Support Question 3 | about: If you have a question, please check out our Slack or StackOverflow! 4 | 5 | --- 6 | 7 | 8 | 9 | Apache Cordova uses GitHub Issues as a feature request and bug tracker _only_. 10 | For usage and support questions, please check out the resources below. Thanks! 11 | 12 | --- 13 | 14 | You can get answers to your usage and support questions about **Apache Cordova** on: 15 | 16 | * Slack Community Chat: https://cordova.slack.com (you can sign-up at http://slack.cordova.io/) 17 | * StackOverflow: https://stackoverflow.com/questions/tagged/cordova using the tag `cordova` 18 | 19 | --- 20 | 21 | If you are using a tool that uses Cordova internally, like e.g. Ionic, check their support channels: 22 | 23 | * **Ionic Framework** 24 | * [Ionic Community Forum](https://forum.ionicframework.com/) 25 | * [Ionic Worldwide Slack](https://ionicworldwide.herokuapp.com/) 26 | * **PhoneGap** 27 | * [PhoneGap Developer Community](https://forums.adobe.com/community/phonegap) 28 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Platforms affected 10 | 11 | 12 | 13 | ### Motivation and Context 14 | 15 | 16 | 17 | 18 | 19 | ### Description 20 | 21 | 22 | 23 | 24 | ### Testing 25 | 26 | 27 | 28 | 29 | ### Checklist 30 | 31 | - [ ] I've run the tests to see all new and existing tests pass 32 | - [ ] I added automated test coverage as appropriate for this change 33 | - [ ] Commit is prefixed with `(platform)` if this change only applies to one platform (e.g. `(android)`) 34 | - [ ] If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct [keyword to close issues using keywords](https://help.github.com/articles/closing-issues-using-keywords/)) 35 | - [ ] I've updated the documentation if necessary 36 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | name: Android Testsuite 19 | 20 | on: 21 | push: 22 | paths-ignore: 23 | - '**.md' 24 | - 'LICENSE' 25 | - '.eslint*' 26 | 27 | pull_request: 28 | paths-ignore: 29 | - '**.md' 30 | - 'LICENSE' 31 | - '.eslint*' 32 | 33 | jobs: 34 | test: 35 | name: Android ${{ matrix.versions.android }} Test 36 | runs-on: ubuntu-latest 37 | continue-on-error: true 38 | 39 | # hoist configurations to top that are expected to be updated 40 | env: 41 | # Storing a copy of the repo 42 | repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }} 43 | 44 | node-version: 20 45 | 46 | # These are the default Java configurations used by most tests. 47 | # To customize these options, add "java-distro" or "java-version" to the strategy matrix with its overriding value. 48 | default_java-distro: temurin 49 | default_java-version: 17 50 | 51 | # These are the default Android System Image configurations used by most tests. 52 | # To customize these options, add "system-image-arch" or "system-image-target" to the strategy matrix with its overriding value. 53 | default_system-image-arch: x86_64 54 | default_system-image-target: google_apis # Most system images have a google_api option. Set this as default. 55 | 56 | # configurations for each testing strategy (test matrix) 57 | strategy: 58 | matrix: 59 | versions: 60 | - android: 7 61 | android-api: 24 62 | 63 | - android: 7.1 64 | android-api: 25 65 | 66 | - android: 8 67 | android-api: 26 68 | 69 | - android: 8.1 70 | android-api: 27 71 | system-image-arch: x86 72 | 73 | - android: 9 74 | android-api: 28 75 | 76 | - android: 10 77 | android-api: 29 78 | 79 | - android: 11 80 | android-api: 30 81 | 82 | - android: 12 83 | android-api: 31 84 | 85 | - android: 12L 86 | android-api: 32 87 | 88 | - android: 13 89 | android-api: 33 90 | 91 | - android: 14 92 | android-api: 34 93 | 94 | timeout-minutes: 60 95 | 96 | steps: 97 | - uses: actions/checkout@v4 98 | - uses: actions/setup-node@v4 99 | with: 100 | node-version: ${{ env.node-version }} 101 | - uses: actions/setup-java@v4 102 | env: 103 | java-version: ${{ matrix.versions.java-version == '' && env.default_java-version || matrix.versions.java-version }} 104 | java-distro: ${{ matrix.versions.java-distro == '' && env.default_java-distro || matrix.versions.java-distro }} 105 | with: 106 | distribution: ${{ env.java-distro }} 107 | java-version: ${{ env.java-version }} 108 | 109 | - name: Enable KVM group perms 110 | run: | 111 | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules 112 | sudo udevadm control --reload-rules 113 | sudo udevadm trigger --name-match=kvm 114 | 115 | - name: Run Environment Information 116 | run: | 117 | node --version 118 | npm --version 119 | java -version 120 | 121 | - name: Run npm install 122 | run: | 123 | export PATH="/usr/local/lib/android/sdk/platform-tools":$PATH 124 | export JAVA_HOME=$JAVA_HOME_11_X64 125 | npm i -g cordova@latest 126 | npm ci 127 | 128 | - name: Run paramedic install 129 | if: ${{ endswith(env.repo, '/cordova-paramedic') != true }} 130 | run: npm i -g github:apache/cordova-paramedic 131 | 132 | - uses: reactivecircus/android-emulator-runner@v2 133 | env: 134 | system-image-arch: ${{ matrix.versions.system-image-arch == '' && env.default_system-image-arch || matrix.versions.system-image-arch }} 135 | system-image-target: ${{ matrix.versions.system-image-target == '' && env.default_system-image-target || matrix.versions.system-image-target }} 136 | with: 137 | api-level: ${{ matrix.versions.android-api }} 138 | target: ${{ env.system-image-target }} 139 | arch: ${{ env.system-image-arch }} 140 | force-avd-creation: false 141 | disable-animations: false 142 | emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim 143 | script: echo "Pregenerate the AVD before running Paramedic" 144 | 145 | - name: Run paramedic tests 146 | uses: reactivecircus/android-emulator-runner@v2 147 | env: 148 | system-image-arch: ${{ matrix.versions.system-image-arch == '' && env.default_system-image-arch || matrix.versions.system-image-arch }} 149 | system-image-target: ${{ matrix.versions.system-image-target == '' && env.default_system-image-target || matrix.versions.system-image-target }} 150 | test_config: 'android-${{ matrix.versions.android }}.config.json' 151 | # Generally, this should automatically work for cordova-paramedic & plugins. If the path is unique, this can be manually changed. 152 | test_plugin_path: ${{ endswith(env.repo, '/cordova-paramedic') && './spec/testable-plugin/' || './' }} 153 | paramedic: ${{ endswith(env.repo, '/cordova-paramedic') && 'node main.js' || 'cordova-paramedic' }} 154 | with: 155 | api-level: ${{ matrix.versions.android-api }} 156 | target: ${{ env.system-image-target }} 157 | arch: ${{ env.system-image-arch }} 158 | force-avd-creation: false 159 | disable-animations: false 160 | emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim 161 | script: ${{ env.paramedic }} --config ./pr/local/${{ env.test_config }} --plugin ${{ env.test_plugin_path }} 162 | -------------------------------------------------------------------------------- /.github/workflows/chrome.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | name: Chrome Testsuite 19 | 20 | on: 21 | push: 22 | paths-ignore: 23 | - '**.md' 24 | - 'LICENSE' 25 | - '.eslint*' 26 | pull_request: 27 | paths-ignore: 28 | - '**.md' 29 | - 'LICENSE' 30 | - '.eslint*' 31 | 32 | jobs: 33 | test: 34 | name: Chrome Latest Test 35 | runs-on: ubuntu-latest 36 | 37 | # hoist configurations to top that are expected to be updated 38 | env: 39 | # Storing a copy of the repo 40 | repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }} 41 | 42 | node-version: 20 43 | 44 | steps: 45 | - uses: actions/checkout@v4 46 | - uses: actions/setup-node@v4 47 | with: 48 | node-version: ${{ env.node-version }} 49 | 50 | - name: Run install xvfb 51 | run: sudo apt-get install xvfb 52 | 53 | - name: Run Environment Information 54 | run: | 55 | node --version 56 | npm --version 57 | 58 | - name: Run npm install 59 | run: | 60 | npm i -g cordova@latest 61 | npm ci 62 | 63 | - name: Run paramedic install 64 | if: ${{ endswith(env.repo, '/cordova-paramedic') != true }} 65 | run: npm i -g github:apache/cordova-paramedic 66 | 67 | - name: Run paramedic tests 68 | env: 69 | test_config: 'browser.config.json' 70 | # Generally, this should automatically work for cordova-paramedic & plugins. If the path is unique, this can be manually changed. 71 | test_plugin_path: ${{ endswith(env.repo, '/cordova-paramedic') && './spec/testable-plugin/' || './' }} 72 | paramedic: ${{ endswith(env.repo, '/cordova-paramedic') && 'node main.js' || 'cordova-paramedic' }} 73 | run: xvfb-run --auto-servernum ${{ env.paramedic }} --config ./pr/local/${{ env.test_config }} --plugin ${{ env.test_plugin_path }} 74 | -------------------------------------------------------------------------------- /.github/workflows/ios.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | name: iOS Testsuite 19 | 20 | on: 21 | push: 22 | paths-ignore: 23 | - '**.md' 24 | - 'LICENSE' 25 | - '.eslint*' 26 | pull_request: 27 | paths-ignore: 28 | - '**.md' 29 | - 'LICENSE' 30 | - '.eslint*' 31 | 32 | jobs: 33 | test: 34 | name: iOS ${{ matrix.versions.ios-version }} Test 35 | runs-on: ${{ matrix.versions.os-version }} 36 | continue-on-error: true 37 | 38 | # hoist configurations to top that are expected to be updated 39 | env: 40 | # Storing a copy of the repo 41 | repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }} 42 | 43 | node-version: 20 44 | 45 | # > Starting April 26, 2021, all iOS and iPadOS apps submitted to the App Store must be built with Xcode 12 and the iOS 14 SDK. 46 | # Because of Apple's requirement, listed above, We will only be using the latest Xcode release for testing. 47 | # To customize these options, add "xcode-version" to the strategy matrix with its overriding value. 48 | default_xcode-version: latest-stable 49 | 50 | strategy: 51 | matrix: 52 | versions: 53 | - os-version: macos-12 54 | ios-version: 15.x 55 | xcode-version: 13.x 56 | 57 | - os-version: macos-14 58 | ios-version: 16.x 59 | xcode-version: 14.x 60 | 61 | - os-version: macos-14 62 | ios-version: 17.x 63 | xcode-version: 15.x 64 | 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: actions/setup-node@v4 68 | with: 69 | node-version: ${{ env.node-version }} 70 | - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd 71 | env: 72 | xcode-version: ${{ matrix.versions.xcode-version == '' && env.default_xcode-version || matrix.versions.xcode-version }} 73 | with: 74 | xcode-version: ${{ env.xcode-version }} 75 | 76 | - name: Run Environment Information 77 | run: | 78 | node --version 79 | npm --version 80 | xcodebuild -version 81 | 82 | - name: Run npm install 83 | run: | 84 | npm i -g cordova@latest ios-deploy@latest 85 | npm ci 86 | 87 | - name: Run paramedic install 88 | if: ${{ endswith(env.repo, '/cordova-paramedic') != true }} 89 | run: npm i -g github:apache/cordova-paramedic 90 | 91 | - name: Run paramedic tests 92 | env: 93 | test_config: 'ios-${{ matrix.versions.ios-version }}.config.json' 94 | # Generally, this should automatically work for cordova-paramedic & plugins. If the path is unique, this can be manually changed. 95 | test_plugin_path: ${{ endswith(env.repo, '/cordova-paramedic') && './spec/testable-plugin/' || './' }} 96 | paramedic: ${{ endswith(env.repo, '/cordova-paramedic') && 'node main.js' || 'cordova-paramedic' }} 97 | run: ${{ env.paramedic }} --config ./pr/local/${{ env.test_config }} --plugin ${{ env.test_plugin_path }} 98 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | name: Lint Test 19 | 20 | on: 21 | push: 22 | paths: 23 | - '**.js' 24 | - '.eslint*' 25 | - '.github/workflow/lint.yml' 26 | pull_request: 27 | paths: 28 | - '**.js' 29 | - '.eslint*' 30 | - '.github/workflow/lint.yml' 31 | 32 | jobs: 33 | test: 34 | name: Lint Test 35 | runs-on: ubuntu-latest 36 | env: 37 | node-version: 20 38 | 39 | steps: 40 | - uses: actions/checkout@v4 41 | - uses: actions/setup-node@v4 42 | with: 43 | node-version: ${{ env.node-version }} 44 | 45 | - name: Run Environment Information 46 | run: | 47 | node --version 48 | npm --version 49 | 50 | - name: Run npm install 51 | run: | 52 | npm ci 53 | 54 | - name: Run lint test 55 | run: | 56 | npm run lint 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #If ignorance is bliss, then somebody knock the smile off my face 2 | 3 | *.csproj.user 4 | *.suo 5 | *.cache 6 | Thumbs.db 7 | *.DS_Store 8 | 9 | *.bak 10 | *.cache 11 | *.log 12 | *.swp 13 | *.user 14 | 15 | /.project 16 | node_modules 17 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true 3 | , "devel": true 4 | , "bitwise": true 5 | , "undef": true 6 | , "trailing": true 7 | , "quotmark": false 8 | , "indent": 4 9 | , "unused": "vars" 10 | , "latedef": "nofunc" 11 | , "globals": { 12 | "module": false, 13 | "exports": false, 14 | "require": false, 15 | "cordova": false, 16 | "File": true, 17 | "FileSystem": true, 18 | "FileReader": true, 19 | "FileWriter": true, 20 | "FileError": true, 21 | "LocalFileSystem": true, 22 | "Metadata": true, 23 | "Flags": true, 24 | "DirectoryEntry": true, 25 | "resolveLocalFileSystemURL": false, 26 | "requestFileSystem": true, 27 | "FILESYSTEM_PREFIX": true, 28 | "FILESYSTEM_PROTOCOL": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | tests 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org 2 | 3 | -------------------------------------------------------------------------------- /.ratignore: -------------------------------------------------------------------------------- 1 | asset-test.txt 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | # Contributing to Apache Cordova 23 | 24 | Anyone can contribute to Cordova. And we need your contributions. 25 | 26 | There are multiple ways to contribute: report bugs, improve the docs, and 27 | contribute code. 28 | 29 | For instructions on this, start with the 30 | [contribution overview](http://cordova.apache.org/contribute/). 31 | 32 | The details are explained there, but the important items are: 33 | - Check for Github issues that corresponds to your contribution and link or create them if necessary. 34 | - Run the tests so your patch doesn't break existing functionality. 35 | 36 | We look forward to your contributions! 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache Cordova 2 | Copyright 2012 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /doc/plugins.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | Notes for plugin developers 21 | =========================== 22 | 23 | These notes are primarily intended for Android and iOS developers who want to write plugins which interface with the file system using the File plugin. 24 | 25 | Working with Cordova file system URLs 26 | ------------------------------------- 27 | 28 | Since version 1.0.0, this plugin has used URLs with a `cdvfile` scheme for all communication over the bridge, rather than exposing raw device file system paths to JavaScript. 29 | 30 | On the JavaScript side, this means that FileEntry and DirectoryEntry objects have a fullPath attribute which is relative to the root of the HTML file system. If your plugin's JavaScript API accepts a FileEntry or DirectoryEntry object, you should call `.toURL()` on that object before passing it across the bridge to native code. 31 | 32 | ### Converting cdvfile:// URLs to fileystem paths 33 | 34 | Plugins which need to write to the filesystem may want to convert a received file system URL to an actual filesystem location. There are multiple ways of doing this, depending on the native platform. 35 | 36 | It is important to remember that not all `cdvfile://` URLs are mappable to real files on the device. Some URLs can refer to assets on device which are not represented by files, or can even refer to remote resources. Because of these possibilities, plugins should always test whether they get a meaningful result back when trying to convert URLs to paths. 37 | 38 | #### Android 39 | 40 | On Android, the simplest method to convert a `cdvfile://` URL to a filesystem path is to use `org.apache.cordova.CordovaResourceApi`. `CordovaResourceApi` has several methods which can handle `cdvfile://` URLs: 41 | 42 | // webView is a member of the Plugin class 43 | CordovaResourceApi resourceApi = webView.getResourceApi(); 44 | 45 | // Obtain a file:/// URL representing this file on the device, 46 | // or the same URL unchanged if it cannot be mapped to a file 47 | Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL)); 48 | 49 | It is also possible to use the File plugin directly: 50 | 51 | import org.apache.cordova.file.FileUtils; 52 | import org.apache.cordova.file.FileSystem; 53 | import java.net.MalformedURLException; 54 | 55 | // Get the File plugin from the plugin manager 56 | FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File"); 57 | 58 | // Given a URL, get a path for it 59 | try { 60 | String path = filePlugin.filesystemPathForURL(cdvfileURL); 61 | } catch (MalformedURLException e) { 62 | // The filesystem url wasn't recognized 63 | } 64 | 65 | To convert from a path to a `cdvfile://` URL: 66 | 67 | import org.apache.cordova.file.LocalFilesystemURL; 68 | 69 | // Get a LocalFilesystemURL object for a device path, 70 | // or null if it cannot be represented as a cdvfile URL. 71 | LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path); 72 | // Get the string representation of the URL object 73 | String cdvfileURL = url.toString(); 74 | 75 | If your plugin creates a file, and you want to return a FileEntry object for it, use the File plugin: 76 | 77 | // Return a JSON structure suitable for returning to JavaScript, 78 | // or null if this file is not representable as a cdvfile URL. 79 | JSONObject entry = filePlugin.getEntryForFile(file); 80 | 81 | #### iOS 82 | 83 | Cordova on iOS does not use the same `CordovaResourceApi` concept as Android. On iOS, you should use the File plugin to convert between URLs and filesystem paths. 84 | 85 | // Get a CDVFilesystem URL object from a URL string 86 | CDVFilesystemURL* url = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL]; 87 | // Get a path for the URL object, or nil if it cannot be mapped to a file 88 | NSString* path = [filePlugin filesystemPathForURL:url]; 89 | 90 | 91 | // Get a CDVFilesystem URL object for a device path, or 92 | // nil if it cannot be represented as a cdvfile URL. 93 | CDVFilesystemURL* url = [filePlugin fileSystemURLforLocalPath:path]; 94 | // Get the string representation of the URL object 95 | NSString* cdvfileURL = [url absoluteString]; 96 | 97 | If your plugin creates a file, and you want to return a FileEntry object for it, use the File plugin: 98 | 99 | // Get a CDVFilesystem URL object for a device path, or 100 | // nil if it cannot be represented as a cdvfile URL. 101 | CDVFilesystemURL* url = [filePlugin fileSystemURLforLocalPath:path]; 102 | // Get a structure to return to JavaScript 103 | NSDictionary* entry = [filePlugin makeEntryForLocalURL:url] 104 | 105 | #### JavaScript 106 | 107 | In JavaScript, to get a `cdvfile://` URL from a FileEntry or DirectoryEntry object, simply call `.toURL()` on it: 108 | 109 | var cdvfileURL = entry.toURL(); 110 | 111 | In plugin response handlers, to convert from a returned FileEntry structure to an actual Entry object, your handler code should import the File plugin and create a new object: 112 | 113 | // create appropriate Entry object 114 | var entry; 115 | if (entryStruct.isDirectory) { 116 | entry = new DirectoryEntry(entryStruct.name, entryStruct.fullPath, new FileSystem(entryStruct.filesystemName)); 117 | } else { 118 | entry = new FileEntry(entryStruct.name, entryStruct.fullPath, new FileSystem(entryStruct.filesystemName)); 119 | } 120 | 121 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-file", 3 | "version": "8.1.4-dev", 4 | "description": "Cordova File Plugin", 5 | "types": "./types/index.d.ts", 6 | "cordova": { 7 | "id": "cordova-plugin-file", 8 | "platforms": [ 9 | "android", 10 | "browser", 11 | "ios", 12 | "osx", 13 | "windows" 14 | ] 15 | }, 16 | "repository": "github:apache/cordova-plugin-file", 17 | "bugs": "https://github.com/apache/cordova-plugin-file/issues", 18 | "keywords": [ 19 | "cordova", 20 | "file", 21 | "ecosystem:cordova", 22 | "cordova-android", 23 | "cordova-browser", 24 | "cordova-ios", 25 | "cordova-osx", 26 | "cordova-windows" 27 | ], 28 | "scripts": { 29 | "test": "npm run lint", 30 | "lint": "eslint ." 31 | }, 32 | "author": "Apache Software Foundation", 33 | "license": "Apache-2.0", 34 | "engines": { 35 | "cordovaDependencies": { 36 | "5.0.0": { 37 | "cordova-android": ">=6.3.0" 38 | }, 39 | "7.0.0": { 40 | "cordova-android": ">=10.0.0" 41 | }, 42 | "8.0.0": { 43 | "cordova-android": ">=12.0.0" 44 | }, 45 | "9.0.0": { 46 | "cordova": ">100" 47 | } 48 | } 49 | }, 50 | "devDependencies": { 51 | "@cordova/eslint-config": "^5.0.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 25 | File 26 | Cordova File Plugin 27 | Apache 2.0 28 | cordova,file 29 | https://github.com/apache/cordova-plugin-file 30 | https://github.com/apache/cordova-plugin-file/issues 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | The Android Persistent storage location now defaults to "Internal". Please check this plugin's README to see if your application needs any changes in its config.xml. 119 | 120 | If this is a new application no changes are required. 121 | 122 | If this is an update to an existing application that did not specify an "AndroidPersistentFileLocation" you may need to add: 123 | 124 | "<preference name="AndroidPersistentFileLocation" value="Compatibility" />" 125 | 126 | to config.xml in order for the application to find previously stored files. 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | -------------------------------------------------------------------------------- /src/android/ContentFilesystem.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.file; 20 | 21 | import android.content.ContentResolver; 22 | import android.content.Context; 23 | import android.database.Cursor; 24 | import android.net.Uri; 25 | import android.provider.DocumentsContract; 26 | import android.provider.MediaStore; 27 | import android.provider.OpenableColumns; 28 | import java.io.File; 29 | import java.io.FileNotFoundException; 30 | import java.io.IOException; 31 | 32 | import org.apache.cordova.CordovaPreferences; 33 | import org.apache.cordova.CordovaResourceApi; 34 | import org.json.JSONException; 35 | import org.json.JSONObject; 36 | 37 | public class ContentFilesystem extends Filesystem { 38 | 39 | private final Context context; 40 | 41 | public ContentFilesystem(Context context, CordovaResourceApi resourceApi, CordovaPreferences preferences) { 42 | super(Uri.parse("content://"), "content", resourceApi, preferences); 43 | this.context = context; 44 | } 45 | 46 | @Override 47 | public Uri toNativeUri(LocalFilesystemURL inputURL) { 48 | String encodedPath = inputURL.uri.getEncodedPath(); 49 | String authorityAndPath = encodedPath.substring(encodedPath.indexOf(this.name) + 1 + this.name.length() + 2); 50 | if (authorityAndPath.length() < 2) { 51 | return null; 52 | } 53 | String ret = "content://" + authorityAndPath; 54 | String query = inputURL.uri.getEncodedQuery(); 55 | if (query != null) { 56 | ret += '?' + query; 57 | } 58 | String frag = inputURL.uri.getEncodedFragment(); 59 | if (frag != null) { 60 | ret += '#' + frag; 61 | } 62 | return Uri.parse(ret); 63 | } 64 | 65 | @Override 66 | public LocalFilesystemURL toLocalUri(Uri inputURL) { 67 | if (!"content".equals(inputURL.getScheme())) { 68 | return null; 69 | } 70 | String subPath = inputURL.getEncodedPath(); 71 | if (subPath.length() > 0) { 72 | subPath = subPath.substring(1); 73 | } 74 | 75 | Uri.Builder b = createLocalUriBuilder().appendPath(inputURL.getAuthority()); 76 | 77 | if (subPath.length() > 0) { 78 | b.appendEncodedPath(subPath); 79 | } 80 | Uri localUri = b.encodedQuery(inputURL.getEncodedQuery()) 81 | .encodedFragment(inputURL.getEncodedFragment()) 82 | .build(); 83 | return LocalFilesystemURL.parse(localUri); 84 | } 85 | 86 | @Override 87 | public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, 88 | String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException { 89 | throw new UnsupportedOperationException("getFile() not supported for content:. Use resolveLocalFileSystemURL instead."); 90 | } 91 | 92 | @Override 93 | public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) 94 | throws NoModificationAllowedException { 95 | Uri contentUri = toNativeUri(inputURL); 96 | try { 97 | context.getContentResolver().delete(contentUri, null, null); 98 | } catch (UnsupportedOperationException t) { 99 | // Was seeing this on the File mobile-spec tests on 4.0.3 x86 emulator. 100 | // The ContentResolver applies only when the file was registered in the 101 | // first case, which is generally only the case with images. 102 | NoModificationAllowedException nmae = new NoModificationAllowedException("Deleting not supported for content uri: " + contentUri); 103 | nmae.initCause(t); 104 | throw nmae; 105 | } 106 | return true; 107 | } 108 | 109 | @Override 110 | public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) 111 | throws NoModificationAllowedException { 112 | throw new NoModificationAllowedException("Cannot remove content url"); 113 | } 114 | 115 | @Override 116 | public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException { 117 | throw new UnsupportedOperationException("readEntriesAtLocalURL() not supported for content:. Use resolveLocalFileSystemURL instead."); 118 | } 119 | 120 | @Override 121 | public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException { 122 | long size = -1; 123 | long lastModified = 0; 124 | Uri nativeUri = toNativeUri(inputURL); 125 | String mimeType = resourceApi.getMimeType(nativeUri); 126 | Cursor cursor = openCursorForURL(nativeUri); 127 | try { 128 | if (cursor != null && cursor.moveToFirst()) { 129 | Long sizeForCursor = resourceSizeForCursor(cursor); 130 | if (sizeForCursor != null) { 131 | size = sizeForCursor.longValue(); 132 | } 133 | Long modified = lastModifiedDateForCursor(cursor); 134 | if (modified != null) 135 | lastModified = modified.longValue(); 136 | } else { 137 | // Some content providers don't support cursors at all! 138 | CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(nativeUri); 139 | size = offr.length; 140 | } 141 | } catch (IOException e) { 142 | FileNotFoundException fnfe = new FileNotFoundException(); 143 | fnfe.initCause(e); 144 | throw fnfe; 145 | } finally { 146 | if (cursor != null) 147 | cursor.close(); 148 | } 149 | 150 | JSONObject metadata = new JSONObject(); 151 | try { 152 | metadata.put("size", size); 153 | metadata.put("type", mimeType); 154 | metadata.put("name", name); 155 | metadata.put("fullPath", inputURL.path); 156 | metadata.put("lastModifiedDate", lastModified); 157 | } catch (JSONException e) { 158 | return null; 159 | } 160 | return metadata; 161 | } 162 | 163 | @Override 164 | public long writeToFileAtURL(LocalFilesystemURL inputURL, String data, 165 | int offset, boolean isBinary) throws NoModificationAllowedException { 166 | throw new NoModificationAllowedException("Couldn't write to file given its content URI"); 167 | } 168 | @Override 169 | public long truncateFileAtURL(LocalFilesystemURL inputURL, long size) 170 | throws NoModificationAllowedException { 171 | throw new NoModificationAllowedException("Couldn't truncate file given its content URI"); 172 | } 173 | 174 | protected Cursor openCursorForURL(Uri nativeUri) { 175 | ContentResolver contentResolver = context.getContentResolver(); 176 | try { 177 | return contentResolver.query(nativeUri, null, null, null, null); 178 | } catch (UnsupportedOperationException e) { 179 | return null; 180 | } 181 | } 182 | 183 | private Long resourceSizeForCursor(Cursor cursor) { 184 | int columnIndex = cursor.getColumnIndex(OpenableColumns.SIZE); 185 | if (columnIndex != -1) { 186 | String sizeStr = cursor.getString(columnIndex); 187 | if (sizeStr != null) { 188 | return Long.parseLong(sizeStr); 189 | } 190 | } 191 | return null; 192 | } 193 | 194 | protected Long lastModifiedDateForCursor(Cursor cursor) { 195 | int columnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED); 196 | if (columnIndex == -1) { 197 | columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED); 198 | } 199 | if (columnIndex != -1) { 200 | String dateStr = cursor.getString(columnIndex); 201 | if (dateStr != null) { 202 | return Long.parseLong(dateStr); 203 | } 204 | } 205 | return null; 206 | } 207 | 208 | @Override 209 | public String filesystemPathForURL(LocalFilesystemURL url) { 210 | File f = resourceApi.mapUriToFile(toNativeUri(url)); 211 | return f == null ? null : f.getAbsolutePath(); 212 | } 213 | 214 | @Override 215 | public LocalFilesystemURL URLforFilesystemPath(String path) { 216 | // Returns null as we don't support reverse mapping back to content:// URLs 217 | return null; 218 | } 219 | 220 | @Override 221 | public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) { 222 | return true; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/android/DirectoryManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.file; 20 | 21 | import android.os.Environment; 22 | import android.os.StatFs; 23 | 24 | import java.io.File; 25 | 26 | /** 27 | * This class provides file directory utilities. 28 | * All file operations are performed on the SD card. 29 | * 30 | * It is used by the FileUtils class. 31 | */ 32 | public class DirectoryManager { 33 | 34 | @SuppressWarnings("unused") 35 | private static final String LOG_TAG = "DirectoryManager"; 36 | 37 | /** 38 | * Determine if a file or directory exists. 39 | * @param name The name of the file to check. 40 | * @return T=exists, F=not found 41 | */ 42 | public static boolean testFileExists(String name) { 43 | boolean status; 44 | 45 | // If SD card exists 46 | if ((testSaveLocationExists()) && (!name.equals(""))) { 47 | File path = Environment.getExternalStorageDirectory(); 48 | File newPath = constructFilePaths(path.toString(), name); 49 | status = newPath.exists(); 50 | } 51 | // If no SD card 52 | else { 53 | status = false; 54 | } 55 | return status; 56 | } 57 | 58 | /** 59 | * Get the free space in external storage 60 | * 61 | * @return Size in KB or -1 if not available 62 | */ 63 | public static long getFreeExternalStorageSpace() { 64 | String status = Environment.getExternalStorageState(); 65 | long freeSpaceInBytes = 0; 66 | 67 | // Check if external storage exists 68 | if (status.equals(Environment.MEDIA_MOUNTED)) { 69 | freeSpaceInBytes = getFreeSpaceInBytes(Environment.getExternalStorageDirectory().getPath()); 70 | } else { 71 | // If no external storage then return -1 72 | return -1; 73 | } 74 | 75 | return freeSpaceInBytes / 1024; 76 | } 77 | 78 | /** 79 | * Given a path return the number of free bytes in the filesystem containing the path. 80 | * 81 | * @param path to the file system 82 | * @return free space in bytes 83 | */ 84 | public static long getFreeSpaceInBytes(String path) { 85 | try { 86 | StatFs stat = new StatFs(path); 87 | long blockSize = stat.getBlockSize(); 88 | long availableBlocks = stat.getAvailableBlocks(); 89 | return availableBlocks * blockSize; 90 | } catch (IllegalArgumentException e) { 91 | // The path was invalid. Just return 0 free bytes. 92 | return 0; 93 | } 94 | } 95 | 96 | /** 97 | * Determine if SD card exists. 98 | * 99 | * @return T=exists, F=not found 100 | */ 101 | public static boolean testSaveLocationExists() { 102 | String sDCardStatus = Environment.getExternalStorageState(); 103 | boolean status; 104 | 105 | // If SD card is mounted 106 | if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) { 107 | status = true; 108 | } 109 | 110 | // If no SD card 111 | else { 112 | status = false; 113 | } 114 | return status; 115 | } 116 | 117 | /** 118 | * Create a new file object from two file paths. 119 | * 120 | * @param file1 Base file path 121 | * @param file2 Remaining file path 122 | * @return File object 123 | */ 124 | private static File constructFilePaths (String file1, String file2) { 125 | File newPath; 126 | if (file2.startsWith(file1)) { 127 | newPath = new File(file2); 128 | } 129 | else { 130 | newPath = new File(file1 + "/" + file2); 131 | } 132 | return newPath; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/android/EncodingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.file; 21 | 22 | @SuppressWarnings("serial") 23 | public class EncodingException extends Exception { 24 | 25 | public EncodingException(String message) { 26 | super(message); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/android/FileExistsException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.file; 21 | 22 | @SuppressWarnings("serial") 23 | public class FileExistsException extends Exception { 24 | 25 | public FileExistsException(String msg) { 26 | super(msg); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/android/InvalidModificationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 21 | package org.apache.cordova.file; 22 | 23 | @SuppressWarnings("serial") 24 | public class InvalidModificationException extends Exception { 25 | 26 | public InvalidModificationException(String message) { 27 | super(message); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/android/LocalFilesystemURL.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.file; 20 | 21 | import android.net.Uri; 22 | 23 | public class LocalFilesystemURL { 24 | 25 | public static final String FILESYSTEM_PROTOCOL = "cdvfile"; 26 | public static final String CDVFILE_KEYWORD = "__cdvfile_"; 27 | 28 | public final Uri uri; 29 | public final String fsName; 30 | public final String path; 31 | public final boolean isDirectory; 32 | 33 | private LocalFilesystemURL(Uri uri, String fsName, String fsPath, boolean isDirectory) { 34 | this.uri = uri; 35 | this.fsName = fsName; 36 | this.path = fsPath; 37 | this.isDirectory = isDirectory; 38 | } 39 | 40 | public static LocalFilesystemURL parse(Uri uri) { 41 | if(!uri.toString().contains(CDVFILE_KEYWORD)) { 42 | return null; 43 | } 44 | 45 | String path = uri.getPath(); 46 | if (path.length() < 1) { 47 | return null; 48 | } 49 | 50 | int firstSlashIdx = path.indexOf('/', 1); 51 | if (firstSlashIdx < 0) { 52 | return null; 53 | } 54 | 55 | String fsName = path.substring(1, firstSlashIdx); 56 | fsName = fsName.substring(CDVFILE_KEYWORD.length()); 57 | fsName = fsName.substring(0, fsName.length() - 2); 58 | 59 | path = path.substring(firstSlashIdx); 60 | 61 | boolean isDirectory = path.charAt(path.length() - 1) == '/'; 62 | return new LocalFilesystemURL(uri, fsName, path, isDirectory); 63 | } 64 | 65 | public static LocalFilesystemURL parse(String uri) { 66 | return parse(Uri.parse(uri)); 67 | } 68 | 69 | public static String fsNameToCdvKeyword(String fsName) { return CDVFILE_KEYWORD + fsName + "__"; } 70 | 71 | public String toString() { 72 | return uri.toString(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/android/NoModificationAllowedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.file; 21 | 22 | @SuppressWarnings("serial") 23 | public class NoModificationAllowedException extends Exception { 24 | 25 | public NoModificationAllowedException(String message) { 26 | super(message); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/android/PendingRequests.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.file; 20 | 21 | import android.util.SparseArray; 22 | 23 | import org.apache.cordova.CallbackContext; 24 | 25 | /** 26 | * Holds pending runtime permission requests 27 | */ 28 | class PendingRequests { 29 | private int currentReqId = 0; 30 | private SparseArray requests = new SparseArray(); 31 | 32 | /** 33 | * Creates a request and adds it to the array of pending requests. Each created request gets a 34 | * unique result code for use with requestPermission() 35 | * @param rawArgs The raw arguments passed to the plugin 36 | * @param action The action this request corresponds to (get file, etc.) 37 | * @param callbackContext The CallbackContext for this plugin call 38 | * @return The request code that can be used to retrieve the Request object 39 | */ 40 | public synchronized int createRequest(String rawArgs, int action, CallbackContext callbackContext) { 41 | Request req = new Request(rawArgs, action, callbackContext); 42 | requests.put(req.requestCode, req); 43 | return req.requestCode; 44 | } 45 | 46 | /** 47 | * Gets the request corresponding to this request code and removes it from the pending requests 48 | * @param requestCode The request code for the desired request 49 | * @return The request corresponding to the given request code or null if such a 50 | * request is not found 51 | */ 52 | public synchronized Request getAndRemove(int requestCode) { 53 | Request result = requests.get(requestCode); 54 | requests.remove(requestCode); 55 | return result; 56 | } 57 | 58 | /** 59 | * Holds the options and CallbackContext for a call made to the plugin. 60 | */ 61 | public class Request { 62 | 63 | // Unique int used to identify this request in any Android permission callback 64 | private int requestCode; 65 | 66 | // Action to be performed after permission request result 67 | private int action; 68 | 69 | // Raw arguments passed to plugin 70 | private String rawArgs; 71 | 72 | // The callback context for this plugin request 73 | private CallbackContext callbackContext; 74 | 75 | private Request(String rawArgs, int action, CallbackContext callbackContext) { 76 | this.rawArgs = rawArgs; 77 | this.action = action; 78 | this.callbackContext = callbackContext; 79 | this.requestCode = currentReqId ++; 80 | } 81 | 82 | public int getAction() { 83 | return this.action; 84 | } 85 | 86 | public String getRawArgs() { 87 | return rawArgs; 88 | } 89 | 90 | public CallbackContext getCallbackContext() { 91 | return callbackContext; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/android/TypeMismatchException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 21 | package org.apache.cordova.file; 22 | 23 | @SuppressWarnings("serial") 24 | public class TypeMismatchException extends Exception { 25 | 26 | public TypeMismatchException(String message) { 27 | super(message); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/android/build-extras.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | ext.postBuildExtras = { 20 | def inAssetsDir = file("assets") 21 | def outAssetsDir = inAssetsDir 22 | def outFile = new File(outAssetsDir, "cdvasset.manifest") 23 | 24 | def newTask = task("cdvCreateAssetManifest") << { 25 | def contents = new HashMap() 26 | def sizes = new HashMap() 27 | contents[""] = inAssetsDir.list() 28 | def tree = fileTree(dir: inAssetsDir) 29 | tree.visit { fileDetails -> 30 | if (fileDetails.isDirectory()) { 31 | contents[fileDetails.relativePath.toString()] = fileDetails.file.list() 32 | } else { 33 | sizes[fileDetails.relativePath.toString()] = fileDetails.file.length() 34 | } 35 | } 36 | 37 | outAssetsDir.mkdirs() 38 | outFile.withObjectOutputStream { oos -> 39 | oos.writeObject(contents) 40 | oos.writeObject(sizes) 41 | } 42 | } 43 | newTask.inputs.dir inAssetsDir 44 | newTask.outputs.file outFile 45 | def preBuildTask = tasks["preBuild"] 46 | preBuildTask.dependsOn(newTask) 47 | } 48 | -------------------------------------------------------------------------------- /src/ios/CDVAssetLibraryFilesystem.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import "CDVFile.h" 21 | 22 | extern NSString* const kCDVAssetsLibraryPrefix; 23 | extern NSString* const kCDVAssetsLibraryScheme; 24 | 25 | @interface CDVAssetLibraryFilesystem : NSObject { 26 | } 27 | 28 | - (id) initWithName:(NSString *)name; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /src/ios/CDVAssetLibraryFilesystem.m: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import "CDVFile.h" 21 | #import "CDVAssetLibraryFilesystem.h" 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | 28 | NSString* const kCDVAssetsLibraryPrefix = @"assets-library://"; 29 | NSString* const kCDVAssetsLibraryScheme = @"assets-library"; 30 | 31 | @implementation CDVAssetLibraryFilesystem 32 | @synthesize name=_name, urlTransformer; 33 | 34 | 35 | /* 36 | The CDVAssetLibraryFilesystem works with resources which are identified 37 | by iOS as 38 | asset-library:// 39 | and represents them internally as URLs of the form 40 | cdvfile://localhost/assets-library/ 41 | */ 42 | 43 | - (NSURL *)assetLibraryURLForLocalURL:(CDVFilesystemURL *)url 44 | { 45 | if ([url.url.scheme isEqualToString:kCDVFilesystemURLPrefix]) { 46 | NSString *path = [[url.url absoluteString] substringFromIndex:[@"cdvfile://localhost/assets-library" length]]; 47 | return [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@", path]]; 48 | } 49 | return url.url; 50 | } 51 | 52 | - (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url 53 | { 54 | NSDictionary* entry = [self makeEntryForLocalURL:url]; 55 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry]; 56 | } 57 | 58 | - (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url { 59 | return [self makeEntryForPath:url.fullPath isDirectory:NO]; 60 | } 61 | 62 | - (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir 63 | { 64 | NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5]; 65 | NSString* lastPart = [fullPath lastPathComponent]; 66 | if (isDir && ![fullPath hasSuffix:@"/"]) { 67 | fullPath = [fullPath stringByAppendingString:@"/"]; 68 | } 69 | [dirEntry setObject:[NSNumber numberWithBool:!isDir] forKey:@"isFile"]; 70 | [dirEntry setObject:[NSNumber numberWithBool:isDir] forKey:@"isDirectory"]; 71 | [dirEntry setObject:fullPath forKey:@"fullPath"]; 72 | [dirEntry setObject:lastPart forKey:@"name"]; 73 | [dirEntry setObject:self.name forKey: @"filesystemName"]; 74 | 75 | NSURL* nativeURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@",fullPath]]; 76 | if (self.urlTransformer) { 77 | nativeURL = self.urlTransformer(nativeURL); 78 | } 79 | dirEntry[@"nativeURL"] = [nativeURL absoluteString]; 80 | 81 | return dirEntry; 82 | } 83 | 84 | /* helper function to get the mimeType from the file extension 85 | * IN: 86 | * NSString* fullPath - filename (may include path) 87 | * OUT: 88 | * NSString* the mime type as type/subtype. nil if not able to determine 89 | */ 90 | + (NSString*)getMimeTypeFromPath:(NSString*)fullPath 91 | { 92 | NSString* mimeType = nil; 93 | 94 | if (fullPath) { 95 | CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL); 96 | if (typeId) { 97 | mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType); 98 | if (!mimeType) { 99 | // special case for m4a 100 | if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) { 101 | mimeType = @"audio/mp4"; 102 | } else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) { 103 | mimeType = @"audio/wav"; 104 | } else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) { 105 | mimeType = @"text/css"; 106 | } 107 | } 108 | CFRelease(typeId); 109 | } 110 | } 111 | return mimeType; 112 | } 113 | 114 | - (id)initWithName:(NSString *)name 115 | { 116 | if (self) { 117 | self.name = name; 118 | } 119 | return self; 120 | } 121 | 122 | - (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options 123 | { 124 | // return unsupported result for assets-library URLs 125 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"getFile not supported for assets-library URLs."]; 126 | } 127 | 128 | - (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI 129 | { 130 | // we don't (yet?) support getting the parent of an asset 131 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR]; 132 | } 133 | 134 | - (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options 135 | { 136 | // setMetadata doesn't make sense for asset library files 137 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 138 | } 139 | 140 | - (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI 141 | { 142 | // return error for assets-library URLs 143 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR]; 144 | } 145 | 146 | - (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI 147 | { 148 | // return error for assets-library URLs 149 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"removeRecursively not supported for assets-library URLs."]; 150 | } 151 | 152 | - (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI 153 | { 154 | // return unsupported result for assets-library URLs 155 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"readEntries not supported for assets-library URLs."]; 156 | } 157 | 158 | - (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos 159 | { 160 | // assets-library files can't be truncated 161 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR]; 162 | } 163 | 164 | - (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend 165 | { 166 | // text can't be written into assets-library files 167 | return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR]; 168 | } 169 | 170 | - (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback 171 | { 172 | // Copying to an assets library file is not doable, since we can't write it. 173 | CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR]; 174 | callback(result); 175 | } 176 | 177 | - (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url 178 | { 179 | NSString *path = nil; 180 | if ([[url.url scheme] isEqualToString:kCDVAssetsLibraryScheme]) { 181 | path = [url.url path]; 182 | } else { 183 | path = url.fullPath; 184 | } 185 | if ([path hasSuffix:@"/"]) { 186 | path = [path substringToIndex:([path length]-1)]; 187 | } 188 | return path; 189 | } 190 | 191 | - (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback 192 | { 193 | ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) { 194 | if (asset) { 195 | // We have the asset! Get the data and send it off. 196 | ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation]; 197 | NSUInteger size = (end > start) ? (end - start) : [assetRepresentation size]; 198 | Byte* buffer = (Byte*)malloc(size); 199 | NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:start length:size error:nil]; 200 | NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES]; 201 | NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType); 202 | 203 | callback(data, MIMEType, NO_ERROR); 204 | } else { 205 | callback(nil, nil, NOT_FOUND_ERR); 206 | } 207 | }; 208 | 209 | ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { 210 | // Retrieving the asset failed for some reason. Send the appropriate error. 211 | NSLog(@"Error: %@", error); 212 | callback(nil, nil, SECURITY_ERR); 213 | }; 214 | 215 | ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; 216 | [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock]; 217 | } 218 | 219 | - (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback 220 | { 221 | // In this case, we need to use an asynchronous method to retrieve the file. 222 | // Because of this, we can't just assign to `result` and send it at the end of the method. 223 | // Instead, we return after calling the asynchronous method and send `result` in each of the blocks. 224 | ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) { 225 | if (asset) { 226 | // We have the asset! Populate the dictionary and send it off. 227 | NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5]; 228 | ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation]; 229 | [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:[assetRepresentation size]] forKey:@"size"]; 230 | [fileInfo setObject:localURL.fullPath forKey:@"fullPath"]; 231 | NSString* filename = [assetRepresentation filename]; 232 | [fileInfo setObject:filename forKey:@"name"]; 233 | [fileInfo setObject:[CDVAssetLibraryFilesystem getMimeTypeFromPath:filename] forKey:@"type"]; 234 | NSDate* creationDate = [asset valueForProperty:ALAssetPropertyDate]; 235 | NSNumber* msDate = [NSNumber numberWithDouble:[creationDate timeIntervalSince1970] * 1000]; 236 | [fileInfo setObject:msDate forKey:@"lastModifiedDate"]; 237 | 238 | callback([CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]); 239 | } else { 240 | // We couldn't find the asset. Send the appropriate error. 241 | callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]); 242 | } 243 | }; 244 | ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { 245 | // Retrieving the asset failed for some reason. Send the appropriate error. 246 | callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]); 247 | }; 248 | 249 | ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; 250 | [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock]; 251 | return; 252 | } 253 | @end 254 | -------------------------------------------------------------------------------- /src/ios/CDVFile.bundle/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | NSPrivacyTracking 24 | 25 | NSPrivacyTrackingDomains 26 | 27 | NSPrivacyAccessedAPITypes 28 | 29 | 30 | NSPrivacyAccessedAPIType 31 | NSPrivacyAccessedAPICategoryDiskSpace 32 | NSPrivacyAccessedAPITypeReasons 33 | 34 | E174.1 35 | 36 | 37 | 38 | NSPrivacyAccessedAPIType 39 | NSPrivacyAccessedAPICategoryFileTimestamp 40 | NSPrivacyAccessedAPITypeReasons 41 | 42 | C617.1 43 | 44 | 45 | 46 | NSPrivacyCollectedDataTypes 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/ios/CDVFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import 21 | #import 22 | 23 | extern NSString* const kCDVAssetsLibraryPrefix; 24 | extern NSString* const kCDVFilesystemURLPrefix; 25 | 26 | enum CDVFileError { 27 | NO_ERROR = 0, 28 | NOT_FOUND_ERR = 1, 29 | SECURITY_ERR = 2, 30 | ABORT_ERR = 3, 31 | NOT_READABLE_ERR = 4, 32 | ENCODING_ERR = 5, 33 | NO_MODIFICATION_ALLOWED_ERR = 6, 34 | INVALID_STATE_ERR = 7, 35 | SYNTAX_ERR = 8, 36 | INVALID_MODIFICATION_ERR = 9, 37 | QUOTA_EXCEEDED_ERR = 10, 38 | TYPE_MISMATCH_ERR = 11, 39 | PATH_EXISTS_ERR = 12 40 | }; 41 | typedef int CDVFileError; 42 | 43 | @interface CDVFilesystemURL : NSObject { 44 | NSURL *_url; 45 | NSString *_fileSystemName; 46 | NSString *_fullPath; 47 | } 48 | 49 | - (id) initWithString:(NSString*)strURL; 50 | - (id) initWithURL:(NSURL*)URL; 51 | + (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL; 52 | + (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL; 53 | 54 | - (NSString *)absoluteURL; 55 | 56 | @property (atomic) NSURL *url; 57 | @property (atomic) NSString *fileSystemName; 58 | @property (atomic) NSString *fullPath; 59 | 60 | @end 61 | 62 | @interface CDVFilesystemURLProtocol : NSURLProtocol 63 | @end 64 | 65 | @protocol CDVFileSystem 66 | - (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url; 67 | - (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options; 68 | - (CDVPluginResult *)getParentForURL:(CDVFilesystemURL *)localURI; 69 | - (CDVPluginResult *)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options; 70 | - (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI; 71 | - (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI; 72 | - (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI; 73 | - (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos; 74 | - (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend; 75 | - (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback; 76 | - (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback; 77 | - (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback; 78 | 79 | - (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url; 80 | - (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir; 81 | 82 | @property (nonatomic,strong) NSString *name; 83 | @property (nonatomic, copy) NSURL*(^urlTransformer)(NSURL*); 84 | 85 | @optional 86 | - (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURI; 87 | - (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path; 88 | 89 | @end 90 | 91 | @interface CDVFile : CDVPlugin { 92 | NSString* rootDocsPath; 93 | NSString* appDocsPath; 94 | NSString* appLibraryPath; 95 | NSString* appTempPath; 96 | 97 | NSMutableArray* fileSystems_; 98 | BOOL userHasAllowed; 99 | } 100 | 101 | - (NSNumber*)checkFreeDiskSpace:(NSString*)appPath; 102 | - (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir; 103 | - (NSDictionary *)makeEntryForURL:(NSURL *)URL; 104 | - (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath; 105 | 106 | - (NSObject *)filesystemForURL:(CDVFilesystemURL *)localURL; 107 | 108 | /* Native Registration API */ 109 | - (void)registerFilesystem:(NSObject *)fs; 110 | - (NSObject *)fileSystemByName:(NSString *)fsName; 111 | 112 | /* Exec API */ 113 | - (void)requestFileSystem:(CDVInvokedUrlCommand*)command; 114 | - (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command; 115 | - (void)getDirectory:(CDVInvokedUrlCommand*)command; 116 | - (void)getFile:(CDVInvokedUrlCommand*)command; 117 | - (void)getParent:(CDVInvokedUrlCommand*)command; 118 | - (void)removeRecursively:(CDVInvokedUrlCommand*)command; 119 | - (void)remove:(CDVInvokedUrlCommand*)command; 120 | - (void)copyTo:(CDVInvokedUrlCommand*)command; 121 | - (void)moveTo:(CDVInvokedUrlCommand*)command; 122 | - (void)getFileMetadata:(CDVInvokedUrlCommand*)command; 123 | - (void)readEntries:(CDVInvokedUrlCommand*)command; 124 | - (void)readAsText:(CDVInvokedUrlCommand*)command; 125 | - (void)readAsDataURL:(CDVInvokedUrlCommand*)command; 126 | - (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command; 127 | - (void)write:(CDVInvokedUrlCommand*)command; 128 | - (void)testFileExists:(CDVInvokedUrlCommand*)command; 129 | - (void)testDirectoryExists:(CDVInvokedUrlCommand*)command; 130 | - (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command; 131 | - (void)truncate:(CDVInvokedUrlCommand*)command; 132 | - (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy; 133 | 134 | /* Compatibilty with older File API */ 135 | - (NSString*)getMimeTypeFromPath:(NSString*)fullPath; 136 | - (NSDictionary *)getDirectoryEntry:(NSString *)target isDirectory:(BOOL)bDirRequest; 137 | 138 | /* Conversion between filesystem paths and URLs */ 139 | - (NSString *)filesystemPathForURL:(CDVFilesystemURL *)URL; 140 | 141 | /* Internal methods for testing */ 142 | - (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command; 143 | 144 | @property (nonatomic, strong) NSString* rootDocsPath; 145 | @property (nonatomic, strong) NSString* appDocsPath; 146 | @property (nonatomic, strong) NSString* appLibraryPath; 147 | @property (nonatomic, strong) NSString* appTempPath; 148 | @property (nonatomic, strong) NSString* persistentPath; 149 | @property (nonatomic, strong) NSString* temporaryPath; 150 | @property (nonatomic, strong) NSMutableArray* fileSystems; 151 | 152 | @property BOOL userHasAllowed; 153 | 154 | @end 155 | 156 | #define kW3FileTemporary @"temporary" 157 | #define kW3FilePersistent @"persistent" 158 | -------------------------------------------------------------------------------- /src/ios/CDVLocalFilesystem.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import "CDVFile.h" 21 | 22 | @interface CDVLocalFilesystem : NSObject { 23 | NSString *_name; 24 | NSString *_fsRoot; 25 | } 26 | 27 | - (id) initWithName:(NSString *)name root:(NSString *)fsRoot; 28 | + (NSString*)getMimeTypeFromPath:(NSString*)fullPath; 29 | 30 | @property (nonatomic,strong) NSString *fsRoot; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /src/osx/CDVFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import 21 | #import 22 | 23 | NSString* const kCDVFilesystemURLPrefix; 24 | 25 | /** 26 | * The default filesystems if non are specified. 27 | */ 28 | #define CDV_FILESYSTEMS_DEFAULT @"documents,cache,bundle,root" 29 | 30 | /** 31 | * Preference name of the extra filesystems to be "mounted". the following are supported: 32 | * 'bundle' - mounts the application directory 33 | * 'documents' - mounts the users Documents directory (~/Documents) 34 | * 'root' - mounts the root file system 35 | * 'cache' - mounts the caches directory (~/Library/Caches/ *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback; 89 | - (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback; 90 | - (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback; 91 | 92 | - (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url; 93 | - (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir; 94 | 95 | @property (nonatomic,strong) NSString *name; 96 | @property (nonatomic, copy) NSURL*(^urlTransformer)(NSURL*); 97 | 98 | @optional 99 | - (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURI; 100 | - (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path; 101 | 102 | @end 103 | 104 | @interface CDVFile : CDVPlugin { 105 | NSString* rootDocsPath; 106 | NSString* appDocsPath; 107 | NSString* appLibraryPath; 108 | NSString* appTempPath; 109 | 110 | NSMutableArray* fileSystems_; 111 | BOOL userHasAllowed; 112 | } 113 | 114 | - (NSNumber*)checkFreeDiskSpace:(NSString*)appPath; 115 | - (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir; 116 | - (NSDictionary *)makeEntryForURL:(NSURL *)URL; 117 | - (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath; 118 | 119 | - (NSObject *)filesystemForURL:(CDVFilesystemURL *)localURL; 120 | 121 | /* Native Registration API */ 122 | - (void)registerFilesystem:(NSObject *)fs; 123 | - (NSObject *)fileSystemByName:(NSString *)fsName; 124 | 125 | /* Exec API */ 126 | - (void)requestFileSystem:(CDVInvokedUrlCommand*)command; 127 | - (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command; 128 | - (void)getDirectory:(CDVInvokedUrlCommand*)command; 129 | - (void)getFile:(CDVInvokedUrlCommand*)command; 130 | - (void)getParent:(CDVInvokedUrlCommand*)command; 131 | - (void)removeRecursively:(CDVInvokedUrlCommand*)command; 132 | - (void)remove:(CDVInvokedUrlCommand*)command; 133 | - (void)copyTo:(CDVInvokedUrlCommand*)command; 134 | - (void)moveTo:(CDVInvokedUrlCommand*)command; 135 | - (void)getFileMetadata:(CDVInvokedUrlCommand*)command; 136 | - (void)readEntries:(CDVInvokedUrlCommand*)command; 137 | - (void)readAsText:(CDVInvokedUrlCommand*)command; 138 | - (void)readAsDataURL:(CDVInvokedUrlCommand*)command; 139 | - (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command; 140 | - (void)write:(CDVInvokedUrlCommand*)command; 141 | - (void)testFileExists:(CDVInvokedUrlCommand*)command; 142 | - (void)testDirectoryExists:(CDVInvokedUrlCommand*)command; 143 | - (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command; 144 | - (void)truncate:(CDVInvokedUrlCommand*)command; 145 | - (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy; 146 | 147 | /* Compatibilty with older File API */ 148 | - (NSString*)getMimeTypeFromPath:(NSString*)fullPath; 149 | - (NSDictionary *)getDirectoryEntry:(NSString *)target isDirectory:(BOOL)bDirRequest; 150 | 151 | /* Conversion between filesystem paths and URLs */ 152 | - (NSString *)filesystemPathForURL:(CDVFilesystemURL *)URL; 153 | 154 | /* Internal methods for testing */ 155 | - (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command; 156 | 157 | /** 158 | * local path of the 'documents' file system (~/Documents) 159 | */ 160 | @property (nonatomic, strong) NSString* appDocsPath; 161 | 162 | /** 163 | * local path of the 'applicationStorageDirectory' file system (~/Library/Application Support/) 164 | */ 165 | @property (nonatomic, strong) NSString* appSupportPath; 166 | 167 | /** 168 | * local path of the 'persistent' file system (~/Library/Application Support//files) 169 | */ 170 | @property (nonatomic, strong) NSString* appDataPath; 171 | 172 | /** 173 | * local path of the 'documents' file system (~/Documents) 174 | */ 175 | @property (nonatomic, strong) NSString* appTempPath; 176 | 177 | /** 178 | * local path of the 'cache' file system (~/Library/Caches/) 179 | */ 180 | @property (nonatomic, strong) NSString* appCachePath; 181 | 182 | /** 183 | * registered file systems 184 | */ 185 | @property (nonatomic, strong) NSMutableArray* fileSystems; 186 | 187 | @property BOOL userHasAllowed; 188 | 189 | @end 190 | -------------------------------------------------------------------------------- /src/osx/CDVLocalFilesystem.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import "CDVFile.h" 21 | 22 | @interface CDVLocalFilesystem : NSObject { 23 | NSString *_name; 24 | NSString *_fsRoot; 25 | } 26 | 27 | - (id) initWithName:(NSString *)name root:(NSString *)fsRoot; 28 | + (NSString*)getMimeTypeFromPath:(NSString*)fullPath; 29 | 30 | @property (nonatomic,strong) NSString *fsRoot; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /tests/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-file-tests", 3 | "version": "8.1.4-dev", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cordova-plugin-file-tests", 9 | "version": "8.1.4-dev", 10 | "license": "Apache-2.0" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-file-tests", 3 | "version": "8.1.4-dev", 4 | "description": "", 5 | "cordova": { 6 | "id": "cordova-plugin-file-tests", 7 | "platforms": [ 8 | "android" 9 | ] 10 | }, 11 | "keywords": [ 12 | "ecosystem:cordova", 13 | "cordova-android" 14 | ], 15 | "author": "", 16 | "license": "Apache-2.0" 17 | } 18 | -------------------------------------------------------------------------------- /tests/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 25 | 26 | Cordova File Plugin Tests 27 | Apache 2.0 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/src/android/TestContentProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.file.test; 20 | 21 | import android.content.ContentProvider; 22 | import android.net.Uri; 23 | import android.content.res.AssetFileDescriptor; 24 | import android.content.res.AssetManager; 25 | 26 | import java.io.File; 27 | import java.io.FileInputStream; 28 | import java.io.FileNotFoundException; 29 | import android.content.ContentValues; 30 | import android.database.Cursor; 31 | import android.os.ParcelFileDescriptor; 32 | 33 | import org.apache.cordova.CordovaResourceApi; 34 | 35 | import java.io.IOException; 36 | import java.util.HashMap; 37 | 38 | public class TestContentProvider extends ContentProvider { 39 | 40 | @Override 41 | public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 42 | String fileName = uri.getQueryParameter("realPath"); 43 | if (fileName == null) { 44 | fileName = uri.getPath(); 45 | } 46 | if (fileName == null || fileName.length() < 1) { 47 | throw new FileNotFoundException(); 48 | } 49 | CordovaResourceApi resourceApi = new CordovaResourceApi(getContext(), null); 50 | try { 51 | File f = File.createTempFile("test-content-provider", ".tmp"); 52 | resourceApi.copyResource(Uri.parse("file:///android_asset" + fileName), Uri.fromFile(f)); 53 | return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY); 54 | } catch (FileNotFoundException e) { 55 | throw e; 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | throw new FileNotFoundException("IO error: " + e.toString()); 59 | } 60 | } 61 | 62 | @Override 63 | public boolean onCreate() { 64 | return false; 65 | } 66 | 67 | @Override 68 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 69 | throw new UnsupportedOperationException(); 70 | } 71 | 72 | @Override 73 | public String getType(Uri uri) { 74 | return "text/html"; 75 | } 76 | 77 | @Override 78 | public Uri insert(Uri uri, ContentValues values) { 79 | throw new UnsupportedOperationException(); 80 | } 81 | 82 | @Override 83 | public int delete(Uri uri, String selection, String[] selectionArgs) { 84 | throw new UnsupportedOperationException(); 85 | } 86 | 87 | @Override 88 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 89 | throw new UnsupportedOperationException(); 90 | } 91 | 92 | 93 | } 94 | -------------------------------------------------------------------------------- /tests/www/fixtures/asset-test/asset-test.txt: -------------------------------------------------------------------------------- 1 | This file is here for testing purposes -------------------------------------------------------------------------------- /www/DirectoryEntry.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | const argscheck = require('cordova/argscheck'); 23 | const utils = require('cordova/utils'); 24 | const exec = require('cordova/exec'); 25 | const Entry = require('./Entry'); 26 | const FileError = require('./FileError'); 27 | const DirectoryReader = require('./DirectoryReader'); 28 | 29 | /** 30 | * An interface representing a directory on the file system. 31 | * 32 | * {boolean} isFile always false (readonly) 33 | * {boolean} isDirectory always true (readonly) 34 | * {DOMString} name of the directory, excluding the path leading to it (readonly) 35 | * {DOMString} fullPath the absolute full path to the directory (readonly) 36 | * {FileSystem} filesystem on which the directory resides (readonly) 37 | */ 38 | const DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) { 39 | // add trailing slash if it is missing 40 | if ((fullPath) && !/\/$/.test(fullPath)) { 41 | fullPath += '/'; 42 | } 43 | // add trailing slash if it is missing 44 | if (nativeURL && !/\/$/.test(nativeURL)) { 45 | nativeURL += '/'; 46 | } 47 | DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL); 48 | }; 49 | 50 | utils.extend(DirectoryEntry, Entry); 51 | 52 | /** 53 | * Creates a new DirectoryReader to read entries from this directory 54 | */ 55 | DirectoryEntry.prototype.createReader = function () { 56 | return new DirectoryReader(this.toInternalURL()); 57 | }; 58 | 59 | /** 60 | * Creates or looks up a directory 61 | * 62 | * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory 63 | * @param {Flags} options to create or exclusively create the directory 64 | * @param {Function} successCallback is called with the new entry 65 | * @param {Function} errorCallback is called with a FileError 66 | */ 67 | DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) { 68 | argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments); 69 | const fs = this.filesystem; 70 | const win = successCallback && function (result) { 71 | const entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL); 72 | successCallback(entry); 73 | }; 74 | const fail = errorCallback && function (code) { 75 | errorCallback(new FileError(code)); 76 | }; 77 | exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]); 78 | }; 79 | 80 | /** 81 | * Deletes a directory and all of it's contents 82 | * 83 | * @param {Function} successCallback is called with no parameters 84 | * @param {Function} errorCallback is called with a FileError 85 | */ 86 | DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) { 87 | argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments); 88 | const fail = errorCallback && function (code) { 89 | errorCallback(new FileError(code)); 90 | }; 91 | exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]); 92 | }; 93 | 94 | /** 95 | * Creates or looks up a file 96 | * 97 | * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file 98 | * @param {Flags} options to create or exclusively create the file 99 | * @param {Function} successCallback is called with the new entry 100 | * @param {Function} errorCallback is called with a FileError 101 | */ 102 | DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) { 103 | argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments); 104 | const fs = this.filesystem; 105 | const win = successCallback && function (result) { 106 | const FileEntry = require('./FileEntry'); 107 | const entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL); 108 | successCallback(entry); 109 | }; 110 | const fail = errorCallback && function (code) { 111 | errorCallback(new FileError(code)); 112 | }; 113 | exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]); 114 | }; 115 | 116 | module.exports = DirectoryEntry; 117 | -------------------------------------------------------------------------------- /www/DirectoryReader.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | const exec = require('cordova/exec'); 23 | const FileError = require('./FileError'); 24 | 25 | /** 26 | * An interface that lists the files and directories in a directory. 27 | */ 28 | function DirectoryReader (localURL) { 29 | this.localURL = localURL || null; 30 | this.hasReadEntries = false; 31 | } 32 | 33 | /** 34 | * Returns a list of entries from a directory. 35 | * 36 | * @param {Function} successCallback is called with a list of entries 37 | * @param {Function} errorCallback is called with a FileError 38 | */ 39 | DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) { 40 | // If we've already read and passed on this directory's entries, return an empty list. 41 | if (this.hasReadEntries) { 42 | successCallback([]); 43 | return; 44 | } 45 | const reader = this; 46 | const win = typeof successCallback !== 'function' 47 | ? null 48 | : function (result) { 49 | const retVal = []; 50 | for (let i = 0; i < result.length; i++) { 51 | let entry = null; 52 | if (result[i].isDirectory) { 53 | entry = new (require('./DirectoryEntry'))(); 54 | } else if (result[i].isFile) { 55 | entry = new (require('./FileEntry'))(); 56 | } 57 | entry.isDirectory = result[i].isDirectory; 58 | entry.isFile = result[i].isFile; 59 | entry.name = result[i].name; 60 | entry.fullPath = result[i].fullPath; 61 | entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName); 62 | entry.nativeURL = result[i].nativeURL; 63 | retVal.push(entry); 64 | } 65 | reader.hasReadEntries = true; 66 | successCallback(retVal); 67 | }; 68 | const fail = typeof errorCallback !== 'function' 69 | ? null 70 | : function (code) { 71 | errorCallback(new FileError(code)); 72 | }; 73 | exec(win, fail, 'File', 'readEntries', [this.localURL]); 74 | }; 75 | 76 | module.exports = DirectoryReader; 77 | -------------------------------------------------------------------------------- /www/Entry.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | const argscheck = require('cordova/argscheck'); 23 | const exec = require('cordova/exec'); 24 | const FileError = require('./FileError'); 25 | const Metadata = require('./Metadata'); 26 | 27 | /** 28 | * Represents a file or directory on the local file system. 29 | * 30 | * @param isFile 31 | * {boolean} true if Entry is a file (readonly) 32 | * @param isDirectory 33 | * {boolean} true if Entry is a directory (readonly) 34 | * @param name 35 | * {DOMString} name of the file or directory, excluding the path 36 | * leading to it (readonly) 37 | * @param fullPath 38 | * {DOMString} the absolute full path to the file or directory 39 | * (readonly) 40 | * @param fileSystem 41 | * {FileSystem} the filesystem on which this entry resides 42 | * (readonly) 43 | * @param nativeURL 44 | * {DOMString} an alternate URL which can be used by native 45 | * webview controls, for example media players. 46 | * (optional, readonly) 47 | */ 48 | function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) { 49 | this.isFile = !!isFile; 50 | this.isDirectory = !!isDirectory; 51 | this.name = name || ''; 52 | this.fullPath = fullPath || ''; 53 | this.filesystem = fileSystem || null; 54 | this.nativeURL = nativeURL || null; 55 | } 56 | 57 | /** 58 | * Look up the metadata of the entry. 59 | * 60 | * @param successCallback 61 | * {Function} is called with a Metadata object 62 | * @param errorCallback 63 | * {Function} is called with a FileError 64 | */ 65 | Entry.prototype.getMetadata = function (successCallback, errorCallback) { 66 | argscheck.checkArgs('FF', 'Entry.getMetadata', arguments); 67 | const success = successCallback && function (entryMetadata) { 68 | const metadata = new Metadata({ 69 | size: entryMetadata.size, 70 | modificationTime: entryMetadata.lastModifiedDate 71 | }); 72 | successCallback(metadata); 73 | }; 74 | const fail = errorCallback && function (code) { 75 | errorCallback(new FileError(code)); 76 | }; 77 | exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]); 78 | }; 79 | 80 | /** 81 | * Set the metadata of the entry. 82 | * 83 | * @param successCallback 84 | * {Function} is called with a Metadata object 85 | * @param errorCallback 86 | * {Function} is called with a FileError 87 | * @param metadataObject 88 | * {Object} keys and values to set 89 | */ 90 | Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) { 91 | argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments); 92 | exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]); 93 | }; 94 | 95 | /** 96 | * Move a file or directory to a new location. 97 | * 98 | * @param parent 99 | * {DirectoryEntry} the directory to which to move this entry 100 | * @param newName 101 | * {DOMString} new name of the entry, defaults to the current name 102 | * @param successCallback 103 | * {Function} called with the new DirectoryEntry object 104 | * @param errorCallback 105 | * {Function} called with a FileError 106 | */ 107 | Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) { 108 | argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments); 109 | const fail = errorCallback && function (code) { 110 | errorCallback(new FileError(code)); 111 | }; 112 | const srcURL = this.toInternalURL(); 113 | // entry name 114 | const name = newName || this.name; 115 | const success = function (entry) { 116 | if (entry) { 117 | if (successCallback) { 118 | // create appropriate Entry object 119 | const newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name); 120 | const fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); 121 | const result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL); 122 | successCallback(result); 123 | } 124 | } else { 125 | // no Entry object returned 126 | if (fail) { 127 | fail(FileError.NOT_FOUND_ERR); 128 | } 129 | } 130 | }; 131 | 132 | // copy 133 | exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]); 134 | }; 135 | 136 | /** 137 | * Copy a directory to a different location. 138 | * 139 | * @param parent 140 | * {DirectoryEntry} the directory to which to copy the entry 141 | * @param newName 142 | * {DOMString} new name of the entry, defaults to the current name 143 | * @param successCallback 144 | * {Function} called with the new Entry object 145 | * @param errorCallback 146 | * {Function} called with a FileError 147 | */ 148 | Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) { 149 | argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments); 150 | const fail = errorCallback && function (code) { 151 | errorCallback(new FileError(code)); 152 | }; 153 | const srcURL = this.toInternalURL(); 154 | // entry name 155 | const name = newName || this.name; 156 | // success callback 157 | const success = function (entry) { 158 | if (entry) { 159 | if (successCallback) { 160 | // create appropriate Entry object 161 | const newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name); 162 | const fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); 163 | const result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL); 164 | successCallback(result); 165 | } 166 | } else { 167 | // no Entry object returned 168 | if (fail) { 169 | fail(FileError.NOT_FOUND_ERR); 170 | } 171 | } 172 | }; 173 | 174 | // copy 175 | exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]); 176 | }; 177 | 178 | /** 179 | * Return a URL that can be passed across the bridge to identify this entry. 180 | */ 181 | Entry.prototype.toInternalURL = function () { 182 | if (this.filesystem && this.filesystem.__format__) { 183 | return this.filesystem.__format__(this.fullPath, this.nativeURL); 184 | } 185 | }; 186 | 187 | /** 188 | * Return a URL that can be used to identify this entry. 189 | * Use a URL that can be used to as the src attribute of a