From 791574c26e794fb7f1fd8db7afe48883c13e2492 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Wed, 17 Apr 2013 15:50:29 -0400 Subject: [PATCH 1/3] Make URL parsing more robust in FileHelper. Fixes some cases when query parameters mess things up. --- .../src/org/apache/cordova/FileHelper.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/framework/src/org/apache/cordova/FileHelper.java b/framework/src/org/apache/cordova/FileHelper.java index c10ed964..8b446b06 100644 --- a/framework/src/org/apache/cordova/FileHelper.java +++ b/framework/src/org/apache/cordova/FileHelper.java @@ -28,6 +28,8 @@ import org.apache.cordova.api.LOG; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URLConnection; +import java.util.Locale; public class FileHelper { private static final String LOG_TAG = "FileUtils"; @@ -92,7 +94,8 @@ public class FileHelper { Uri uri = Uri.parse(uriString); return cordova.getActivity().getContentResolver().openInputStream(uri); } else if (uriString.startsWith("file:///android_asset/")) { - String relativePath = uriString.substring(22); + Uri uri = Uri.parse(uriString); + String relativePath = uri.getPath().substring(15); return cordova.getActivity().getAssets().open(relativePath); } else { return new FileInputStream(getRealPath(uriString, cordova)); @@ -122,14 +125,18 @@ public class FileHelper { public static String getMimeType(String uriString, CordovaInterface cordova) { String mimeType = null; + Uri uri = Uri.parse(uriString); if (uriString.startsWith("content://")) { - Uri uri = Uri.parse(uriString); mimeType = cordova.getActivity().getContentResolver().getType(uri); } else { - // MimeTypeMap.getFileExtensionFromUrl has a bug that occurs when the filename has a space, so we encode it. - // We also convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185). - String encodedUriString = uriString.replace(" ", "%20").toLowerCase(); - String extension = MimeTypeMap.getFileExtensionFromUrl(encodedUriString); + // MimeTypeMap.getFileExtensionFromUrl() fails when there are query parameters. + String extension = uri.getPath(); + int lastDot = extension.lastIndexOf('.'); + if (lastDot != -1) { + extension = extension.substring(lastDot + 1); + } + // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185). + extension = extension.toLowerCase(); if (extension.equals("3ga")) { mimeType = "audio/3gpp"; } else { From 80fe4458c6bec221b8ad0ca15d1d0adce4698c05 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Wed, 17 Apr 2013 15:51:37 -0400 Subject: [PATCH 2/3] Use FileHelper in IceCreamCordovaWebViewClient. Removes some duplicate logic and makes it a bit more robust. --- .../cordova/IceCreamCordovaWebViewClient.java | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java b/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java index 0ab62029..375282ec 100644 --- a/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java @@ -24,11 +24,12 @@ import java.io.InputStream; import org.apache.cordova.api.CordovaInterface; import org.apache.cordova.api.LOG; -import android.content.res.AssetManager; -import android.net.Uri; +import android.annotation.TargetApi; +import android.os.Build; import android.webkit.WebResourceResponse; import android.webkit.WebView; +@TargetApi(Build.VERSION_CODES.HONEYCOMB) public class IceCreamCordovaWebViewClient extends CordovaWebViewClient { @@ -43,34 +44,20 @@ public class IceCreamCordovaWebViewClient extends CordovaWebViewClient { @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if(url.contains("?") || url.contains("#") || needsIceCreamSpaceInAssetUrlFix(url)){ - return generateWebResourceResponse(url); - } else { - return super.shouldInterceptRequest(view, url); + WebResourceResponse ret = generateWebResourceResponse(url); + if (ret != null) { + return ret; + } } + return super.shouldInterceptRequest(view, url); } private WebResourceResponse generateWebResourceResponse(String url) { - final String ANDROID_ASSET = "file:///android_asset/"; - if (url.startsWith(ANDROID_ASSET)) { - String niceUrl = url; - niceUrl = url.replaceFirst(ANDROID_ASSET, ""); - if(niceUrl.contains("?")){ - niceUrl = niceUrl.split("\\?")[0]; - } - if(niceUrl.contains("#")) - { - niceUrl = niceUrl.split("#")[0]; - } - - String mimetype = null; - if(niceUrl.endsWith(".html")){ - mimetype = "text/html"; - } + if (url.startsWith("file:///android_asset/")) { + String mimetype = FileHelper.getMimeType(url, cordova); try { - AssetManager assets = cordova.getActivity().getAssets(); - Uri uri = Uri.parse(niceUrl); - InputStream stream = assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING); + InputStream stream = FileHelper.getInputStreamFromUriString(url, cordova); WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream); return response; } catch (IOException e) { From b13166f5d92196ed3e1b2d2dfd4cef7242876d70 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Wed, 17 Apr 2013 16:12:28 -0400 Subject: [PATCH 3/3] [CB-2432] Fix Camera.getPicture() for picasa images --- .../org/apache/cordova/CameraLauncher.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 22a9b948..b34f722b 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -42,6 +42,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.Bitmap.CompressFormat; +import android.graphics.Rect; import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.net.Uri; @@ -396,19 +397,21 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation) { this.callbackContext.success(uri.toString()); } else { + String uriString = uri.toString(); // Get the path to the image. Makes loading so much easier. - String imagePath = FileHelper.getRealPath(uri, this.cordova); - String mimeType = FileHelper.getMimeType(imagePath, this.cordova); - // Log.d(LOG_TAG, "Real path = " + imagePath); - // Log.d(LOG_TAG, "mime type = " + mimeType); + String mimeType = FileHelper.getMimeType(uriString, this.cordova); // If we don't have a valid image so quit. - if (imagePath == null || mimeType == null || - !(mimeType.equalsIgnoreCase("image/jpeg") || mimeType.equalsIgnoreCase("image/png"))) { + if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) { Log.d(LOG_TAG, "I either have a null image path or bitmap"); this.failPicture("Unable to retrieve path to picture!"); return; } - Bitmap bitmap = getScaledBitmap(imagePath); + Bitmap bitmap = null; + try { + bitmap = getScaledBitmap(uriString); + } catch (IOException e) { + e.printStackTrace(); + } if (bitmap == null) { Log.d(LOG_TAG, "I either have a null image path or bitmap"); this.failPicture("Unable to create bitmap!"); @@ -417,7 +420,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect if (this.correctOrientation) { String[] cols = { MediaStore.Images.Media.ORIENTATION }; - Cursor cursor = this.cordova.getActivity().getContentResolver().query(intent.getData(), + Cursor cursor = this.cordova.getActivity().getContentResolver().query(uri, cols, null, null, null); if (cursor != null) { cursor.moveToPosition(0); @@ -563,17 +566,18 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect * * @param imagePath * @return + * @throws IOException */ - private Bitmap getScaledBitmap(String imagePath) { + private Bitmap getScaledBitmap(String imageUrl) throws IOException { // If no new width or height were specified return the original bitmap if (this.targetWidth <= 0 && this.targetHeight <= 0) { - return BitmapFactory.decodeFile(imagePath); + return BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova)); } // figure out the original width and height of the image BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(imagePath, options); + BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova), null, options); //CB-2292: WTF? Why is the width null? if(options.outWidth == 0 || options.outHeight == 0) @@ -587,7 +591,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect // Load in the smallest bitmap possible that is closest to the size we want options.inJustDecodeBounds = false; options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight); - Bitmap unscaledBitmap = BitmapFactory.decodeFile(imagePath, options); + Bitmap unscaledBitmap = BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova), null, options); if (unscaledBitmap == null) { return null; }