diff --git a/VERSION b/VERSION
index 26aaba0e..f0bb29e7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.0
+1.3.0
diff --git a/bin/templates/project/phonegap/templates/project/assets/www/index.html b/bin/templates/project/phonegap/templates/project/assets/www/index.html
index e9e786d6..d89121be 100644
--- a/bin/templates/project/phonegap/templates/project/assets/www/index.html
+++ b/bin/templates/project/phonegap/templates/project/assets/www/index.html
@@ -4,8 +4,8 @@
PhoneGap
-
-
+
+
@@ -29,8 +29,12 @@
Beep
Vibrate
Get a Picture
- Get Phone's Contacts
- Check Network
+ Get Phone's Contacts
+ Check Network
+
+ - Compass Heading:
- Off
+
+ Toggle Compass
diff --git a/bin/templates/project/phonegap/templates/project/assets/www/main.js b/bin/templates/project/phonegap/templates/project/assets/www/main.js
index 1001aabc..f6316928 100644
--- a/bin/templates/project/phonegap/templates/project/assets/www/main.js
+++ b/bin/templates/project/phonegap/templates/project/assets/www/main.js
@@ -119,6 +119,25 @@ function check_network() {
confirm('Connection type:\n ' + states[networkState]);
}
+var watchID = null;
+
+function updateHeading(h) {
+ document.getElementById('h').innerHTML = h.magneticHeading;
+}
+
+function toggleCompass() {
+ if (watchID !== null) {
+ navigator.compass.clearWatch(watchID);
+ watchID = null;
+ updateHeading({ magneticHeading : "Off"});
+ } else {
+ var options = { frequency: 1000 };
+ watchID = navigator.compass.watchHeading(updateHeading, function(e) {
+ alert('Compass Error: ' + e.code);
+ }, options);
+ }
+}
+
function init() {
// the next line makes it impossible to see Contacts on the HTC Evo since it
// doesn't have a scroll button
diff --git a/framework/assets/js/filetransfer.js b/framework/assets/js/filetransfer.js
index 690cfcd1..e3e0d996 100644
--- a/framework/assets/js/filetransfer.js
+++ b/framework/assets/js/filetransfer.js
@@ -83,6 +83,17 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, debug, chunkedMode]);
};
+/**
+ * Downloads a file form a given URL and saves it to the specified directory.
+ * @param source {String} URL of the server to receive the file
+ * @param target {String} Full path of the file on the device
+ * @param successCallback (Function} Callback to be invoked when upload has completed
+ * @param errorCallback {Function} Callback to be invoked upon error
+ */
+FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) {
+ PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'download', [source, target]);
+};
+
/**
* Options to customize the HTTP request used to upload files.
* @constructor
diff --git a/framework/assets/www/index.html b/framework/assets/www/index.html
index d75751c8..72af12a0 100644
--- a/framework/assets/www/index.html
+++ b/framework/assets/www/index.html
@@ -1,7 +1,7 @@
-
+
diff --git a/framework/src/com/phonegap/Capture.java b/framework/src/com/phonegap/Capture.java
index a0ccf234..a9a5cb5f 100644
--- a/framework/src/com/phonegap/Capture.java
+++ b/framework/src/com/phonegap/Capture.java
@@ -49,6 +49,13 @@ public class Capture extends Plugin {
private static final int CAPTURE_IMAGE = 1; // Constant for capture image
private static final int CAPTURE_VIDEO = 2; // Constant for capture video
private static final String LOG_TAG = "Capture";
+
+ private static final int CAPTURE_INTERNAL_ERR = 0;
+ private static final int CAPTURE_APPLICATION_BUSY = 1;
+ private static final int CAPTURE_INVALID_ARGUMENT = 2;
+ private static final int CAPTURE_NO_MEDIA_FILES = 3;
+ private static final int CAPTURE_NOT_SUPPORTED = 20;
+
private String callbackId; // The ID of the callback to be invoked with our result
private long limit; // the number of pics/vids/clips to take
private double duration; // optional duration parameter for video recording
@@ -260,7 +267,7 @@ public class Capture extends Plugin {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) {
LOG.d(LOG_TAG, "Can't write to internal media storage.");
- this.fail("Error capturing image - no media storage found.");
+ this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found."));
return;
}
}
@@ -290,7 +297,7 @@ public class Capture extends Plugin {
}
} catch (IOException e) {
e.printStackTrace();
- this.fail("Error capturing image.");
+ this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image."));
}
} else if (requestCode == CAPTURE_VIDEO) {
// Get the uri of the video clip
@@ -315,7 +322,7 @@ public class Capture extends Plugin {
}
// user canceled the action
else {
- this.fail("Canceled.");
+ this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Canceled."));
}
}
// If something else
@@ -326,7 +333,7 @@ public class Capture extends Plugin {
}
// something bad happened
else {
- this.fail("Did not complete!");
+ this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Did not complete!"));
}
}
}
@@ -369,13 +376,24 @@ public class Capture extends Plugin {
return obj;
}
+
+ private JSONObject createErrorObject(int code, String message) {
+ JSONObject obj = new JSONObject();
+ try {
+ obj.put("code", code);
+ obj.put("message", message);
+ } catch (JSONException e) {
+ // This will never happen
+ }
+ return obj;
+ }
/**
* Send error message to JavaScript.
*
* @param err
*/
- public void fail(String err) {
+ public void fail(JSONObject err) {
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
}
}
diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java
index 4e1ca9f6..9e9cee20 100644
--- a/framework/src/com/phonegap/ContactAccessorSdk5.java
+++ b/framework/src/com/phonegap/ContactAccessorSdk5.java
@@ -1054,7 +1054,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (organizations != null) {
for (int i=0; i oldHeight) {
- LOG.v(TAG, "Throw hide keyboard event");
- callbackServer.sendJavascript("PhoneGap.fireDocumentEvent('hidekeyboard');");
+ if (callbackServer != null) {
+ LOG.v(TAG, "Throw hide keyboard event");
+ callbackServer.sendJavascript("PhoneGap.fireDocumentEvent('hidekeyboard');");
+ }
}
// If the height as gotten smaller then we will assume the soft keyboard has
// been displayed.
else if (height < oldHeight) {
- LOG.v(TAG, "Throw show keyboard event");
- callbackServer.sendJavascript("PhoneGap.fireDocumentEvent('showkeyboard');");
+ if (callbackServer != null) {
+ LOG.v(TAG, "Throw show keyboard event");
+ callbackServer.sendJavascript("PhoneGap.fireDocumentEvent('showkeyboard');");
+ }
}
// Update the old height for the next event
diff --git a/framework/src/com/phonegap/FileTransfer.java b/framework/src/com/phonegap/FileTransfer.java
index 8d014a22..0c3132ff 100644
--- a/framework/src/com/phonegap/FileTransfer.java
+++ b/framework/src/com/phonegap/FileTransfer.java
@@ -20,8 +20,10 @@ package com.phonegap;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -52,98 +54,100 @@ import com.phonegap.api.PluginResult;
public class FileTransfer extends Plugin {
- private static final String LOG_TAG = "FileUploader";
- private static final String LINE_START = "--";
- private static final String LINE_END = "\r\n";
- private static final String BOUNDRY = "*****";
+ private static final String LOG_TAG = "FileUploader";
+ private static final String LINE_START = "--";
+ private static final String LINE_END = "\r\n";
+ private static final String BOUNDRY = "*****";
- public static int FILE_NOT_FOUND_ERR = 1;
+ public static int FILE_NOT_FOUND_ERR = 1;
public static int INVALID_URL_ERR = 2;
public static int CONNECTION_ERR = 3;
-
+
private SSLSocketFactory defaultSSLSocketFactory = null;
private HostnameVerifier defaultHostnameVerifier = null;
- /* (non-Javadoc)
- * @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
- */
- @Override
- public PluginResult execute(String action, JSONArray args, String callbackId) {
- String file = null;
- String server = null;
- try {
- file = args.getString(0);
- server = args.getString(1);
- }
- catch (JSONException e) {
- Log.d(LOG_TAG, "Missing filename or server name");
- return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing filename or server name");
- }
-
- // Setup the options
- String fileKey = null;
- String fileName = null;
- String mimeType = null;
-
- fileKey = getArgument(args, 2, "file");
- fileName = getArgument(args, 3, "image.jpg");
- mimeType = getArgument(args, 4, "image/jpeg");
+ /* (non-Javadoc)
+ * @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
+ */
+ @Override
+ public PluginResult execute(String action, JSONArray args, String callbackId) {
+ String source = null;
+ String target = null;
+ try {
+ source = args.getString(0);
+ target = args.getString(1);
+ }
+ catch (JSONException e) {
+ Log.d(LOG_TAG, "Missing source or target");
+ return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing source or target");
+ }
- try {
- JSONObject params = args.optJSONObject(5);
- boolean trustEveryone = args.optBoolean(6);
- boolean chunkedMode = args.getBoolean(7);
+ try {
+ if (action.equals("upload")) {
+ // Setup the options
+ String fileKey = null;
+ String fileName = null;
+ String mimeType = null;
- if (action.equals("upload")) {
- FileUploadResult r = upload(file, server, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode);
- Log.d(LOG_TAG, "****** About to return a result from upload");
- return new PluginResult(PluginResult.Status.OK, r.toJSONObject());
- } else {
- return new PluginResult(PluginResult.Status.INVALID_ACTION);
- }
- } catch (FileNotFoundException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- JSONObject error = createFileUploadError(FILE_NOT_FOUND_ERR);
+ fileKey = getArgument(args, 2, "file");
+ fileName = getArgument(args, 3, "image.jpg");
+ mimeType = getArgument(args, 4, "image/jpeg");
+ JSONObject params = args.optJSONObject(5);
+ boolean trustEveryone = args.optBoolean(6);
+ boolean chunkedMode = args.optBoolean(7);
+ FileUploadResult r = upload(source, target, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode);
+ Log.d(LOG_TAG, "****** About to return a result from upload");
+ return new PluginResult(PluginResult.Status.OK, r.toJSONObject());
+ } else if (action.equals("download")) {
+ JSONObject r = download(source, target);
+ Log.d(LOG_TAG, "****** About to return a result from download");
+ return new PluginResult(PluginResult.Status.OK, r, "window.localFileSystem._castEntry");
+ } else {
+ return new PluginResult(PluginResult.Status.INVALID_ACTION);
+ }
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IllegalArgumentException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- JSONObject error = createFileUploadError(INVALID_URL_ERR);
+ Log.e(LOG_TAG, e.getMessage(), e);
+ JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
- } catch (SSLException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- Log.d(LOG_TAG, "Got my ssl exception!!!");
- JSONObject error = createFileUploadError(CONNECTION_ERR);
+ } catch (SSLException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ Log.d(LOG_TAG, "Got my ssl exception!!!");
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IOException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- JSONObject error = createFileUploadError(CONNECTION_ERR);
+ Log.e(LOG_TAG, e.getMessage(), e);
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
- }
- }
-
- // always verify the host - don't check for certificate
- final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
- public boolean verify(String hostname, SSLSession session) {
- return true;
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
- };
+ }
- /**
- * This function will install a trust manager that will blindly trust all SSL
- * certificates. The reason this code is being added is to enable developers
- * to do development using self signed SSL certificates on their web server.
- *
- * The standard HttpsURLConnection class will throw an exception on self
- * signed certificates if this code is not run.
- */
- private void trustAllHosts() {
+ // always verify the host - don't check for certificate
+ final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ };
+
+ /**
+ * This function will install a trust manager that will blindly trust all SSL
+ * certificates. The reason this code is being added is to enable developers
+ * to do development using self signed SSL certificates on their web server.
+ *
+ * The standard HttpsURLConnection class will throw an exception on self
+ * signed certificates if this code is not run.
+ */
+ private void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
- return new java.security.cert.X509Certificate[] {};
+ return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
@@ -157,54 +161,56 @@ public class FileTransfer extends Plugin {
// Install the all-trusting trust manager
try {
- // Backup the current SSL socket factory
- defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
- // Install our all trusting manager
- SSLContext sc = SSLContext.getInstance("TLS");
+ // Backup the current SSL socket factory
+ defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
+ // Install our all trusting manager
+ SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
- }
+ }
- /**
- * Create an error object based on the passed in errorCode
- * @param errorCode the error
- * @return JSONObject containing the error
- */
- private JSONObject createFileUploadError(int errorCode) {
- JSONObject error = null;
- try {
- error = new JSONObject();
- error.put("code", errorCode);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return error;
- }
-
- /**
- * Convenience method to read a parameter from the list of JSON args.
- * @param args the args passed to the Plugin
- * @param position the position to retrieve the arg from
- * @param defaultString the default to be used if the arg does not exist
- * @return String with the retrieved value
- */
- private String getArgument(JSONArray args, int position, String defaultString) {
- String arg = defaultString;
- if(args.length() >= position) {
- arg = args.optString(position);
- if (arg == null || "null".equals(arg)) {
- arg = defaultString;
- }
- }
- return arg;
- }
-
/**
- * Uploads the specified file to the server URL provided using an HTTP
- * multipart request.
+ * Create an error object based on the passed in errorCode
+ * @param errorCode the error
+ * @return JSONObject containing the error
+ */
+ private JSONObject createFileTransferError(int errorCode, String source, String target) {
+ JSONObject error = null;
+ try {
+ error = new JSONObject();
+ error.put("code", errorCode);
+ error.put("source", source);
+ error.put("target", target);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ return error;
+ }
+
+ /**
+ * Convenience method to read a parameter from the list of JSON args.
+ * @param args the args passed to the Plugin
+ * @param position the position to retrieve the arg from
+ * @param defaultString the default to be used if the arg does not exist
+ * @return String with the retrieved value
+ */
+ private String getArgument(JSONArray args, int position, String defaultString) {
+ String arg = defaultString;
+ if(args.length() >= position) {
+ arg = args.optString(position);
+ if (arg == null || "null".equals(arg)) {
+ arg = defaultString;
+ }
+ }
+ return arg;
+ }
+
+ /**
+ * Uploads the specified file to the server URL provided using an HTTP
+ * multipart request.
* @param file Full path of the file on the file system
* @param server URL of the server to receive the file
* @param fileKey Name of file request parameter
@@ -213,173 +219,226 @@ public class FileTransfer extends Plugin {
* @param params key:value pairs of user-defined parameters
* @return FileUploadResult containing result of upload request
*/
- public FileUploadResult upload(String file, String server, final String fileKey, final String fileName,
- final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException {
- // Create return object
- FileUploadResult result = new FileUploadResult();
-
- // Get a input stream of the file on the phone
- InputStream fileInputStream = getPathFromUri(file);
+ public FileUploadResult upload(String file, String server, final String fileKey, final String fileName,
+ final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException {
+ // Create return object
+ FileUploadResult result = new FileUploadResult();
- HttpURLConnection conn = null;
- DataOutputStream dos = null;
+ // Get a input stream of the file on the phone
+ InputStream fileInputStream = getPathFromUri(file);
- int bytesRead, bytesAvailable, bufferSize;
- long totalBytes;
- byte[] buffer;
- int maxBufferSize = 8096;
+ HttpURLConnection conn = null;
+ DataOutputStream dos = null;
- //------------------ CLIENT REQUEST
- // open a URL connection to the server
- URL url = new URL(server);
-
- // Open a HTTP connection to the URL based on protocol
+ int bytesRead, bytesAvailable, bufferSize;
+ long totalBytes;
+ byte[] buffer;
+ int maxBufferSize = 8096;
+
+ //------------------ CLIENT REQUEST
+ // open a URL connection to the server
+ URL url = new URL(server);
+
+ // Open a HTTP connection to the URL based on protocol
if (url.getProtocol().toLowerCase().equals("https")) {
- // Using standard HTTPS connection. Will not allow self signed certificate
- if (!trustEveryone) {
- conn = (HttpsURLConnection) url.openConnection();
- }
- // Use our HTTPS connection that blindly trusts everyone.
- // This should only be used in debug environments
- else {
- // Setup the HTTPS connection class to trust everyone
- trustAllHosts();
- HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
- // Save the current hostnameVerifier
- defaultHostnameVerifier = https.getHostnameVerifier();
- // Setup the connection not to verify hostnames
- https.setHostnameVerifier(DO_NOT_VERIFY);
- conn = https;
- }
- }
+ // Using standard HTTPS connection. Will not allow self signed certificate
+ if (!trustEveryone) {
+ conn = (HttpsURLConnection) url.openConnection();
+ }
+ // Use our HTTPS connection that blindly trusts everyone.
+ // This should only be used in debug environments
+ else {
+ // Setup the HTTPS connection class to trust everyone
+ trustAllHosts();
+ HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
+ // Save the current hostnameVerifier
+ defaultHostnameVerifier = https.getHostnameVerifier();
+ // Setup the connection not to verify hostnames
+ https.setHostnameVerifier(DO_NOT_VERIFY);
+ conn = https;
+ }
+ }
// Return a standard HTTP connection
else {
- conn = (HttpURLConnection) url.openConnection();
+ conn = (HttpURLConnection) url.openConnection();
}
-
- // Allow Inputs
- conn.setDoInput(true);
-
- // Allow Outputs
- conn.setDoOutput(true);
-
- // Don't use a cached copy.
- conn.setUseCaches(false);
-
- // Use a post method.
- conn.setRequestMethod("POST");
- conn.setRequestProperty("Connection", "Keep-Alive");
- conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY);
- // Set the cookies on the response
- String cookie = CookieManager.getInstance().getCookie(server);
- if (cookie != null) {
- conn.setRequestProperty("Cookie", cookie);
- }
-
- // Should set this up as an option
- if (chunkedMode) {
- conn.setChunkedStreamingMode(maxBufferSize);
- }
-
- dos = new DataOutputStream( conn.getOutputStream() );
+ // Allow Inputs
+ conn.setDoInput(true);
- // Send any extra parameters
- try {
- for (Iterator iter = params.keys(); iter.hasNext();) {
- Object key = iter.next();
- dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
- dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\";");
- dos.writeBytes(LINE_END + LINE_END);
- dos.write(params.getString(key.toString()).getBytes());
- dos.writeBytes(LINE_END);
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
-
- dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
- dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"" + fileName +"\"" + LINE_END);
- dos.writeBytes("Content-Type: " + mimeType + LINE_END);
- dos.writeBytes(LINE_END);
-
- // create a buffer of maximum size
- bytesAvailable = fileInputStream.available();
- bufferSize = Math.min(bytesAvailable, maxBufferSize);
- buffer = new byte[bufferSize];
-
- // read file and write it into form...
- bytesRead = fileInputStream.read(buffer, 0, bufferSize);
- totalBytes = 0;
+ // Allow Outputs
+ conn.setDoOutput(true);
- while (bytesRead > 0) {
- totalBytes += bytesRead;
- result.setBytesSent(totalBytes);
- dos.write(buffer, 0, bufferSize);
- bytesAvailable = fileInputStream.available();
- bufferSize = Math.min(bytesAvailable, maxBufferSize);
- bytesRead = fileInputStream.read(buffer, 0, bufferSize);
- }
+ // Don't use a cached copy.
+ conn.setUseCaches(false);
- // send multipart form data necesssary after file data...
- dos.writeBytes(LINE_END);
- dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END);
-
- // close streams
- fileInputStream.close();
- dos.flush();
- dos.close();
+ // Use a post method.
+ conn.setRequestMethod("POST");
+ conn.setRequestProperty("Connection", "Keep-Alive");
+ conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY);
- //------------------ read the SERVER RESPONSE
- StringBuffer responseString = new StringBuffer("");
- DataInputStream inStream;
- try {
- inStream = new DataInputStream ( conn.getInputStream() );
- } catch(FileNotFoundException e) {
- throw new IOException("Received error from server");
- }
-
- String line;
- while (( line = inStream.readLine()) != null) {
- responseString.append(line);
- }
- Log.d(LOG_TAG, "got response from server");
- Log.d(LOG_TAG, responseString.toString());
+ // Set the cookies on the response
+ String cookie = CookieManager.getInstance().getCookie(server);
+ if (cookie != null) {
+ conn.setRequestProperty("Cookie", cookie);
+ }
- // send request and retrieve response
+ // Should set this up as an option
+ if (chunkedMode) {
+ conn.setChunkedStreamingMode(maxBufferSize);
+ }
+
+ dos = new DataOutputStream( conn.getOutputStream() );
+
+ // Send any extra parameters
+ try {
+ for (Iterator iter = params.keys(); iter.hasNext();) {
+ Object key = iter.next();
+ dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
+ dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\";");
+ dos.writeBytes(LINE_END + LINE_END);
+ dos.write(params.getString(key.toString()).getBytes());
+ dos.writeBytes(LINE_END);
+ }
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+
+ dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
+ dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"" + fileName +"\"" + LINE_END);
+ dos.writeBytes("Content-Type: " + mimeType + LINE_END);
+ dos.writeBytes(LINE_END);
+
+ // create a buffer of maximum size
+ bytesAvailable = fileInputStream.available();
+ bufferSize = Math.min(bytesAvailable, maxBufferSize);
+ buffer = new byte[bufferSize];
+
+ // read file and write it into form...
+ bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+ totalBytes = 0;
+
+ while (bytesRead > 0) {
+ totalBytes += bytesRead;
+ result.setBytesSent(totalBytes);
+ dos.write(buffer, 0, bufferSize);
+ bytesAvailable = fileInputStream.available();
+ bufferSize = Math.min(bytesAvailable, maxBufferSize);
+ bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+ }
+
+ // send multipart form data necesssary after file data...
+ dos.writeBytes(LINE_END);
+ dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END);
+
+ // close streams
+ fileInputStream.close();
+ dos.flush();
+ dos.close();
+
+ //------------------ read the SERVER RESPONSE
+ StringBuffer responseString = new StringBuffer("");
+ DataInputStream inStream;
+ try {
+ inStream = new DataInputStream ( conn.getInputStream() );
+ } catch(FileNotFoundException e) {
+ throw new IOException("Received error from server");
+ }
+
+ String line;
+ while (( line = inStream.readLine()) != null) {
+ responseString.append(line);
+ }
+ Log.d(LOG_TAG, "got response from server");
+ Log.d(LOG_TAG, responseString.toString());
+
+ // send request and retrieve response
result.setResponseCode(conn.getResponseCode());
result.setResponse(responseString.toString());
inStream.close();
conn.disconnect();
-
+
// Revert back to the proper verifier and socket factories
if (trustEveryone && url.getProtocol().toLowerCase().equals("https")) {
- ((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier);
- HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
- }
-
- return result;
- }
+ ((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier);
+ HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
+ }
- /**
+ return result;
+ }
+
+ /**
+ * Downloads a file form a given URL and saves it to the specified directory.
+ *
+ * @param source URL of the server to receive the file
+ * @param target Full path of the file on the file system
+ * @return JSONObject the downloaded file
+ */
+ public JSONObject download(String source, String target) throws IOException {
+ try {
+ File file = new File(target);
+
+ // create needed directories
+ file.getParentFile().mkdirs();
+
+ // connect to server
+ URL url = new URL(source);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setDoOutput(true);
+ connection.connect();
+
+ Log.d(LOG_TAG, "Download file:" + url);
+
+ InputStream inputStream = connection.getInputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead = 0;
+
+ FileOutputStream outputStream = new FileOutputStream(file);
+
+ // write bytes to file
+ while ( (bytesRead = inputStream.read(buffer)) > 0 ) {
+ outputStream.write(buffer,0, bytesRead);
+ }
+
+ outputStream.close();
+
+ Log.d(LOG_TAG, "Saved file: " + target);
+
+ // create FileEntry object
+ FileUtils fileUtil = new FileUtils();
+
+ return fileUtil.getEntry(file);
+ } catch (Exception e) {
+ Log.d(LOG_TAG, e.getMessage(), e);
+ throw new IOException("Error while downloading");
+ }
+ }
+
+ /**
* Get an input stream based on file path or content:// uri
- *
+ *
* @param path
* @return an input stream
- * @throws FileNotFoundException
+ * @throws FileNotFoundException
*/
- private InputStream getPathFromUri(String path) throws FileNotFoundException {
- if (path.startsWith("content:")) {
- Uri uri = Uri.parse(path);
- return ctx.getContentResolver().openInputStream(uri);
- }
- else if (path.startsWith("file://")) {
- return new FileInputStream(path.substring(7));
- }
- else {
- return new FileInputStream(path);
- }
- }
+ private InputStream getPathFromUri(String path) throws FileNotFoundException {
+ if (path.startsWith("content:")) {
+ Uri uri = Uri.parse(path);
+ return ctx.getContentResolver().openInputStream(uri);
+ }
+ else if (path.startsWith("file://")) {
+ int question = path.indexOf("?");
+ if (question == -1) {
+ return new FileInputStream(path.substring(7));
+ } else {
+ return new FileInputStream(path.substring(7, question));
+ }
+ }
+ else {
+ return new FileInputStream(path);
+ }
+ }
}
diff --git a/framework/src/com/phonegap/FileUtils.java b/framework/src/com/phonegap/FileUtils.java
index 00aa9ce3..9bc0d0a9 100755
--- a/framework/src/com/phonegap/FileUtils.java
+++ b/framework/src/com/phonegap/FileUtils.java
@@ -50,214 +50,214 @@ import com.phonegap.file.TypeMismatchException;
* Only files on the SD card can be accessed.
*/
public class FileUtils extends Plugin {
- private static final String LOG_TAG = "FileUtils";
- private static final String _DATA = "_data"; // The column name where the file path is stored
+ private static final String LOG_TAG = "FileUtils";
+ private static final String _DATA = "_data"; // The column name where the file path is stored
- public static int NOT_FOUND_ERR = 1;
- public static int SECURITY_ERR = 2;
- public static int ABORT_ERR = 3;
+ public static int NOT_FOUND_ERR = 1;
+ public static int SECURITY_ERR = 2;
+ public static int ABORT_ERR = 3;
- public static int NOT_READABLE_ERR = 4;
- public static int ENCODING_ERR = 5;
- public static int NO_MODIFICATION_ALLOWED_ERR = 6;
- public static int INVALID_STATE_ERR = 7;
- public static int SYNTAX_ERR = 8;
- public static int INVALID_MODIFICATION_ERR = 9;
+ public static int NOT_READABLE_ERR = 4;
+ public static int ENCODING_ERR = 5;
+ public static int NO_MODIFICATION_ALLOWED_ERR = 6;
+ public static int INVALID_STATE_ERR = 7;
+ public static int SYNTAX_ERR = 8;
+ public static int INVALID_MODIFICATION_ERR = 9;
public static int QUOTA_EXCEEDED_ERR = 10;
public static int TYPE_MISMATCH_ERR = 11;
public static int PATH_EXISTS_ERR = 12;
- public static int TEMPORARY = 0;
- public static int PERSISTENT = 1;
- public static int RESOURCE = 2;
- public static int APPLICATION = 3;
-
- FileReader f_in;
- FileWriter f_out;
-
- /**
- * Constructor.
- */
- public FileUtils() {
- }
+ public static int TEMPORARY = 0;
+ public static int PERSISTENT = 1;
+ public static int RESOURCE = 2;
+ public static int APPLICATION = 3;
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackId The callback id used when calling back into JavaScript.
- * @return A PluginResult object with a status and message.
- */
- public PluginResult execute(String action, JSONArray args, String callbackId) {
- PluginResult.Status status = PluginResult.Status.OK;
- String result = "";
- //System.out.println("FileUtils.execute("+action+")");
-
- try {
- try {
- if (action.equals("testSaveLocationExists")) {
- boolean b = DirectoryManager.testSaveLocationExists();
- return new PluginResult(status, b);
- }
- else if (action.equals("getFreeDiskSpace")) {
- long l = DirectoryManager.getFreeDiskSpace();
- return new PluginResult(status, l);
- }
- else if (action.equals("testFileExists")) {
- boolean b = DirectoryManager.testFileExists(args.getString(0));
- return new PluginResult(status, b);
- }
- else if (action.equals("testDirectoryExists")) {
- boolean b = DirectoryManager.testFileExists(args.getString(0));
- return new PluginResult(status, b);
- }
- else if (action.equals("readAsText")) {
- String s = this.readAsText(args.getString(0), args.getString(1));
- return new PluginResult(status, s);
- }
- else if (action.equals("readAsDataURL")) {
- String s = this.readAsDataURL(args.getString(0));
- return new PluginResult(status, s);
- }
- else if (action.equals("write")) {
- long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2));
- return new PluginResult(status, fileSize);
- }
- else if (action.equals("truncate")) {
- long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
- return new PluginResult(status, fileSize);
- }
- else if (action.equals("requestFileSystem")) {
- long size = args.optLong(1);
- if (size != 0) {
- if (size > (DirectoryManager.getFreeDiskSpace()*1024)) {
- JSONObject error = new JSONObject().put("code", FileUtils.QUOTA_EXCEEDED_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- }
- }
- JSONObject obj = requestFileSystem(args.getInt(0));
- return new PluginResult(status, obj, "window.localFileSystem._castFS");
- }
- else if (action.equals("resolveLocalFileSystemURI")) {
- JSONObject obj = resolveLocalFileSystemURI(args.getString(0));
- return new PluginResult(status, obj, "window.localFileSystem._castEntry");
- }
- else if (action.equals("getMetadata")) {
- JSONObject obj = getMetadata(args.getString(0));
- return new PluginResult(status, obj, "window.localFileSystem._castDate");
- }
- else if (action.equals("getFileMetadata")) {
- JSONObject obj = getFileMetadata(args.getString(0));
- return new PluginResult(status, obj, "window.localFileSystem._castDate");
- }
- else if (action.equals("getParent")) {
- JSONObject obj = getParent(args.getString(0));
- return new PluginResult(status, obj, "window.localFileSystem._castEntry");
- }
- else if (action.equals("getDirectory")) {
- JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), true);
- return new PluginResult(status, obj, "window.localFileSystem._castEntry");
- }
- else if (action.equals("getFile")) {
- JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), false);
- return new PluginResult(status, obj, "window.localFileSystem._castEntry");
- }
- else if (action.equals("remove")) {
- boolean success;
-
- success = remove(args.getString(0));
-
- if (success) {
- notifyDelete(args.getString(0));
- return new PluginResult(status);
- } else {
- JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- }
- }
- else if (action.equals("removeRecursively")) {
- boolean success = removeRecursively(args.getString(0));
- if (success) {
- return new PluginResult(status);
- } else {
- JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- }
- }
- else if (action.equals("moveTo")) {
- JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), true);
- return new PluginResult(status, entry, "window.localFileSystem._castEntry");
- }
- else if (action.equals("copyTo")) {
- JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), false);
- return new PluginResult(status, entry, "window.localFileSystem._castEntry");
- }
- else if (action.equals("readEntries")) {
- JSONArray entries = readEntries(args.getString(0));
- return new PluginResult(status, entries, "window.localFileSystem._castEntries");
- }
- return new PluginResult(status, result);
- } catch (FileNotFoundException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.NOT_FOUND_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (FileExistsException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.PATH_EXISTS_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (NoModificationAllowedException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (JSONException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (InvalidModificationException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (MalformedURLException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (IOException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (EncodingException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- } catch (TypeMismatchException e) {
- JSONObject error = new JSONObject().put("code", FileUtils.TYPE_MISMATCH_ERR);
- return new PluginResult(PluginResult.Status.ERROR, error);
- }
- } catch (JSONException e) {
- e.printStackTrace();
- return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
- }
- }
-
- /**
- * Need to check to see if we need to clean up the content store
- *
- * @param filePath the path to check
- */
- private void notifyDelete(String filePath) {
- int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- MediaStore.Images.Media.DATA + " = ?",
- new String[] {filePath});
- }
+ FileReader f_in;
+ FileWriter f_out;
/**
- * Allows the user to look up the Entry for a file or directory referred to by a local URI.
- *
- * @param url of the file/directory to look up
- * @return a JSONObject representing a Entry from the filesystem
- * @throws MalformedURLException if the url is not valid
- * @throws FileNotFoundException if the file does not exist
- * @throws IOException if the user can't read the file
- * @throws JSONException
- */
- private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException {
+ * Constructor.
+ */
+ public FileUtils() {
+ }
+
+ /**
+ * Executes the request and returns PluginResult.
+ *
+ * @param action The action to execute.
+ * @param args JSONArry of arguments for the plugin.
+ * @param callbackId The callback id used when calling back into JavaScript.
+ * @return A PluginResult object with a status and message.
+ */
+ public PluginResult execute(String action, JSONArray args, String callbackId) {
+ PluginResult.Status status = PluginResult.Status.OK;
+ String result = "";
+ //System.out.println("FileUtils.execute("+action+")");
+
+ try {
+ try {
+ if (action.equals("testSaveLocationExists")) {
+ boolean b = DirectoryManager.testSaveLocationExists();
+ return new PluginResult(status, b);
+ }
+ else if (action.equals("getFreeDiskSpace")) {
+ long l = DirectoryManager.getFreeDiskSpace();
+ return new PluginResult(status, l);
+ }
+ else if (action.equals("testFileExists")) {
+ boolean b = DirectoryManager.testFileExists(args.getString(0));
+ return new PluginResult(status, b);
+ }
+ else if (action.equals("testDirectoryExists")) {
+ boolean b = DirectoryManager.testFileExists(args.getString(0));
+ return new PluginResult(status, b);
+ }
+ else if (action.equals("readAsText")) {
+ String s = this.readAsText(args.getString(0), args.getString(1));
+ return new PluginResult(status, s);
+ }
+ else if (action.equals("readAsDataURL")) {
+ String s = this.readAsDataURL(args.getString(0));
+ return new PluginResult(status, s);
+ }
+ else if (action.equals("write")) {
+ long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2));
+ return new PluginResult(status, fileSize);
+ }
+ else if (action.equals("truncate")) {
+ long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
+ return new PluginResult(status, fileSize);
+ }
+ else if (action.equals("requestFileSystem")) {
+ long size = args.optLong(1);
+ if (size != 0) {
+ if (size > (DirectoryManager.getFreeDiskSpace()*1024)) {
+ JSONObject error = new JSONObject().put("code", FileUtils.QUOTA_EXCEEDED_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ }
+ }
+ JSONObject obj = requestFileSystem(args.getInt(0));
+ return new PluginResult(status, obj, "window.localFileSystem._castFS");
+ }
+ else if (action.equals("resolveLocalFileSystemURI")) {
+ JSONObject obj = resolveLocalFileSystemURI(args.getString(0));
+ return new PluginResult(status, obj, "window.localFileSystem._castEntry");
+ }
+ else if (action.equals("getMetadata")) {
+ JSONObject obj = getMetadata(args.getString(0));
+ return new PluginResult(status, obj, "window.localFileSystem._castDate");
+ }
+ else if (action.equals("getFileMetadata")) {
+ JSONObject obj = getFileMetadata(args.getString(0));
+ return new PluginResult(status, obj, "window.localFileSystem._castDate");
+ }
+ else if (action.equals("getParent")) {
+ JSONObject obj = getParent(args.getString(0));
+ return new PluginResult(status, obj, "window.localFileSystem._castEntry");
+ }
+ else if (action.equals("getDirectory")) {
+ JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), true);
+ return new PluginResult(status, obj, "window.localFileSystem._castEntry");
+ }
+ else if (action.equals("getFile")) {
+ JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), false);
+ return new PluginResult(status, obj, "window.localFileSystem._castEntry");
+ }
+ else if (action.equals("remove")) {
+ boolean success;
+
+ success = remove(args.getString(0));
+
+ if (success) {
+ notifyDelete(args.getString(0));
+ return new PluginResult(status);
+ } else {
+ JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ }
+ }
+ else if (action.equals("removeRecursively")) {
+ boolean success = removeRecursively(args.getString(0));
+ if (success) {
+ return new PluginResult(status);
+ } else {
+ JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ }
+ }
+ else if (action.equals("moveTo")) {
+ JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), true);
+ return new PluginResult(status, entry, "window.localFileSystem._castEntry");
+ }
+ else if (action.equals("copyTo")) {
+ JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), false);
+ return new PluginResult(status, entry, "window.localFileSystem._castEntry");
+ }
+ else if (action.equals("readEntries")) {
+ JSONArray entries = readEntries(args.getString(0));
+ return new PluginResult(status, entries, "window.localFileSystem._castEntries");
+ }
+ return new PluginResult(status, result);
+ } catch (FileNotFoundException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.NOT_FOUND_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (FileExistsException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.PATH_EXISTS_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (NoModificationAllowedException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (JSONException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (InvalidModificationException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (MalformedURLException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (IOException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (EncodingException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ } catch (TypeMismatchException e) {
+ JSONObject error = new JSONObject().put("code", FileUtils.TYPE_MISMATCH_ERR);
+ return new PluginResult(PluginResult.Status.ERROR, error);
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ }
+ }
+
+ /**
+ * Need to check to see if we need to clean up the content store
+ *
+ * @param filePath the path to check
+ */
+ private void notifyDelete(String filePath) {
+ int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ MediaStore.Images.Media.DATA + " = ?",
+ new String[] {filePath});
+ }
+
+ /**
+ * Allows the user to look up the Entry for a file or directory referred to by a local URI.
+ *
+ * @param url of the file/directory to look up
+ * @return a JSONObject representing a Entry from the filesystem
+ * @throws MalformedURLException if the url is not valid
+ * @throws FileNotFoundException if the file does not exist
+ * @throws IOException if the user can't read the file
+ * @throws JSONException
+ */
+ private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException {
String decoded = URLDecoder.decode(url, "UTF-8");
-
+
File fp = null;
-
+
// Handle the special case where you get an Android content:// uri.
if (decoded.startsWith("content:")) {
Cursor cursor = this.ctx.managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null);
@@ -266,15 +266,15 @@ public class FileUtils extends Plugin {
cursor.moveToFirst();
fp = new File(cursor.getString(column_index));
} else {
- // Test to see if this is a valid URL first
- @SuppressWarnings("unused")
- URL testUrl = new URL(decoded);
-
- if (decoded.startsWith("file://")) {
- fp = new File(decoded.substring(7, decoded.length()));
- } else {
- fp = new File(decoded);
- }
+ // Test to see if this is a valid URL first
+ @SuppressWarnings("unused")
+ URL testUrl = new URL(decoded);
+
+ if (decoded.startsWith("file://")) {
+ fp = new File(decoded.substring(7, decoded.length()));
+ } else {
+ fp = new File(decoded);
+ }
}
if (!fp.exists()) {
@@ -283,614 +283,612 @@ public class FileUtils extends Plugin {
if (!fp.canRead()) {
throw new IOException();
}
- return getEntry(fp);
- }
+ return getEntry(fp);
+ }
- /**
- * Read the list of files from this directory.
- *
- * @param fileName the directory to read from
- * @return a JSONArray containing JSONObjects that represent Entry objects.
- * @throws FileNotFoundException if the directory is not found.
- * @throws JSONException
- */
- private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException {
- File fp = new File(fileName);
+ /**
+ * Read the list of files from this directory.
+ *
+ * @param fileName the directory to read from
+ * @return a JSONArray containing JSONObjects that represent Entry objects.
+ * @throws FileNotFoundException if the directory is not found.
+ * @throws JSONException
+ */
+ private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException {
+ File fp = new File(fileName);
- if (!fp.exists()) {
- // The directory we are listing doesn't exist so we should fail.
- throw new FileNotFoundException();
- }
+ if (!fp.exists()) {
+ // The directory we are listing doesn't exist so we should fail.
+ throw new FileNotFoundException();
+ }
- JSONArray entries = new JSONArray();
-
- if (fp.isDirectory()) {
- File[] files = fp.listFiles();
- for (int i=0; i 0) {
- throw new InvalidModificationException("directory is not empty");
- }
- }
-
- // Try to rename the directory
- if (!srcDir.renameTo(destinationDir)) {
- // Trying to rename the directory failed. Possibly because we moved across file system on the device.
- // Now we have to do things the hard way
- // 1) Copy all the old files
- // 2) delete the src directory
- }
-
- return getEntry(destinationDir);
- }
+ // Try to rename the file
+ if (!srcFile.renameTo(destFile)) {
+ // Trying to rename the file failed. Possibly because we moved across file system on the device.
+ // Now we have to do things the hard way
+ // 1) Copy all the old file
+ // 2) delete the src file
+ }
- /**
- * Deletes a directory and all of its contents, if any. In the event of an error
- * [e.g. trying to delete a directory that contains a file that cannot be removed],
- * some of the contents of the directory may be deleted.
- * It is an error to attempt to delete the root directory of a filesystem.
- *
- * @param filePath the directory to be removed
- * @return a boolean representing success of failure
- * @throws FileExistsException
- */
- private boolean removeRecursively(String filePath) throws FileExistsException {
- File fp = new File(filePath);
+ return getEntry(destFile);
+ }
- // You can't delete the root directory.
- if (atRootDirectory(filePath)) {
- return false;
- }
+ /**
+ * Move a directory
+ *
+ * @param srcDir directory to be copied
+ * @param destinationDir destination to be copied to
+ * @return a DirectoryEntry object
+ * @throws JSONException
+ * @throws IOException
+ * @throws InvalidModificationException
+ */
+ private JSONObject moveDirectory(File srcDir, File destinationDir) throws JSONException, InvalidModificationException {
+ // Renaming a file to an existing directory should fail
+ if (destinationDir.exists() && destinationDir.isFile()) {
+ throw new InvalidModificationException("Can't rename a file to a directory");
+ }
- return removeDirRecursively(fp);
- }
-
- /**
- * Loops through a directory deleting all the files.
- *
- * @param directory to be removed
- * @return a boolean representing success of failure
- * @throws FileExistsException
- */
- private boolean removeDirRecursively(File directory) throws FileExistsException {
- if (directory.isDirectory()) {
- for (File file : directory.listFiles()) {
- removeDirRecursively(file);
- }
- }
+ // Check to make sure we are not copying the directory into itself
+ if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) {
+ throw new InvalidModificationException("Can't move itself into itself");
+ }
- if (!directory.delete()) {
- throw new FileExistsException("could not delete: " + directory.getName());
- } else {
- return true;
- }
- }
+ // If the destination directory already exists and is empty then delete it. This is according to spec.
+ if (destinationDir.exists()) {
+ if (destinationDir.list().length > 0) {
+ throw new InvalidModificationException("directory is not empty");
+ }
+ }
- /**
- * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty.
- * It is an error to attempt to delete the root directory of a filesystem.
- *
- * @param filePath file or directory to be removed
- * @return a boolean representing success of failure
- * @throws NoModificationAllowedException
- * @throws InvalidModificationException
- */
- private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException {
- File fp = new File(filePath);
-
- // You can't delete the root directory.
- if (atRootDirectory(filePath)) {
- throw new NoModificationAllowedException("You can't delete the root directory");
- }
-
- // You can't delete a directory that is not empty
- if (fp.isDirectory() && fp.list().length > 0) {
- throw new InvalidModificationException("You can't delete a directory that is not empty.");
- }
-
- return fp.delete();
- }
+ // Try to rename the directory
+ if (!srcDir.renameTo(destinationDir)) {
+ // Trying to rename the directory failed. Possibly because we moved across file system on the device.
+ // Now we have to do things the hard way
+ // 1) Copy all the old files
+ // 2) delete the src directory
+ }
- /**
- * Creates or looks up a file.
- *
- * @param dirPath base directory
- * @param fileName file/directory to lookup or create
- * @param options specify whether to create or not
- * @param directory if true look up directory, if false look up file
- * @return a Entry object
- * @throws FileExistsException
- * @throws IOException
- * @throws TypeMismatchException
- * @throws EncodingException
- * @throws JSONException
- */
- private JSONObject getFile(String dirPath, String fileName, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- boolean create = false;
- boolean exclusive = false;
- if (options != null) {
- create = options.optBoolean("create");
- if (create) {
- exclusive = options.optBoolean("exclusive");
- }
- }
-
- // Check for a ":" character in the file to line up with BB and iOS
- if (fileName.contains(":")) {
- throw new EncodingException("This file has a : in it's name");
- }
-
- File fp = createFileObject(dirPath, fileName);
-
- if (create) {
- if (exclusive && fp.exists()) {
- throw new FileExistsException("create/exclusive fails");
- }
- if (directory) {
- fp.mkdir();
- } else {
- fp.createNewFile();
- }
- if (!fp.exists()) {
- throw new FileExistsException("create fails");
- }
- }
- else {
- if (!fp.exists()) {
- throw new FileNotFoundException("path does not exist");
- }
- if (directory) {
- if (fp.isFile()) {
- throw new TypeMismatchException("path doesn't exist or is file");
- }
- } else {
- if (fp.isDirectory()) {
- throw new TypeMismatchException("path doesn't exist or is directory");
- }
- }
- }
+ return getEntry(destinationDir);
+ }
- // Return the directory
- return getEntry(fp);
- }
+ /**
+ * Deletes a directory and all of its contents, if any. In the event of an error
+ * [e.g. trying to delete a directory that contains a file that cannot be removed],
+ * some of the contents of the directory may be deleted.
+ * It is an error to attempt to delete the root directory of a filesystem.
+ *
+ * @param filePath the directory to be removed
+ * @return a boolean representing success of failure
+ * @throws FileExistsException
+ */
+ private boolean removeRecursively(String filePath) throws FileExistsException {
+ File fp = new File(filePath);
- /**
- * If the path starts with a '/' just return that file object. If not construct the file
- * object from the path passed in and the file name.
- *
- * @param dirPath root directory
- * @param fileName new file name
- * @return
- */
- private File createFileObject(String dirPath, String fileName) {
- File fp = null;
- if (fileName.startsWith("/")) {
- fp = new File(fileName);
- } else {
- fp = new File(dirPath + File.separator + fileName);
- }
- return fp;
- }
+ // You can't delete the root directory.
+ if (atRootDirectory(filePath)) {
+ return false;
+ }
- /**
- * Look up the parent DirectoryEntry containing this Entry.
- * If this Entry is the root of its filesystem, its parent is itself.
- *
- * @param filePath
- * @return
- * @throws JSONException
- */
- private JSONObject getParent(String filePath) throws JSONException {
- if (atRootDirectory(filePath)) {
- return getEntry(filePath);
- }
- return getEntry(new File(filePath).getParent());
- }
+ return removeDirRecursively(fp);
+ }
- /**
- * Checks to see if we are at the root directory. Useful since we are
- * not allow to delete this directory.
- *
- * @param filePath to directory
- * @return true if we are at the root, false otherwise.
- */
- private boolean atRootDirectory(String filePath) {
- if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getPackageName() + "/cache") ||
- filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
- return true;
- }
- return false;
- }
+ /**
+ * Loops through a directory deleting all the files.
+ *
+ * @param directory to be removed
+ * @return a boolean representing success of failure
+ * @throws FileExistsException
+ */
+ private boolean removeDirRecursively(File directory) throws FileExistsException {
+ if (directory.isDirectory()) {
+ for (File file : directory.listFiles()) {
+ removeDirRecursively(file);
+ }
+ }
- /**
- * Look up metadata about this entry.
- *
- * @param filePath to entry
- * @return a Metadata object
- * @throws FileNotFoundException
- * @throws JSONException
- */
- private JSONObject getMetadata(String filePath) throws FileNotFoundException, JSONException {
- File file = new File(filePath);
-
- if (!file.exists()) {
- throw new FileNotFoundException("Failed to find file in getMetadata");
- }
-
- JSONObject metadata = new JSONObject();
- metadata.put("modificationTime", file.lastModified());
+ if (!directory.delete()) {
+ throw new FileExistsException("could not delete: " + directory.getName());
+ } else {
+ return true;
+ }
+ }
- return metadata;
- }
+ /**
+ * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty.
+ * It is an error to attempt to delete the root directory of a filesystem.
+ *
+ * @param filePath file or directory to be removed
+ * @return a boolean representing success of failure
+ * @throws NoModificationAllowedException
+ * @throws InvalidModificationException
+ */
+ private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException {
+ File fp = new File(filePath);
- /**
- * Returns a File that represents the current state of the file that this FileEntry represents.
- *
- * @param filePath to entry
- * @return returns a JSONObject represent a W3C File object
- * @throws FileNotFoundException
- * @throws JSONException
- */
- private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException {
- File file = new File(filePath);
-
- if (!file.exists()) {
- throw new FileNotFoundException("File: " + filePath + " does not exist.");
- }
-
- JSONObject metadata = new JSONObject();
- metadata.put("size", file.length());
- metadata.put("type", getMimeType(filePath));
- metadata.put("name", file.getName());
- metadata.put("fullPath", file.getAbsolutePath());
- metadata.put("lastModifiedDate", file.lastModified());
+ // You can't delete the root directory.
+ if (atRootDirectory(filePath)) {
+ throw new NoModificationAllowedException("You can't delete the root directory");
+ }
- return metadata;
- }
+ // You can't delete a directory that is not empty
+ if (fp.isDirectory() && fp.list().length > 0) {
+ throw new InvalidModificationException("You can't delete a directory that is not empty.");
+ }
- /**
- * Requests a filesystem in which to store application data.
- *
- * @param type of file system requested
- * @return a JSONObject representing the file system
- * @throws IOException
- * @throws JSONException
- */
- private JSONObject requestFileSystem(int type) throws IOException, JSONException {
- JSONObject fs = new JSONObject();
- if (type == TEMPORARY) {
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- fs.put("name", "temporary");
- fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() +
- "/Android/data/" + ctx.getPackageName() + "/cache/"));
-
- // Create the cache dir if it doesn't exist.
- File fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
- "/Android/data/" + ctx.getPackageName() + "/cache/");
- fp.mkdirs();
- } else {
- throw new IOException("SD Card not mounted");
- }
- }
- else if (type == PERSISTENT) {
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- fs.put("name", "persistent");
- fs.put("root", getEntry(Environment.getExternalStorageDirectory()));
- } else {
- throw new IOException("SD Card not mounted");
- }
- }
- else if (type == RESOURCE) {
- fs.put("name", "resource");
-
- }
- else if (type == APPLICATION) {
- fs.put("name", "application");
-
- }
- else {
- throw new IOException("No filesystem of type requested");
- }
+ return fp.delete();
+ }
- return fs;
- }
+ /**
+ * Creates or looks up a file.
+ *
+ * @param dirPath base directory
+ * @param fileName file/directory to lookup or create
+ * @param options specify whether to create or not
+ * @param directory if true look up directory, if false look up file
+ * @return a Entry object
+ * @throws FileExistsException
+ * @throws IOException
+ * @throws TypeMismatchException
+ * @throws EncodingException
+ * @throws JSONException
+ */
+ private JSONObject getFile(String dirPath, String fileName, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ boolean create = false;
+ boolean exclusive = false;
+ if (options != null) {
+ create = options.optBoolean("create");
+ if (create) {
+ exclusive = options.optBoolean("exclusive");
+ }
+ }
- /**
- * Returns a JSON Object representing a directory on the device's file system
- *
- * @param path to the directory
- * @return
- * @throws JSONException
- */
- private JSONObject getEntry(File file) throws JSONException {
- JSONObject entry = new JSONObject();
+ // Check for a ":" character in the file to line up with BB and iOS
+ if (fileName.contains(":")) {
+ throw new EncodingException("This file has a : in it's name");
+ }
- entry.put("isFile", file.isFile());
- entry.put("isDirectory", file.isDirectory());
- entry.put("name", file.getName());
- entry.put("fullPath", file.getAbsolutePath());
- // I can't add the next thing it as it would be an infinite loop
- //entry.put("filesystem", null);
+ File fp = createFileObject(dirPath, fileName);
- return entry;
- }
+ if (create) {
+ if (exclusive && fp.exists()) {
+ throw new FileExistsException("create/exclusive fails");
+ }
+ if (directory) {
+ fp.mkdir();
+ } else {
+ fp.createNewFile();
+ }
+ if (!fp.exists()) {
+ throw new FileExistsException("create fails");
+ }
+ }
+ else {
+ if (!fp.exists()) {
+ throw new FileNotFoundException("path does not exist");
+ }
+ if (directory) {
+ if (fp.isFile()) {
+ throw new TypeMismatchException("path doesn't exist or is file");
+ }
+ } else {
+ if (fp.isDirectory()) {
+ throw new TypeMismatchException("path doesn't exist or is directory");
+ }
+ }
+ }
- /**
- * Returns a JSON Object representing a directory on the device's file system
- *
- * @param path to the directory
- * @return
- * @throws JSONException
- */
- private JSONObject getEntry(String path) throws JSONException {
- return getEntry(new File(path));
- }
+ // Return the directory
+ return getEntry(fp);
+ }
- /**
- * Identifies if action to be executed returns a value and should be run synchronously.
- *
- * @param action The action to execute
- * @return T=returns value
- */
- public boolean isSynch(String action) {
- if (action.equals("testSaveLocationExists")) {
- return true;
- }
- else if (action.equals("getFreeDiskSpace")) {
- return true;
- }
- else if (action.equals("testFileExists")) {
- return true;
- }
- else if (action.equals("testDirectoryExists")) {
- return true;
- }
- return false;
- }
+ /**
+ * If the path starts with a '/' just return that file object. If not construct the file
+ * object from the path passed in and the file name.
+ *
+ * @param dirPath root directory
+ * @param fileName new file name
+ * @return
+ */
+ private File createFileObject(String dirPath, String fileName) {
+ File fp = null;
+ if (fileName.startsWith("/")) {
+ fp = new File(fileName);
+ } else {
+ fp = new File(dirPath + File.separator + fileName);
+ }
+ return fp;
+ }
+
+ /**
+ * Look up the parent DirectoryEntry containing this Entry.
+ * If this Entry is the root of its filesystem, its parent is itself.
+ *
+ * @param filePath
+ * @return
+ * @throws JSONException
+ */
+ private JSONObject getParent(String filePath) throws JSONException {
+ if (atRootDirectory(filePath)) {
+ return getEntry(filePath);
+ }
+ return getEntry(new File(filePath).getParent());
+ }
+
+ /**
+ * Checks to see if we are at the root directory. Useful since we are
+ * not allow to delete this directory.
+ *
+ * @param filePath to directory
+ * @return true if we are at the root, false otherwise.
+ */
+ private boolean atRootDirectory(String filePath) {
+ if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getPackageName() + "/cache") ||
+ filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Look up metadata about this entry.
+ *
+ * @param filePath to entry
+ * @return a Metadata object
+ * @throws FileNotFoundException
+ * @throws JSONException
+ */
+ private JSONObject getMetadata(String filePath) throws FileNotFoundException, JSONException {
+ File file = new File(filePath);
+
+ if (!file.exists()) {
+ throw new FileNotFoundException("Failed to find file in getMetadata");
+ }
+
+ JSONObject metadata = new JSONObject();
+ metadata.put("modificationTime", file.lastModified());
+
+ return metadata;
+ }
+
+ /**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param filePath to entry
+ * @return returns a JSONObject represent a W3C File object
+ * @throws FileNotFoundException
+ * @throws JSONException
+ */
+ private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException {
+ File file = new File(filePath);
+
+ if (!file.exists()) {
+ throw new FileNotFoundException("File: " + filePath + " does not exist.");
+ }
+
+ JSONObject metadata = new JSONObject();
+ metadata.put("size", file.length());
+ metadata.put("type", getMimeType(filePath));
+ metadata.put("name", file.getName());
+ metadata.put("fullPath", file.getAbsolutePath());
+ metadata.put("lastModifiedDate", file.lastModified());
+
+ return metadata;
+ }
+
+ /**
+ * Requests a filesystem in which to store application data.
+ *
+ * @param type of file system requested
+ * @return a JSONObject representing the file system
+ * @throws IOException
+ * @throws JSONException
+ */
+ private JSONObject requestFileSystem(int type) throws IOException, JSONException {
+ JSONObject fs = new JSONObject();
+ if (type == TEMPORARY) {
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ fs.put("name", "temporary");
+ fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() +
+ "/Android/data/" + ctx.getPackageName() + "/cache/"));
+
+ // Create the cache dir if it doesn't exist.
+ File fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
+ "/Android/data/" + ctx.getPackageName() + "/cache/");
+ fp.mkdirs();
+ } else {
+ throw new IOException("SD Card not mounted");
+ }
+ }
+ else if (type == PERSISTENT) {
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ fs.put("name", "persistent");
+ fs.put("root", getEntry(Environment.getExternalStorageDirectory()));
+ } else {
+ throw new IOException("SD Card not mounted");
+ }
+ }
+ else if (type == RESOURCE) {
+ fs.put("name", "resource");
+
+ }
+ else if (type == APPLICATION) {
+ fs.put("name", "application");
+
+ }
+ else {
+ throw new IOException("No filesystem of type requested");
+ }
+
+ return fs;
+ }
+
+ /**
+ * Returns a JSON Object representing a directory on the device's file system
+ *
+ * @param path to the directory
+ * @return
+ * @throws JSONException
+ */
+ public JSONObject getEntry(File file) throws JSONException {
+ JSONObject entry = new JSONObject();
+
+ entry.put("isFile", file.isFile());
+ entry.put("isDirectory", file.isDirectory());
+ entry.put("name", file.getName());
+ entry.put("fullPath", file.getAbsolutePath());
+ // I can't add the next thing it as it would be an infinite loop
+ //entry.put("filesystem", null);
+
+ return entry;
+ }
+
+ /**
+ * Returns a JSON Object representing a directory on the device's file system
+ *
+ * @param path to the directory
+ * @return
+ * @throws JSONException
+ */
+ private JSONObject getEntry(String path) throws JSONException {
+ return getEntry(new File(path));
+ }
+
+ /**
+ * Identifies if action to be executed returns a value and should be run synchronously.
+ *
+ * @param action The action to execute
+ * @return T=returns value
+ */
+ public boolean isSynch(String action) {
+ if (action.equals("testSaveLocationExists")) {
+ return true;
+ }
+ else if (action.equals("getFreeDiskSpace")) {
+ return true;
+ }
+ else if (action.equals("testFileExists")) {
+ return true;
+ }
+ else if (action.equals("testDirectoryExists")) {
+ return true;
+ }
+ return false;
+ }
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------
-
+
/**
* Read content of text file.
- *
+ *
* @param filename The name of the file.
* @param encoding The encoding to return contents as. Typical value is UTF-8.
* (see http://www.iana.org/assignments/character-sets)
@@ -898,125 +896,125 @@ public class FileUtils extends Plugin {
* @throws FileNotFoundException, IOException
*/
public String readAsText(String filename, String encoding) throws FileNotFoundException, IOException {
- byte[] bytes = new byte[1000];
- BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- int numRead = 0;
- while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
- bos.write(bytes, 0, numRead);
- }
+ byte[] bytes = new byte[1000];
+ BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ int numRead = 0;
+ while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
+ bos.write(bytes, 0, numRead);
+ }
return new String(bos.toByteArray(), encoding);
}
-
+
/**
* Read content of text file and return as base64 encoded data url.
- *
+ *
* @param filename The name of the file.
* @return Contents of file = data:;base64,
* @throws FileNotFoundException, IOException
*/
public String readAsDataURL(String filename) throws FileNotFoundException, IOException {
- byte[] bytes = new byte[1000];
- BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- int numRead = 0;
- while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
- bos.write(bytes, 0, numRead);
- }
-
- // Determine content type from file name
- String contentType = null;
- if (filename.startsWith("content:")) {
- Uri fileUri = Uri.parse(filename);
- contentType = this.ctx.getContentResolver().getType(fileUri);
- }
- else {
- contentType = getMimeType(filename);
- }
+ byte[] bytes = new byte[1000];
+ BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ int numRead = 0;
+ while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
+ bos.write(bytes, 0, numRead);
+ }
- byte[] base64 = Base64.encodeBase64(bos.toByteArray());
- String data = "data:" + contentType + ";base64," + new String(base64);
- return data;
+ // Determine content type from file name
+ String contentType = null;
+ if (filename.startsWith("content:")) {
+ Uri fileUri = Uri.parse(filename);
+ contentType = this.ctx.getContentResolver().getType(fileUri);
+ }
+ else {
+ contentType = getMimeType(filename);
+ }
+
+ byte[] base64 = Base64.encodeBase64(bos.toByteArray());
+ String data = "data:" + contentType + ";base64," + new String(base64);
+ return data;
}
/**
* Looks up the mime type of a given file name.
- *
+ *
* @param filename
* @return a mime type
*/
- public static String getMimeType(String filename) {
- MimeTypeMap map = MimeTypeMap.getSingleton();
- return map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename));
- }
-
+ public static String getMimeType(String filename) {
+ MimeTypeMap map = MimeTypeMap.getSingleton();
+ return map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename));
+ }
+
/**
* Write contents of file.
- *
+ *
* @param filename The name of the file.
* @param data The contents of the file.
- * @param offset The position to begin writing the file.
+ * @param offset The position to begin writing the file.
* @throws FileNotFoundException, IOException
*/
/**/
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException {
- boolean append = false;
- if (offset > 0) {
- this.truncateFile(filename, offset);
- append = true;
- }
-
- byte [] rawData = data.getBytes();
- ByteArrayInputStream in = new ByteArrayInputStream(rawData);
- FileOutputStream out = new FileOutputStream(filename, append);
- byte buff[] = new byte[rawData.length];
- in.read(buff, 0, buff.length);
- out.write(buff, 0, rawData.length);
- out.flush();
- out.close();
-
- return data.length();
+ boolean append = false;
+ if (offset > 0) {
+ this.truncateFile(filename, offset);
+ append = true;
+ }
+
+ byte [] rawData = data.getBytes();
+ ByteArrayInputStream in = new ByteArrayInputStream(rawData);
+ FileOutputStream out = new FileOutputStream(filename, append);
+ byte buff[] = new byte[rawData.length];
+ in.read(buff, 0, buff.length);
+ out.write(buff, 0, rawData.length);
+ out.flush();
+ out.close();
+
+ return data.length();
}
-
+
/**
* Truncate the file to size
- *
+ *
* @param filename
* @param size
- * @throws FileNotFoundException, IOException
+ * @throws FileNotFoundException, IOException
*/
private long truncateFile(String filename, long size) throws FileNotFoundException, IOException {
- RandomAccessFile raf = new RandomAccessFile(filename, "rw");
+ RandomAccessFile raf = new RandomAccessFile(filename, "rw");
- if (raf.length() >= size) {
- FileChannel channel = raf.getChannel();
- channel.truncate(size);
- return size;
- }
-
- return raf.length();
+ if (raf.length() >= size) {
+ FileChannel channel = raf.getChannel();
+ channel.truncate(size);
+ return size;
+ }
+
+ return raf.length();
}
-
+
/**
* Get an input stream based on file path or content:// uri
- *
+ *
* @param path
* @return an input stream
- * @throws FileNotFoundException
+ * @throws FileNotFoundException
*/
- private InputStream getPathFromUri(String path) throws FileNotFoundException {
- if (path.startsWith("content")) {
- Uri uri = Uri.parse(path);
- return ctx.getContentResolver().openInputStream(uri);
- }
- else {
- return new FileInputStream(path);
- }
- }
-
+ private InputStream getPathFromUri(String path) throws FileNotFoundException {
+ if (path.startsWith("content")) {
+ Uri uri = Uri.parse(path);
+ return ctx.getContentResolver().openInputStream(uri);
+ }
+ else {
+ return new FileInputStream(path);
+ }
+ }
+
/**
* Queries the media store to find out what the file path is for the Uri we supply
- *
+ *
* @param contentUri the Uri of the audio/image/video
* @param ctx the current applicaiton context
* @return the full path to the file
diff --git a/framework/src/com/phonegap/HttpHandler.java b/framework/src/com/phonegap/HttpHandler.java
index 156d5a2c..3893d2a9 100755
--- a/framework/src/com/phonegap/HttpHandler.java
+++ b/framework/src/com/phonegap/HttpHandler.java
@@ -18,8 +18,8 @@
*/
package com.phonegap;
-import java.io.EOFException;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
@@ -56,27 +56,25 @@ public class HttpHandler {
return entity;
}
- private void writeToDisk(HttpEntity entity, String file) throws EOFException
+ private void writeToDisk(HttpEntity entity, String file) throws IllegalStateException, IOException
/**
* writes a HTTP entity to the specified filename and location on disk
*/
{
int i=0;
String FilePath="/sdcard/" + file;
- try {
- InputStream in = entity.getContent();
- byte buff[] = new byte[1024];
- FileOutputStream out=
- new FileOutputStream(FilePath);
- do {
- int numread = in.read(buff);
- if (numread <= 0)
- break;
- out.write(buff, 0, numread);
- i++;
- } while (true);
- out.flush();
- out.close();
- } catch (Exception e) { e.printStackTrace(); }
+ InputStream in = entity.getContent();
+ byte buff[] = new byte[1024];
+ FileOutputStream out=
+ new FileOutputStream(FilePath);
+ do {
+ int numread = in.read(buff);
+ if (numread <= 0)
+ break;
+ out.write(buff, 0, numread);
+ i++;
+ } while (true);
+ out.flush();
+ out.close();
}
}
diff --git a/framework/src/com/phonegap/WebViewReflect.java b/framework/src/com/phonegap/WebViewReflect.java
deleted file mode 100644
index 22f57d3f..00000000
--- a/framework/src/com/phonegap/WebViewReflect.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package com.phonegap;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import android.webkit.WebSettings;
-
-public class WebViewReflect {
- private static Method mWebSettings_setDatabaseEnabled;
- private static Method mWebSettings_setDatabasePath;
- private static Method mWebSettings_setDomStorageEnabled;
- private static Method mWebSettings_setGeolocationEnabled;
-
- static
- {
- checkCompatibility();
- }
-
- private static void setDatabaseEnabled(boolean e) throws IOException {
- try
- {
- mWebSettings_setDatabaseEnabled.invoke(e);
- }
- catch (InvocationTargetException ite) {
- /* unpack original exception when possible */
- Throwable cause = ite.getCause();
- if (cause instanceof IOException) {
- throw (IOException) cause;
- } else if (cause instanceof RuntimeException) {
- throw (RuntimeException) cause;
- } else if (cause instanceof Error) {
- throw (Error) cause;
- } else {
- /* unexpected checked exception; wrap and re-throw */
- throw new RuntimeException(ite);
- }
- } catch (IllegalAccessException ie) {
- System.err.println("unexpected " + ie);
- }
- }
-
-
- public static void checkCompatibility() {
- try {
- mWebSettings_setDatabaseEnabled = WebSettings.class.getMethod(
- "setDatabaseEnabled", new Class[] { boolean.class } );
- mWebSettings_setDatabasePath = WebSettings.class.getMethod(
- "setDatabasePath", new Class[] { String.class });
- mWebSettings_setDomStorageEnabled = WebSettings.class.getMethod(
- "setDomStorageEnabled", new Class[] { boolean.class });
- mWebSettings_setGeolocationEnabled = WebSettings.class.getMethod(
- "setGeolocationEnabled", new Class[] { boolean.class });
- /* success, this is a newer device */
- } catch (NoSuchMethodException nsme) {
- /* failure, must be older device */
- }
- }
-
- public static void setStorage(WebSettings setting, boolean enable, String path) {
- if (mWebSettings_setDatabaseEnabled != null) {
- /* feature is supported */
- try {
- mWebSettings_setDatabaseEnabled.invoke(setting, enable);
- mWebSettings_setDatabasePath.invoke(setting, path);
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } else {
- /* feature not supported, do something else */
- }
- }
- public static void setGeolocationEnabled(WebSettings setting, boolean enable) {
- if (mWebSettings_setGeolocationEnabled != null) {
- /* feature is supported */
- try {
- mWebSettings_setGeolocationEnabled.invoke(setting, enable);
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } else {
- /* feature not supported, do something else */
- System.out.println("Native Geolocation not supported - we're ok");
- }
- }
- public static void setDomStorage(WebSettings setting)
- {
- if(mWebSettings_setDomStorageEnabled != null)
- {
- /* feature is supported */
- try {
- mWebSettings_setDomStorageEnabled.invoke(setting, true);
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } else {
- /* feature not supported, do something else */
- }
-
- }
-}