@@ -20,16 +20,23 @@ Licensed to the Apache Software Foundation (ASF) under one
2020
2121import android .Manifest ;
2222import android .app .Activity ;
23+ import android .content .ContentResolver ;
2324import android .content .Context ;
2425import android .content .pm .PackageManager ;
2526import android .net .Uri ;
2627import android .os .Build ;
2728import android .os .Environment ;
2829import android .util .Base64 ;
30+ import android .util .Log ;
31+ import android .webkit .MimeTypeMap ;
32+ import android .webkit .WebResourceResponse ;
33+
34+ import androidx .webkit .WebViewAssetLoader ;
2935
3036import org .apache .cordova .CallbackContext ;
3137import org .apache .cordova .CordovaInterface ;
3238import org .apache .cordova .CordovaPlugin ;
39+ import org .apache .cordova .CordovaPluginPathHandler ;
3340import org .apache .cordova .CordovaWebView ;
3441import org .apache .cordova .LOG ;
3542import org .apache .cordova .PermissionHelper ;
@@ -39,12 +46,16 @@ Licensed to the Apache Software Foundation (ASF) under one
3946import org .json .JSONException ;
4047import org .json .JSONObject ;
4148
49+ import java .io .BufferedInputStream ;
4250import java .io .ByteArrayOutputStream ;
4351import java .io .File ;
52+ import java .io .FileInputStream ;
4453import java .io .FileNotFoundException ;
4554import java .io .IOException ;
4655import java .io .InputStream ;
56+ import java .net .HttpURLConnection ;
4757import java .net .MalformedURLException ;
58+ import java .net .URL ;
4859import java .security .Permission ;
4960import java .util .ArrayList ;
5061import java .util .HashMap ;
@@ -87,8 +98,6 @@ public class FileUtils extends CordovaPlugin {
8798
8899 private PendingRequests pendingRequests ;
89100
90-
91-
92101 /*
93102 * We need both read and write when accessing the storage, I think.
94103 */
@@ -136,10 +145,10 @@ protected void registerExtraFileSystems(String[] filesystems, HashMap<String, St
136145 if (fsRoot != null ) {
137146 File newRoot = new File (fsRoot );
138147 if (newRoot .mkdirs () || newRoot .isDirectory ()) {
139- registerFilesystem (new LocalFilesystem (fsName , webView .getContext (), webView .getResourceApi (), newRoot ));
148+ registerFilesystem (new LocalFilesystem (fsName , webView .getContext (), webView .getResourceApi (), newRoot , preferences ));
140149 installedFileSystems .add (fsName );
141150 } else {
142- LOG .d (LOG_TAG , "Unable to create root dir for filesystem \" " + fsName + "\" , skipping" );
151+ LOG .d (LOG_TAG , "Unable to create root dir for filesystem \" " + fsName + "\" , skipping" );
143152 }
144153 } else {
145154 LOG .d (LOG_TAG , "Unrecognized extra filesystem identifier: " + fsName );
@@ -217,10 +226,10 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
217226 // Note: The temporary and persistent filesystems need to be the first two
218227 // registered, so that they will match window.TEMPORARY and window.PERSISTENT,
219228 // per spec.
220- this .registerFilesystem (new LocalFilesystem ("temporary" , webView .getContext (), webView .getResourceApi (), tmpRootFile ));
221- this .registerFilesystem (new LocalFilesystem ("persistent" , webView .getContext (), webView .getResourceApi (), persistentRootFile ));
222- this .registerFilesystem (new ContentFilesystem (webView .getContext (), webView .getResourceApi ()));
223- this .registerFilesystem (new AssetFilesystem (webView .getContext ().getAssets (), webView .getResourceApi ()));
229+ this .registerFilesystem (new LocalFilesystem ("temporary" , webView .getContext (), webView .getResourceApi (), tmpRootFile , preferences ));
230+ this .registerFilesystem (new LocalFilesystem ("persistent" , webView .getContext (), webView .getResourceApi (), persistentRootFile , preferences ));
231+ this .registerFilesystem (new ContentFilesystem (webView .getContext (), webView .getResourceApi (), preferences ));
232+ this .registerFilesystem (new AssetFilesystem (webView .getContext ().getAssets (), webView .getResourceApi (), preferences ));
224233
225234 registerExtraFileSystems (getExtraFileSystemsPreference (activity ), getAvailableFileSystems (activity ));
226235
@@ -249,13 +258,15 @@ public Uri remapUri(Uri uri) {
249258 if (!LocalFilesystemURL .FILESYSTEM_PROTOCOL .equals (uri .getScheme ())) {
250259 return null ;
251260 }
261+
252262 try {
253263 LocalFilesystemURL inputURL = LocalFilesystemURL .parse (uri );
254264 Filesystem fs = this .filesystemForURL (inputURL );
255265 if (fs == null ) {
256266 return null ;
257267 }
258268 String path = fs .filesystemPathForURL (inputURL );
269+
259270 if (path != null ) {
260271 return Uri .parse ("file://" + fs .filesystemPathForURL (inputURL ));
261272 }
@@ -270,6 +281,7 @@ public boolean execute(String action, final String rawArgs, final CallbackContex
270281 callbackContext .sendPluginResult (new PluginResult (PluginResult .Status .ERROR , "File plugin is not configured. Please see the README.md file for details on how to update config.xml" ));
271282 return true ;
272283 }
284+
273285 if (action .equals ("testSaveLocationExists" )) {
274286 threadhelper (new FileOp () {
275287 public void run (JSONArray args ) {
@@ -459,18 +471,24 @@ else if (action.equals("getFile")) {
459471 public void run (JSONArray args ) throws FileExistsException , IOException , TypeMismatchException , EncodingException , JSONException {
460472 String dirname = args .getString (0 );
461473 String path = args .getString (1 );
462- String nativeURL = resolveLocalFileSystemURI (dirname ).getString ("nativeURL" );
463- boolean containsCreate = (args .isNull (2 )) ? false : args .getJSONObject (2 ).optBoolean ("create" , false );
464474
465- if (containsCreate && needPermission (nativeURL , WRITE )) {
466- getWritePermission (rawArgs , ACTION_GET_FILE , callbackContext );
467- }
468- else if (!containsCreate && needPermission (nativeURL , READ )) {
469- getReadPermission (rawArgs , ACTION_GET_FILE , callbackContext );
470- }
471- else {
475+ if (dirname .contains (LocalFilesystemURL .CDVFILE_KEYWORD ) == true ) {
472476 JSONObject obj = getFile (dirname , path , args .optJSONObject (2 ), false );
473477 callbackContext .success (obj );
478+ } else {
479+ String nativeURL = resolveLocalFileSystemURI (dirname ).getString ("nativeURL" );
480+ boolean containsCreate = (args .isNull (2 )) ? false : args .getJSONObject (2 ).optBoolean ("create" , false );
481+
482+ if (containsCreate && needPermission (nativeURL , WRITE )) {
483+ getWritePermission (rawArgs , ACTION_GET_FILE , callbackContext );
484+ }
485+ else if (!containsCreate && needPermission (nativeURL , READ )) {
486+ getReadPermission (rawArgs , ACTION_GET_FILE , callbackContext );
487+ }
488+ else {
489+ JSONObject obj = getFile (dirname , path , args .optJSONObject (2 ), false );
490+ callbackContext .success (obj );
491+ }
474492 }
475493 }
476494 }, rawArgs , callbackContext );
@@ -878,6 +896,7 @@ private boolean remove(String baseURLstr) throws NoModificationAllowedException,
878896 private JSONObject getFile (String baseURLstr , String path , JSONObject options , boolean directory ) throws FileExistsException , IOException , TypeMismatchException , EncodingException , JSONException {
879897 try {
880898 LocalFilesystemURL inputURL = LocalFilesystemURL .parse (baseURLstr );
899+
881900 Filesystem fs = this .filesystemForURL (inputURL );
882901 if (fs == null ) {
883902 throw new MalformedURLException ("No installed handlers for this URL" );
@@ -1222,4 +1241,68 @@ public void run(JSONArray args) throws JSONException, FileNotFoundException, IOE
12221241 LOG .d (LOG_TAG , "Received permission callback for unknown request code" );
12231242 }
12241243 }
1244+
1245+ private String getMimeType (Uri uri ) {
1246+ String fileExtensionFromUrl = MimeTypeMap .getFileExtensionFromUrl (uri .toString ()).toLowerCase ();
1247+ return MimeTypeMap .getSingleton ().getMimeTypeFromExtension (fileExtensionFromUrl );
1248+ }
1249+
1250+ public CordovaPluginPathHandler getPathHandler () {
1251+ WebViewAssetLoader .PathHandler pathHandler = path -> {
1252+ String targetFileSystem = null ;
1253+
1254+ if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("persistent" ))) {
1255+ targetFileSystem = "persistent" ;
1256+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("temporary" ))) {
1257+ targetFileSystem = "temporary" ;
1258+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("files" ))) {
1259+ targetFileSystem = "files" ;
1260+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("documents" ))) {
1261+ targetFileSystem = "documents" ;
1262+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("cache" ))) {
1263+ targetFileSystem = "cache" ;
1264+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("root" ))) {
1265+ targetFileSystem = "root" ;
1266+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("files-external" ))) {
1267+ targetFileSystem = "files-external" ;
1268+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("sdcard" ))) {
1269+ targetFileSystem = "sdcard" ;
1270+ } else if (path .startsWith (LocalFilesystemURL .fsNameToCdvKeyword ("cache-external" ))) {
1271+ targetFileSystem = "cache-external" ;
1272+ }
1273+
1274+ if (targetFileSystem != null ) {
1275+ // Loop the registered file systems to find the target.
1276+ for (Filesystem fileSystem : filesystems ) {
1277+
1278+ /*
1279+ * When target is discovered:
1280+ * 1. Transform the url path to the native path
1281+ * 2. Load the file contents
1282+ * 3. Get the file mime type
1283+ * 4. Return the file & mime information back we Web Resources
1284+ */
1285+ if (fileSystem .name .equals (targetFileSystem )) {
1286+ // E.g. replace __cdvfile_persistent__ with native path "/data/user/0/com.example.file/files/files/"
1287+ String fileSystemNativeUri = fileSystem .rootUri .toString ().replace ("file://" , "" );
1288+ String fileTarget = path .replace (LocalFilesystemURL .fsNameToCdvKeyword (targetFileSystem ) + "/" , fileSystemNativeUri );
1289+
1290+ File file = new File (fileTarget );
1291+
1292+ try {
1293+ InputStream in = new FileInputStream (file );
1294+ String mimeType = getMimeType (Uri .parse (file .toString ()));
1295+ return new WebResourceResponse (mimeType , null , in );
1296+ } catch (FileNotFoundException e ) {
1297+ Log .e (LOG_TAG , e .getMessage ());
1298+ }
1299+ }
1300+ }
1301+ }
1302+
1303+ return null ;
1304+ };
1305+
1306+ return new CordovaPluginPathHandler (pathHandler );
1307+ }
12251308}
0 commit comments