@@ -20,16 +20,23 @@ Licensed to the Apache Software Foundation (ASF) under one
20
20
21
21
import android .Manifest ;
22
22
import android .app .Activity ;
23
+ import android .content .ContentResolver ;
23
24
import android .content .Context ;
24
25
import android .content .pm .PackageManager ;
25
26
import android .net .Uri ;
26
27
import android .os .Build ;
27
28
import android .os .Environment ;
28
29
import android .util .Base64 ;
30
+ import android .util .Log ;
31
+ import android .webkit .MimeTypeMap ;
32
+ import android .webkit .WebResourceResponse ;
33
+
34
+ import androidx .webkit .WebViewAssetLoader ;
29
35
30
36
import org .apache .cordova .CallbackContext ;
31
37
import org .apache .cordova .CordovaInterface ;
32
38
import org .apache .cordova .CordovaPlugin ;
39
+ import org .apache .cordova .CordovaPluginPathHandler ;
33
40
import org .apache .cordova .CordovaWebView ;
34
41
import org .apache .cordova .LOG ;
35
42
import org .apache .cordova .PermissionHelper ;
@@ -39,12 +46,16 @@ Licensed to the Apache Software Foundation (ASF) under one
39
46
import org .json .JSONException ;
40
47
import org .json .JSONObject ;
41
48
49
+ import java .io .BufferedInputStream ;
42
50
import java .io .ByteArrayOutputStream ;
43
51
import java .io .File ;
52
+ import java .io .FileInputStream ;
44
53
import java .io .FileNotFoundException ;
45
54
import java .io .IOException ;
46
55
import java .io .InputStream ;
56
+ import java .net .HttpURLConnection ;
47
57
import java .net .MalformedURLException ;
58
+ import java .net .URL ;
48
59
import java .security .Permission ;
49
60
import java .util .ArrayList ;
50
61
import java .util .HashMap ;
@@ -87,8 +98,6 @@ public class FileUtils extends CordovaPlugin {
87
98
88
99
private PendingRequests pendingRequests ;
89
100
90
-
91
-
92
101
/*
93
102
* We need both read and write when accessing the storage, I think.
94
103
*/
@@ -136,10 +145,10 @@ protected void registerExtraFileSystems(String[] filesystems, HashMap<String, St
136
145
if (fsRoot != null ) {
137
146
File newRoot = new File (fsRoot );
138
147
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 ));
140
149
installedFileSystems .add (fsName );
141
150
} 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" );
143
152
}
144
153
} else {
145
154
LOG .d (LOG_TAG , "Unrecognized extra filesystem identifier: " + fsName );
@@ -217,10 +226,10 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
217
226
// Note: The temporary and persistent filesystems need to be the first two
218
227
// registered, so that they will match window.TEMPORARY and window.PERSISTENT,
219
228
// 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 ));
224
233
225
234
registerExtraFileSystems (getExtraFileSystemsPreference (activity ), getAvailableFileSystems (activity ));
226
235
@@ -249,13 +258,15 @@ public Uri remapUri(Uri uri) {
249
258
if (!LocalFilesystemURL .FILESYSTEM_PROTOCOL .equals (uri .getScheme ())) {
250
259
return null ;
251
260
}
261
+
252
262
try {
253
263
LocalFilesystemURL inputURL = LocalFilesystemURL .parse (uri );
254
264
Filesystem fs = this .filesystemForURL (inputURL );
255
265
if (fs == null ) {
256
266
return null ;
257
267
}
258
268
String path = fs .filesystemPathForURL (inputURL );
269
+
259
270
if (path != null ) {
260
271
return Uri .parse ("file://" + fs .filesystemPathForURL (inputURL ));
261
272
}
@@ -270,6 +281,7 @@ public boolean execute(String action, final String rawArgs, final CallbackContex
270
281
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" ));
271
282
return true ;
272
283
}
284
+
273
285
if (action .equals ("testSaveLocationExists" )) {
274
286
threadhelper (new FileOp () {
275
287
public void run (JSONArray args ) {
@@ -459,18 +471,24 @@ else if (action.equals("getFile")) {
459
471
public void run (JSONArray args ) throws FileExistsException , IOException , TypeMismatchException , EncodingException , JSONException {
460
472
String dirname = args .getString (0 );
461
473
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 );
464
474
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 ) {
472
476
JSONObject obj = getFile (dirname , path , args .optJSONObject (2 ), false );
473
477
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
+ }
474
492
}
475
493
}
476
494
}, rawArgs , callbackContext );
@@ -878,6 +896,7 @@ private boolean remove(String baseURLstr) throws NoModificationAllowedException,
878
896
private JSONObject getFile (String baseURLstr , String path , JSONObject options , boolean directory ) throws FileExistsException , IOException , TypeMismatchException , EncodingException , JSONException {
879
897
try {
880
898
LocalFilesystemURL inputURL = LocalFilesystemURL .parse (baseURLstr );
899
+
881
900
Filesystem fs = this .filesystemForURL (inputURL );
882
901
if (fs == null ) {
883
902
throw new MalformedURLException ("No installed handlers for this URL" );
@@ -1222,4 +1241,68 @@ public void run(JSONArray args) throws JSONException, FileNotFoundException, IOE
1222
1241
LOG .d (LOG_TAG , "Received permission callback for unknown request code" );
1223
1242
}
1224
1243
}
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
+ }
1225
1308
}
0 commit comments