\r
import android.content.ContentProvider;\r
import android.content.ContentValues;\r
+import android.content.UriMatcher;\r
import android.database.Cursor;\r
-import android.database.MatrixCursor;\r
import android.net.Uri;\r
import android.os.ParcelFileDescriptor;\r
-import android.provider.MediaStore.Images;\r
+import android.util.Log;\r
\r
public class CryptoContentProvider extends ContentProvider {\r
\r
- private static final String MIME_TYPE_PREFIX = "content://org.openintents.safe/decrypted/";\r
+ private static final boolean debug = true;\r
private static final String TAG = "CryptoContentProvider";\r
+\r
public static final String AUTHORITY = "org.openintents.safe";\r
+ public static final Uri CONTENT_URI\r
+ =Uri.parse("content://"+AUTHORITY);\r
+\r
+ public static final String SESSION_FILE = "session";\r
+ \r
+ private static final int ENCRYPT_ID = 2;\r
+ private static final int DECRYPT_ID = 3;\r
+\r
+ private static final UriMatcher sUriMatcher;\r
\r
+ static {\r
+ sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);\r
+ sUriMatcher.addURI(AUTHORITY, "encrypt/*", ENCRYPT_ID);\r
+ sUriMatcher.addURI(AUTHORITY, "decrypt/*", DECRYPT_ID);\r
+ }\r
+ \r
@Override\r
public boolean onCreate() {\r
return true;\r
@Override\r
public ParcelFileDescriptor openFile(Uri uri, String mode)\r
throws FileNotFoundException {\r
- if (uri.toString().startsWith(\r
- MIME_TYPE_PREFIX)) {\r
- int m = ParcelFileDescriptor.MODE_READ_ONLY;\r
- if (mode.equalsIgnoreCase("rw"))\r
- m = ParcelFileDescriptor.MODE_READ_WRITE;\r
- \r
- File f = new File(uri.toString().substring(20 + AUTHORITY.length()));\r
- ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f, m);\r
- return pfd;\r
- } else {\r
- throw new RuntimeException("Unsupported uri");\r
+ if (debug) Log.d(TAG,"openFile("+uri.toString()+","+mode+")");\r
+\r
+ ParcelFileDescriptor pfd = null;\r
+ try {\r
+ String filesDir=getContext().getFilesDir().toString();\r
+ if (debug) Log.d(TAG,"openFile: filesDir="+filesDir);\r
+\r
+ String path=filesDir;\r
+ String cryptSession;\r
+ String sessionFile;\r
+ int modeBits = 0;\r
+ switch (sUriMatcher.match(uri)) {\r
+ case ENCRYPT_ID:\r
+ if (debug) Log.d(TAG,"openFile: ENCRYPT");\r
+ modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY |\r
+ ParcelFileDescriptor.MODE_CREATE;\r
+ cryptSession = uri.getPathSegments().get(1);\r
+ sessionFile=SESSION_FILE+"."+cryptSession;\r
+ path += "/"+sessionFile;\r
+ break;\r
+ case DECRYPT_ID:\r
+ if (debug) Log.d(TAG,"openFile: DECRYPT");\r
+ modeBits = ParcelFileDescriptor.MODE_READ_ONLY;\r
+ cryptSession = uri.getPathSegments().get(1);\r
+ sessionFile=SESSION_FILE+"."+cryptSession;\r
+ path += "/"+sessionFile;\r
+ break;\r
+ default:\r
+ throw new IllegalArgumentException("Unknown URI " + uri);\r
+ }\r
+\r
+ if (debug) Log.d(TAG,"openFile: path="+path);\r
+ pfd=ParcelFileDescriptor.open(new File(path), modeBits);\r
+ if (!getContext().deleteFile(sessionFile)) {\r
+ Log.e(TAG,"openFile: unable to delete: "+sessionFile);\r
+ }\r
+ } catch (FileNotFoundException e) {\r
+ if (debug) Log.d(TAG,"openFile: FileNotFound");\r
+ throw e;\r
+ } catch (IllegalArgumentException e) {\r
+ throw e;\r
}\r
+\r
+ return pfd;\r
}\r
\r
@Override\r
import org.openintents.util.SecureDelete;\r
\r
import android.content.ContentResolver;\r
+import android.content.Context;\r
import android.net.Uri;\r
import android.os.Environment;\r
import android.util.Log;\r
*/\r
public class CryptoHelper {\r
\r
- private static final boolean debug = false;\r
+ private static final boolean debug = true;\r
private static String TAG = "CryptoHelper";\r
protected static PBEKeySpec pbeKeySpec;\r
protected static PBEParameterSpec pbeParamSpec;\r
* @return decrypted String\r
* @throws Exception\r
*/\r
- public Uri decryptFileWithSessionKey(ContentResolver contentResolver, Uri fileUri) throws CryptoHelperException {\r
+ public Uri decryptFileWithSessionKey(Context ctx, ContentResolver contentResolver, Uri fileUri) throws CryptoHelperException {\r
Log.d(TAG, "decryptFileWithSessionKey");\r
+ Log.d(TAG, "fileUri="+fileUri.toString());\r
status=false; // assume failure\r
if(password == null) {\r
String msg = "Must call setPassword before running decrypt.";\r
throw new CryptoHelperException(msg);\r
}\r
\r
- String outputPath = "";\r
+ String decryptSession;\r
+ try {\r
+ decryptSession=generateSalt();\r
+ } catch (NoSuchAlgorithmException e1) {\r
+ e1.printStackTrace();\r
+ String msg = "Decrypt error: "+e1.getLocalizedMessage();\r
+ throw new CryptoHelperException(msg);\r
+ }\r
+ String outputFile = "";\r
try {\r
InputStream is;\r
if (fileUri.getScheme().equals("file")) {\r
is = new java.io.FileInputStream(fileUri.getPath());\r
- String encryptedFile = fileUri.getPath();\r
- outputPath = fileUri.getPath() + ".decrypted";\r
- if (encryptedFile.endsWith(".oisafe")) {\r
- outputPath = encryptedFile.substring(0, encryptedFile.length() - 7);\r
- }\r
- Log.d(TAG, "Decrypt: Input from " + fileUri.getPath());\r
- Log.d(TAG, "Decrypt: Output to " + outputPath);\r
+ if (debug) Log.d(TAG, "Decrypt: Input from " + fileUri.getPath());\r
} else {\r
is = contentResolver.openInputStream(fileUri);\r
- outputPath = Environment\r
- .getExternalStorageDirectory().toString() + "/tmp.decrypted";\r
+ if (debug) Log.d(TAG, "Decrypt: Input from " + fileUri.toString());\r
}\r
- \r
- FileOutputStream os = new FileOutputStream(outputPath);\r
+ outputFile = CryptoContentProvider.SESSION_FILE+"."+decryptSession;\r
+ if (debug) Log.d(TAG, "Decrypt: Output to " + outputFile);\r
+ String cache=Environment.getDownloadCacheDirectory().getAbsolutePath();\r
+ if (debug) Log.d(TAG, "Decrypt: cache=" + cache);\r
+ FileOutputStream os = ctx.openFileOutput(outputFile,\r
+ Context.MODE_PRIVATE);\r
\r
int numReadTotal = 0;\r
int numRead = 0;\r
while ((numRead = is.read(byteCipherVersion, numRead, \r
byteCipherVersion.length - numRead)) >= 0\r
&& numReadTotal < byteCipherVersion.length) {\r
- Log.d(TAG, "read bytes: " + numRead);\r
+ if (debug) Log.d(TAG, "read bytes: " + numRead);\r
numReadTotal += numRead;\r
}\r
String cipherVersion = new String(byteCipherVersion);\r
\r
// Split cipher into session key and text\r
try {\r
- Log.d(TAG, "cipherVersion : " + cipherVersion);\r
+ if (debug) Log.d(TAG, "cipherVersion : " + cipherVersion);\r
if (cipherVersion.equals("A")) {\r
\r
numRead = 0;\r
while ((numRead = is.read(byteCipherSessionKey, numRead, \r
byteCipherSessionKey.length - numRead)) >= 0\r
&& numReadTotal < byteCipherSessionKey.length) {\r
- Log.d(TAG, "read bytes sessionKey: " + numRead);\r
+ if (debug) Log.d(TAG, "read bytes sessionKey: " + numRead);\r
numReadTotal += numRead;\r
}\r
} else {\r
numRead = 0;\r
while ((numRead = is.read(bytesIn, 0, bytesLen)) >= 0) {\r
if ((numRead & 3) != 0) {\r
- Log.d(TAG, "Bytes read is inappropriate number: " + numRead);\r
+ if (debug) Log.d(TAG, "Bytes read is inappropriate number: " + numRead);\r
}\r
\r
tri.process(bytesIn, 0,\r
os.close();\r
\r
// Securely delete the original file:\r
- SecureDelete.delete(new File(fileUri.getPath()));\r
+// SecureDelete.delete(new File(fileUri.getPath()));\r
\r
} catch (ESJException e) {\r
Log.e(TAG, "Error encrypting file", e);\r
} catch (IOException e) {\r
Log.e(TAG, "IOException", e);\r
}\r
- return Uri.parse("file://" + outputPath); // TODO: UUEncode\r
+// return Uri.parse("file://" + outputPath); // TODO: UUEncode\r
+ Uri uri=Uri.withAppendedPath(CryptoContentProvider.CONTENT_URI, "decrypt/" + decryptSession);\r
+ return uri;\r
}\r
}\r