mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-11 11:35:07 -05:00
removed deprecated code, reworked service blob provider
This commit is contained in:
parent
d61e00ae6c
commit
e247fe18af
@ -357,6 +357,13 @@
|
||||
android:authorities="org.thialfihar.android.apg"
|
||||
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
|
||||
|
||||
|
||||
<!-- TODO: authority! -->
|
||||
<provider
|
||||
android:name=".provider.ApgServiceBlobProvider"
|
||||
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider"
|
||||
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" />
|
||||
|
||||
<!-- DEPRECATED: -->
|
||||
<!-- <provider -->
|
||||
<!-- android:name=".deprecated.DataProvider" -->
|
||||
@ -381,11 +388,6 @@
|
||||
<!-- android:value="2" /> -->
|
||||
<!-- </service> -->
|
||||
|
||||
|
||||
<!-- <provider -->
|
||||
<!-- android:name=".deprecated.ApgServiceBlobProvider" -->
|
||||
<!-- android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider" -->
|
||||
<!-- android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" /> -->
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -1,836 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Markus Doits <markus.doits@googlemail.com>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.deprecated;
|
||||
|
||||
import org.thialfihar.android.apg.deprecated.ApgConInterface.OnCallFinishListener;
|
||||
import org.thialfihar.android.apg.deprecated.IApgService2;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import org.thialfihar.android.apg.util.Log;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A APG-AIDL-Wrapper
|
||||
*
|
||||
* <p>
|
||||
* This class can be used by other projects to simplify connecting to the
|
||||
* APG-AIDL-Service. Kind of wrapper of for AIDL.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It is not used in this project.
|
||||
* </p>
|
||||
*
|
||||
* @author Markus Doits <markus.doits@googlemail.com>
|
||||
* @version 1.1rc1
|
||||
*
|
||||
*/
|
||||
public class ApgCon {
|
||||
private static final boolean LOCAL_LOGV = true;
|
||||
private static final boolean LOCAL_LOGD = true;
|
||||
|
||||
private final static String TAG = "ApgCon";
|
||||
private final static int API_VERSION = 2; // aidl api-version it expects
|
||||
private final static String BLOB_URI = "content://org.thialfihar.android.apg.provider.apgserviceblobprovider";
|
||||
|
||||
/**
|
||||
* How many seconds to wait for a connection to AGP when connecting.
|
||||
* Being unsuccessful for this number of seconds, a connection
|
||||
* is assumed to be failed.
|
||||
*/
|
||||
public int secondsToWaitForConnection = 15;
|
||||
|
||||
private class CallAsync extends AsyncTask<String, Void, Void> {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(String... arg) {
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "Async execution starting");
|
||||
call(arg[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Void res) {
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "Async execution finished");
|
||||
mAsyncRunning = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final error mConnectionStatus;
|
||||
private boolean mAsyncRunning = false;
|
||||
private OnCallFinishListener mOnCallFinishListener;
|
||||
|
||||
private final Bundle mResult = new Bundle();
|
||||
private final Bundle mArgs = new Bundle();
|
||||
private final ArrayList<String> mErrorList = new ArrayList<String>();
|
||||
private final ArrayList<String> mWarningList = new ArrayList<String>();
|
||||
|
||||
/** Remote service for decrypting and encrypting data */
|
||||
private IApgService2 mApgService = null;
|
||||
|
||||
/** Set apgService accordingly to connection status */
|
||||
private ServiceConnection mApgConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "IApgService bound to apgService");
|
||||
mApgService = IApgService2.Stub.asInterface(service);
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "IApgService disconnected");
|
||||
mApgService = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Different types of local errors
|
||||
*/
|
||||
public static enum error {
|
||||
/**
|
||||
* no error
|
||||
*/
|
||||
NO_ERROR,
|
||||
/**
|
||||
* generic error
|
||||
*/
|
||||
GENERIC,
|
||||
/**
|
||||
* connection to apg service not possible
|
||||
*/
|
||||
CANNOT_BIND_TO_APG,
|
||||
/**
|
||||
* function to call not provided
|
||||
*/
|
||||
CALL_MISSING,
|
||||
/**
|
||||
* apg service does not know what to do
|
||||
*/
|
||||
CALL_NOT_KNOWN,
|
||||
/**
|
||||
* could not find APG being installed
|
||||
*/
|
||||
APG_NOT_FOUND,
|
||||
/**
|
||||
* found APG but without AIDL interface
|
||||
*/
|
||||
APG_AIDL_MISSING,
|
||||
/**
|
||||
* found APG but with wrong API
|
||||
*/
|
||||
APG_API_MISSMATCH
|
||||
}
|
||||
|
||||
private static enum ret {
|
||||
ERROR, // returned from AIDL
|
||||
RESULT, // returned from AIDL
|
||||
WARNINGS, // mixed AIDL and LOCAL
|
||||
ERRORS, // mixed AIDL and LOCAL
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* <p>
|
||||
* Creates a new ApgCon object and searches for the right APG version on
|
||||
* initialization. If not found, errors are printed to the error log.
|
||||
* </p>
|
||||
*
|
||||
* @param ctx
|
||||
* the running context
|
||||
*/
|
||||
public ApgCon(Context ctx) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "EncryptionService created");
|
||||
mContext = ctx;
|
||||
|
||||
error tmpError = null;
|
||||
try {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "Searching for the right APG version");
|
||||
ServiceInfo apgServices[] = ctx.getPackageManager().getPackageInfo("org.thialfihar.android.apg",
|
||||
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA).services;
|
||||
if (apgServices == null) {
|
||||
Log.e(TAG, "Could not fetch services");
|
||||
tmpError = error.GENERIC;
|
||||
} else {
|
||||
boolean apgServiceFound = false;
|
||||
for (ServiceInfo inf : apgServices) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "Found service of APG: " + inf.name);
|
||||
if (inf.name.equals("org.thialfihar.android.apg.ApgService")) {
|
||||
apgServiceFound = true;
|
||||
if (inf.metaData == null) {
|
||||
Log.w(TAG, "Could not determine ApgService API");
|
||||
Log.w(TAG, "This probably won't work!");
|
||||
mWarningList.add("(LOCAL) Could not determine ApgService API");
|
||||
tmpError = error.APG_API_MISSMATCH;
|
||||
} else if (inf.metaData.getInt("api_version") != API_VERSION) {
|
||||
Log.w(TAG, "Found ApgService API version " + inf.metaData.getInt("api_version") + " but exspected " + API_VERSION);
|
||||
Log.w(TAG, "This probably won't work!");
|
||||
mWarningList.add("(LOCAL) Found ApgService API version " + inf.metaData.getInt("api_version") + " but exspected " + API_VERSION);
|
||||
tmpError = error.APG_API_MISSMATCH;
|
||||
} else {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "Found api_version " + API_VERSION + ", everything should work");
|
||||
tmpError = error.NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!apgServiceFound) {
|
||||
Log.e(TAG, "Could not find APG with AIDL interface, this probably won't work");
|
||||
mErrorList.add("(LOCAL) Could not find APG with AIDL interface, this probably won't work");
|
||||
mResult.putInt(ret.ERROR.name(), error.APG_AIDL_MISSING.ordinal());
|
||||
tmpError = error.APG_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Could not find APG, is it installed?", e);
|
||||
mErrorList.add("(LOCAL) Could not find APG, is it installed?");
|
||||
mResult.putInt(ret.ERROR.name(), error.APG_NOT_FOUND.ordinal());
|
||||
tmpError = error.APG_NOT_FOUND;
|
||||
}
|
||||
|
||||
mConnectionStatus = tmpError;
|
||||
|
||||
}
|
||||
|
||||
/** try to connect to the apg service */
|
||||
private boolean connect() {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "trying to bind the apgService to context");
|
||||
|
||||
if (mApgService != null) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "allready connected");
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
mContext.bindService(new Intent(IApgService2.class.getName()), mApgConnection, Context.BIND_AUTO_CREATE);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "could not bind APG service", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
int waitCount = 0;
|
||||
while (mApgService == null && waitCount++ < secondsToWaitForConnection) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "sleeping 1 second to wait for apg");
|
||||
android.os.SystemClock.sleep(1000);
|
||||
}
|
||||
|
||||
if (waitCount >= secondsToWaitForConnection) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "slept waiting for nothing!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects ApgCon from Apg
|
||||
*
|
||||
* <p>
|
||||
* This should be called whenever all work with APG is done (e.g. everything
|
||||
* you wanted to encrypt is encrypted), since connections with AIDL should
|
||||
* not be upheld indefinitely.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* Also, if you destroy you end using your ApgCon-instance, this must be
|
||||
* called or else the connection to APG is leaked
|
||||
* </p>
|
||||
*/
|
||||
public void disconnect() {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "disconnecting apgService");
|
||||
if (mApgService != null) {
|
||||
mContext.unbindService(mApgConnection);
|
||||
mApgService = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initialize() {
|
||||
if (mApgService == null) {
|
||||
if (!connect()) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "connection to apg service failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a function from APG's AIDL-interface
|
||||
*
|
||||
* <p>
|
||||
* After you have set up everything with {@link #setArg(String, String)}
|
||||
* (and variants), you can call a function of the AIDL-interface. This
|
||||
* will:
|
||||
* <ul>
|
||||
* <li>start connection to the remote interface (if not already connected)</li>
|
||||
* <li>call the function passed with all parameters synchronously</li>
|
||||
* <li>set up everything to retrieve the result and/or warnings/errors</li>
|
||||
* <li>call the callback if provided
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note your thread will be blocked during execution - if you want to call
|
||||
* the function asynchronously, see {@link #callAsync(String)}.
|
||||
* </p>
|
||||
*
|
||||
* @param function
|
||||
* a remote function to call
|
||||
* @return true, if call successful (= no errors), else false
|
||||
*
|
||||
* @see #callAsync(String)
|
||||
* @see #setArg(String, String)
|
||||
* @see #setOnCallFinishListener(OnCallFinishListener)
|
||||
*/
|
||||
public boolean call(String function) {
|
||||
boolean success = this.call(function, mArgs, mResult);
|
||||
if (mOnCallFinishListener != null) {
|
||||
try {
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "About to execute callback");
|
||||
mOnCallFinishListener.onCallFinish(mResult);
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "Callback executed");
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Exception on callback: (" + e.getClass() + ") " + e.getMessage(), e);
|
||||
mWarningList.add("(LOCAL) Could not execute callback (" + e.getClass() + "): " + e.getMessage());
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a function of remote interface asynchronously
|
||||
*
|
||||
* <p>
|
||||
* This does exactly the same as {@link #call(String)}, but asynchronously.
|
||||
* While connection to APG and work are done in background, your thread can
|
||||
* go on executing.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* To see whether the task is finished, you have two possibilities:
|
||||
* <ul>
|
||||
* <li>In your thread, poll {@link #isRunning()}</li>
|
||||
* <li>Supply a callback with {@link #setOnCallFinishListener(OnCallFinishListener)}</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param function
|
||||
* a remote function to call
|
||||
*
|
||||
* @see #call(String)
|
||||
* @see #isRunning()
|
||||
* @see #setOnCallFinishListener(OnCallFinishListener)
|
||||
*/
|
||||
public void callAsync(String function) {
|
||||
mAsyncRunning = true;
|
||||
new CallAsync().execute(function);
|
||||
}
|
||||
|
||||
private boolean call(String function, Bundle pArgs, Bundle pReturn) {
|
||||
|
||||
if (!initialize()) {
|
||||
mErrorList.add("(LOCAL) Cannot bind to ApgService");
|
||||
mResult.putInt(ret.ERROR.name(), error.CANNOT_BIND_TO_APG.ordinal());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (function == null || function.length() == 0) {
|
||||
mErrorList.add("(LOCAL) Function to call missing");
|
||||
mResult.putInt(ret.ERROR.name(), error.CALL_MISSING.ordinal());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Boolean success = (Boolean) IApgService2.class.getMethod(function, Bundle.class, Bundle.class).invoke(mApgService, pArgs, pReturn);
|
||||
mErrorList.addAll(pReturn.getStringArrayList(ret.ERRORS.name()));
|
||||
mWarningList.addAll(pReturn.getStringArrayList(ret.WARNINGS.name()));
|
||||
return success;
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(TAG, "Remote call not known (" + function + "): " + e.getMessage(), e);
|
||||
mErrorList.add("(LOCAL) Remote call not known (" + function + "): " + e.getMessage());
|
||||
mResult.putInt(ret.ERROR.name(), error.CALL_NOT_KNOWN.ordinal());
|
||||
return false;
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable orig = e.getTargetException();
|
||||
Log.w(TAG, "Exception of type '" + orig.getClass() + "' on AIDL call '" + function + "': " + orig.getMessage(), orig);
|
||||
mErrorList.add("(LOCAL) Exception of type '" + orig.getClass() + "' on AIDL call '" + function + "': " + orig.getMessage());
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Generic error (" + e.getClass() + "): " + e.getMessage(), e);
|
||||
mErrorList.add("(LOCAL) Generic error (" + e.getClass() + "): " + e.getMessage());
|
||||
mResult.putInt(ret.ERROR.name(), error.GENERIC.ordinal());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a string argument for APG
|
||||
*
|
||||
* <p>
|
||||
* This defines a string argument for APG's AIDL-interface.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* To know what key-value-pairs are possible (or required), take a look into
|
||||
* the IApgService.aidl
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note that parameters are not reseted after a call, so you have to
|
||||
* reset ({@link #clearArgs()}) them manually if you want to.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param key
|
||||
* the key
|
||||
* @param val
|
||||
* the value
|
||||
*
|
||||
* @see #clearArgs()
|
||||
*/
|
||||
public void setArg(String key, String val) {
|
||||
mArgs.putString(key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a string-array argument for APG
|
||||
*
|
||||
* <p>
|
||||
* If the AIDL-parameter is an {@literal ArrayList<String>}, you have to use
|
||||
* this function.
|
||||
* </p>
|
||||
*
|
||||
* <code>
|
||||
* <pre>
|
||||
* setArg("a key", new String[]{ "entry 1", "entry 2" });
|
||||
* </pre>
|
||||
* </code>
|
||||
*
|
||||
* @param key
|
||||
* the key
|
||||
* @param vals
|
||||
* the value
|
||||
*
|
||||
* @see #setArg(String, String)
|
||||
*/
|
||||
public void setArg(String key, String vals[]) {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
for (String val : vals) {
|
||||
list.add(val);
|
||||
}
|
||||
mArgs.putStringArrayList(key, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a boolean argument for APG
|
||||
*
|
||||
* @param key
|
||||
* the key
|
||||
* @param vals
|
||||
* the value
|
||||
*
|
||||
* @see #setArg(String, String)
|
||||
*/
|
||||
public void setArg(String key, boolean val) {
|
||||
mArgs.putBoolean(key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a int argument for APG
|
||||
*
|
||||
* @param key
|
||||
* the key
|
||||
* @param vals
|
||||
* the value
|
||||
*
|
||||
* @see #setArg(String, String)
|
||||
*/
|
||||
public void setArg(String key, int val) {
|
||||
mArgs.putInt(key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a int-array argument for APG
|
||||
* <p>
|
||||
* If the AIDL-parameter is an {@literal ArrayList<Integer>}, you have to
|
||||
* use this function.
|
||||
* </p>
|
||||
*
|
||||
* @param key
|
||||
* the key
|
||||
* @param vals
|
||||
* the value
|
||||
*
|
||||
* @see #setArg(String, String)
|
||||
*/
|
||||
public void setArg(String key, int vals[]) {
|
||||
ArrayList<Integer> list = new ArrayList<Integer>();
|
||||
for (int val : vals) {
|
||||
list.add(val);
|
||||
}
|
||||
mArgs.putIntegerArrayList(key, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up binary data to en/decrypt
|
||||
*
|
||||
* @param is
|
||||
* InputStream to get the data from
|
||||
*/
|
||||
public void setBlob(InputStream is) {
|
||||
if( LOCAL_LOGD ) Log.d(TAG, "setBlob() called");
|
||||
// 1. get the new contentUri
|
||||
ContentResolver cr = mContext.getContentResolver();
|
||||
Uri contentUri = cr.insert(Uri.parse(BLOB_URI), new ContentValues());
|
||||
|
||||
// 2. insert binary data
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = cr.openOutputStream(contentUri, "w");
|
||||
} catch( Exception e ) {
|
||||
Log.e(TAG, "... exception on setBlob", e);
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[8];
|
||||
int len = 0;
|
||||
try {
|
||||
while( (len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
if(LOCAL_LOGD) Log.d(TAG, "... write finished, now closing");
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "... error on writing buffer", e);
|
||||
}
|
||||
|
||||
mArgs.putString("BLOB", contentUri.toString() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all arguments
|
||||
*
|
||||
* <p>
|
||||
* Anything the has been set up with the various
|
||||
* {@link #setArg(String, String)} functions is cleared.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note that any warning, error, callback, result, etc. is NOT cleared with
|
||||
* this.
|
||||
* </p>
|
||||
*
|
||||
* @see #reset()
|
||||
*/
|
||||
public void clearArgs() {
|
||||
mArgs.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object associated with the key
|
||||
*
|
||||
* @param key
|
||||
* the object's key you want to return
|
||||
* @return an object at position key, or null if not set
|
||||
*/
|
||||
public Object getArg(String key) {
|
||||
return mArgs.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through the errors
|
||||
*
|
||||
* <p>
|
||||
* With this method you can iterate through all errors. The errors are only
|
||||
* returned once and deleted immediately afterwards, so you can only return
|
||||
* each error once.
|
||||
* </p>
|
||||
*
|
||||
* @return a human readable description of a error that happened, or null if
|
||||
* no more errors
|
||||
*
|
||||
* @see #hasNextError()
|
||||
* @see #clearErrors()
|
||||
*/
|
||||
public String getNextError() {
|
||||
if (mErrorList.size() != 0)
|
||||
return mErrorList.remove(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are any new errors
|
||||
*
|
||||
* @return true, if there are unreturned errors, false otherwise
|
||||
*
|
||||
* @see #getNextError()
|
||||
*/
|
||||
public boolean hasNextError() {
|
||||
return mErrorList.size() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numeric representation of the last error
|
||||
*
|
||||
* <p>
|
||||
* Values <100 mean the error happened locally, values >=100 mean the error
|
||||
* happened at the remote side (APG). See the IApgService.aidl (or get the
|
||||
* human readable description with {@link #getNextError()}) for what
|
||||
* errors >=100 mean.
|
||||
* </p>
|
||||
*
|
||||
* @return the id of the error that happened
|
||||
*/
|
||||
public int getError() {
|
||||
if (mResult.containsKey(ret.ERROR.name()))
|
||||
return mResult.getInt(ret.ERROR.name());
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through the warnings
|
||||
*
|
||||
* <p>
|
||||
* With this method you can iterate through all warnings. Warnings are
|
||||
* only returned once and deleted immediately afterwards, so you can only
|
||||
* return each warning once.
|
||||
* </p>
|
||||
*
|
||||
* @return a human readable description of a warning that happened, or null
|
||||
* if no more warnings
|
||||
*
|
||||
* @see #hasNextWarning()
|
||||
* @see #clearWarnings()
|
||||
*/
|
||||
public String getNextWarning() {
|
||||
if (mWarningList.size() != 0)
|
||||
return mWarningList.remove(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are any new warnings
|
||||
*
|
||||
* @return true, if there are unreturned warnings, false otherwise
|
||||
*
|
||||
* @see #getNextWarning()
|
||||
*/
|
||||
public boolean hasNextWarning() {
|
||||
return mWarningList.size() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result
|
||||
*
|
||||
* <p>
|
||||
* This gets your result. After doing an encryption or decryption with APG,
|
||||
* you get the output with this function.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note when your last remote call is unsuccessful, the result will
|
||||
* still have the same value like the last successful call (or null, if no
|
||||
* call was successful). To ensure you do not work with old call's results,
|
||||
* either be sure to {@link #reset()} (or at least {@link #clearResult()})
|
||||
* your instance before each new call or always check that
|
||||
* {@link #hasNextError()} is false.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note: When handling binary data with {@link #setBlob(InputStream)}, you
|
||||
* get your result with {@link #getBlobResult()}.
|
||||
* </p>
|
||||
*
|
||||
* @return the mResult of the last {@link #call(String)} or
|
||||
* {@link #callAsync(String)}.
|
||||
*
|
||||
* @see #reset()
|
||||
* @see #clearResult()
|
||||
* @see #getResultBundle()
|
||||
* @see #getBlobResult()
|
||||
*/
|
||||
public String getResult() {
|
||||
return mResult.getString(ret.RESULT.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the binary result
|
||||
*
|
||||
* <p>
|
||||
* This gets your binary result. It only works if you called {@link #setBlob(InputStream)} before.
|
||||
*
|
||||
* If you did not call encrypt nor decrypt, this will be the same data as you inputed.
|
||||
* </p>
|
||||
*
|
||||
* @return InputStream of the binary data which was en/decrypted
|
||||
*
|
||||
* @see #setBlob(InputStream)
|
||||
* @see #getResult()
|
||||
*/
|
||||
public InputStream getBlobResult() {
|
||||
if(mArgs.containsKey("BLOB")) {
|
||||
ContentResolver cr = mContext.getContentResolver();
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = cr.openInputStream(Uri.parse(mArgs.getString("BLOB")));
|
||||
} catch( Exception e ) {
|
||||
Log.e(TAG, "Could not return blob in result", e);
|
||||
}
|
||||
return in;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result bundle
|
||||
*
|
||||
* <p>
|
||||
* Unlike {@link #getResult()}, which only returns any en-/decrypted
|
||||
* message, this function returns the complete information that was returned
|
||||
* by Apg. This also includes the "RESULT", but additionally the warnings,
|
||||
* errors and any other information.
|
||||
* </p>
|
||||
* <p>
|
||||
* For warnings and errors it is suggested to use the functions that are
|
||||
* provided here, namely {@link #getError()}, {@link #getNextError()},
|
||||
* {@link #get_next_Warning()} etc.), but if any call returns something non
|
||||
* standard, you have access to the complete result bundle to extract the
|
||||
* information.
|
||||
* </p>
|
||||
*
|
||||
* @return the complete result bundle of the last call to apg
|
||||
*/
|
||||
public Bundle getResultBundle() {
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public error getConnectionStatus() {
|
||||
return mConnectionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all unfetched errors
|
||||
*
|
||||
* @see #getNextError()
|
||||
* @see #hasNextError()
|
||||
*/
|
||||
public void clearErrors() {
|
||||
mErrorList.clear();
|
||||
mResult.remove(ret.ERROR.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all unfetched warnings
|
||||
*
|
||||
* @see #getNextWarning()
|
||||
* @see #hasNextWarning()
|
||||
*/
|
||||
public void clearWarnings() {
|
||||
mWarningList.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the last mResult
|
||||
*
|
||||
* @see #getResult()
|
||||
*/
|
||||
public void clearResult() {
|
||||
mResult.remove(ret.RESULT.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback listener when call to AIDL finishes
|
||||
*
|
||||
* @param obj
|
||||
* a object to call back after async execution
|
||||
* @see ApgConInterface
|
||||
*/
|
||||
public void setOnCallFinishListener(OnCallFinishListener lis) {
|
||||
mOnCallFinishListener = lis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any callback object
|
||||
*
|
||||
* @see #setOnCallFinishListener(OnCallFinishListener)
|
||||
*/
|
||||
public void clearOnCallFinishListener() {
|
||||
mOnCallFinishListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an async execution is running
|
||||
*
|
||||
* <p>
|
||||
* If you started something with {@link #callAsync(String)}, this will
|
||||
* return true if the task is still running
|
||||
* </p>
|
||||
*
|
||||
* @return true, if an async task is still running, false otherwise
|
||||
*
|
||||
* @see #callAsync(String)
|
||||
*
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return mAsyncRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely resets your instance
|
||||
*
|
||||
* <p>
|
||||
* This currently resets everything in this instance. Errors, warnings,
|
||||
* results, callbacks, ... are removed. Any connection to the remote
|
||||
* interface is upheld, though.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note when an async execution ({@link #callAsync(String)}) is
|
||||
* running, it's result, warnings etc. will still be evaluated (which might
|
||||
* be not what you want). Also mind that any callback you set is also
|
||||
* reseted, so when finishing the execution any before defined callback will
|
||||
* NOT BE TRIGGERED.
|
||||
* </p>
|
||||
*/
|
||||
public void reset() {
|
||||
clearErrors();
|
||||
clearWarnings();
|
||||
clearArgs();
|
||||
clearOnCallFinishListener();
|
||||
mResult.clear();
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Licensed 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 org.thialfihar.android.apg.deprecated;
|
||||
|
||||
public interface ApgConInterface {
|
||||
public static interface OnCallFinishListener {
|
||||
public abstract void onCallFinish(android.os.Bundle result);
|
||||
}
|
||||
}
|
@ -1,673 +0,0 @@
|
||||
///*
|
||||
// * Licensed 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 org.thialfihar.android.apg.deprecated;
|
||||
//
|
||||
//import java.io.ByteArrayInputStream;
|
||||
//import java.io.ByteArrayOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.lang.reflect.Method;
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.HashSet;
|
||||
//import java.util.Iterator;
|
||||
//
|
||||
//import org.thialfihar.android.apg.deprecated.IApgService2;
|
||||
//import org.thialfihar.android.apg.Id;
|
||||
//import org.thialfihar.android.apg.R;
|
||||
//import org.thialfihar.android.apg.deprecated.IApgService2.Stub;
|
||||
//import org.thialfihar.android.apg.Id.database;
|
||||
//import org.thialfihar.android.apg.R.string;
|
||||
//import org.thialfihar.android.apg.helper.PGPHelper;
|
||||
//import org.thialfihar.android.apg.helper.PGPMain;
|
||||
//import org.thialfihar.android.apg.helper.Preferences;
|
||||
//import org.thialfihar.android.apg.provider.KeyRings;
|
||||
//import org.thialfihar.android.apg.provider.Keys;
|
||||
//import org.thialfihar.android.apg.provider.UserIds;
|
||||
//import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||
//import org.thialfihar.android.apg.util.InputData;
|
||||
//
|
||||
//import android.content.ContentResolver;
|
||||
//import android.content.Intent;
|
||||
//import android.database.Cursor;
|
||||
//import android.database.sqlite.SQLiteQueryBuilder;
|
||||
//import android.net.Uri;
|
||||
//import android.os.Bundle;
|
||||
//import android.os.IBinder;
|
||||
//import org.thialfihar.android.apg.util.Log;
|
||||
//
|
||||
///**
|
||||
// * ATTENTION:
|
||||
// *
|
||||
// * This is the old ApgService used as remote service over aidl interface. It will be reworked!
|
||||
// *
|
||||
// */
|
||||
//public class ApgService2 extends PassphraseCacheService {
|
||||
// private final static String TAG = "ApgService";
|
||||
// public static final boolean LOCAL_LOGV = true;
|
||||
// public static final boolean LOCAL_LOGD = true;
|
||||
//
|
||||
// @Override
|
||||
// public IBinder onBind(Intent intent) {
|
||||
// if (LOCAL_LOGD)
|
||||
// Log.d(TAG, "bound");
|
||||
// return mBinder;
|
||||
// }
|
||||
//
|
||||
// /** error status */
|
||||
// private static enum error {
|
||||
// ARGUMENTS_MISSING, APG_FAILURE, NO_MATCHING_SECRET_KEY, PRIVATE_KEY_PASSPHRASE_WRONG, PRIVATE_KEY_PASSPHRASE_MISSING;
|
||||
//
|
||||
// public int shiftedOrdinal() {
|
||||
// return ordinal() + 100;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static enum call {
|
||||
// encrypt_with_passphrase, encrypt_with_public_key, decrypt, get_keys
|
||||
// }
|
||||
//
|
||||
// /** all arguments that can be passed by calling application */
|
||||
// public static enum arg {
|
||||
// MESSAGE, // message to encrypt or to decrypt
|
||||
// SYMMETRIC_PASSPHRASE, // key for symmetric en/decryption
|
||||
// PUBLIC_KEYS, // public keys for encryption
|
||||
// ENCRYPTION_ALGORYTHM, // encryption algorithm
|
||||
// HASH_ALGORYTHM, // hash algorithm
|
||||
// ARMORED_OUTPUT, // whether to armor output
|
||||
// FORCE_V3_SIGNATURE, // whether to force v3 signature
|
||||
// COMPRESSION, // what compression to use for encrypted output
|
||||
// SIGNATURE_KEY, // key for signing
|
||||
// PRIVATE_KEY_PASSPHRASE, // passphrase for encrypted private key
|
||||
// KEY_TYPE, // type of key (private or public)
|
||||
// BLOB, // blob passed
|
||||
// }
|
||||
//
|
||||
// /** all things that might be returned */
|
||||
// private static enum ret {
|
||||
// ERRORS, // string array list with errors
|
||||
// WARNINGS, // string array list with warnings
|
||||
// ERROR, // numeric error
|
||||
// RESULT, // en-/decrypted
|
||||
// FINGERPRINTS, // fingerprints of keys
|
||||
// USER_IDS, // user ids
|
||||
// }
|
||||
//
|
||||
// /** required arguments for each AIDL function */
|
||||
// private static final HashMap<String, HashSet<arg>> FUNCTIONS_REQUIRED_ARGS = new HashMap<String, HashSet<arg>>();
|
||||
// static {
|
||||
// HashSet<arg> args = new HashSet<arg>();
|
||||
// args.add(arg.SYMMETRIC_PASSPHRASE);
|
||||
// FUNCTIONS_REQUIRED_ARGS.put(call.encrypt_with_passphrase.name(), args);
|
||||
//
|
||||
// args = new HashSet<arg>();
|
||||
// args.add(arg.PUBLIC_KEYS);
|
||||
// FUNCTIONS_REQUIRED_ARGS.put(call.encrypt_with_public_key.name(), args);
|
||||
//
|
||||
// args = new HashSet<arg>();
|
||||
// FUNCTIONS_REQUIRED_ARGS.put(call.decrypt.name(), args);
|
||||
//
|
||||
// args = new HashSet<arg>();
|
||||
// args.add(arg.KEY_TYPE);
|
||||
// FUNCTIONS_REQUIRED_ARGS.put(call.get_keys.name(), args);
|
||||
// }
|
||||
//
|
||||
// /** optional arguments for each AIDL function */
|
||||
// private static final HashMap<String, HashSet<arg>> FUNCTIONS_OPTIONAL_ARGS = new HashMap<String, HashSet<arg>>();
|
||||
// static {
|
||||
// HashSet<arg> args = new HashSet<arg>();
|
||||
// args.add(arg.ENCRYPTION_ALGORYTHM);
|
||||
// args.add(arg.HASH_ALGORYTHM);
|
||||
// args.add(arg.ARMORED_OUTPUT);
|
||||
// args.add(arg.FORCE_V3_SIGNATURE);
|
||||
// args.add(arg.COMPRESSION);
|
||||
// args.add(arg.PRIVATE_KEY_PASSPHRASE);
|
||||
// args.add(arg.SIGNATURE_KEY);
|
||||
// args.add(arg.BLOB);
|
||||
// args.add(arg.MESSAGE);
|
||||
// FUNCTIONS_OPTIONAL_ARGS.put(call.encrypt_with_passphrase.name(), args);
|
||||
// FUNCTIONS_OPTIONAL_ARGS.put(call.encrypt_with_public_key.name(), args);
|
||||
//
|
||||
// args = new HashSet<arg>();
|
||||
// args.add(arg.SYMMETRIC_PASSPHRASE);
|
||||
// args.add(arg.PUBLIC_KEYS);
|
||||
// args.add(arg.PRIVATE_KEY_PASSPHRASE);
|
||||
// args.add(arg.MESSAGE);
|
||||
// args.add(arg.BLOB);
|
||||
// FUNCTIONS_OPTIONAL_ARGS.put(call.decrypt.name(), args);
|
||||
// }
|
||||
//
|
||||
// /** a map from ApgService parameters to function calls to get the default */
|
||||
// private static final HashMap<arg, String> FUNCTIONS_DEFAULTS = new HashMap<arg, String>();
|
||||
// static {
|
||||
// FUNCTIONS_DEFAULTS.put(arg.ENCRYPTION_ALGORYTHM, "getDefaultEncryptionAlgorithm");
|
||||
// FUNCTIONS_DEFAULTS.put(arg.HASH_ALGORYTHM, "getDefaultHashAlgorithm");
|
||||
// FUNCTIONS_DEFAULTS.put(arg.ARMORED_OUTPUT, "getDefaultAsciiArmour");
|
||||
// FUNCTIONS_DEFAULTS.put(arg.FORCE_V3_SIGNATURE, "getForceV3Signatures");
|
||||
// FUNCTIONS_DEFAULTS.put(arg.COMPRESSION, "getDefaultMessageCompression");
|
||||
// }
|
||||
//
|
||||
// /** a map of the default function names to their method */
|
||||
// private static final HashMap<String, Method> FUNCTIONS_DEFAULTS_METHODS = new HashMap<String, Method>();
|
||||
// static {
|
||||
// try {
|
||||
// FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm",
|
||||
// Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
|
||||
// FUNCTIONS_DEFAULTS_METHODS.put("getDefaultHashAlgorithm",
|
||||
// Preferences.class.getMethod("getDefaultHashAlgorithm"));
|
||||
// FUNCTIONS_DEFAULTS_METHODS.put("getDefaultAsciiArmour",
|
||||
// Preferences.class.getMethod("getDefaultAsciiArmour"));
|
||||
// FUNCTIONS_DEFAULTS_METHODS.put("getForceV3Signatures",
|
||||
// Preferences.class.getMethod("getForceV3Signatures"));
|
||||
// FUNCTIONS_DEFAULTS_METHODS.put("getDefaultMessageCompression",
|
||||
// Preferences.class.getMethod("getDefaultMessageCompression"));
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "Function method exception: " + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException {
|
||||
// byte[] buffer = new byte[8];
|
||||
// int len = 0;
|
||||
// while ((len = is.read(buffer)) != -1) {
|
||||
// os.write(buffer, 0, len);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static Cursor getKeyEntries(HashMap<String, Object> pParams) {
|
||||
// SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
// qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
|
||||
// + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
|
||||
// + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
|
||||
// + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
|
||||
// + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
|
||||
// + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') ");
|
||||
//
|
||||
// String orderBy = pParams.containsKey("order_by") ? (String) pParams.get("order_by")
|
||||
// : UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC";
|
||||
//
|
||||
// String typeVal[] = null;
|
||||
// String typeWhere = null;
|
||||
// if (pParams.containsKey("key_type")) {
|
||||
// typeWhere = KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?";
|
||||
// typeVal = new String[] { "" + pParams.get("key_type") };
|
||||
// }
|
||||
// return qb.query(PGPMain.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere,
|
||||
// typeVal, null, null, orderBy);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * maps a fingerprint or user id of a key to a master key in database
|
||||
// *
|
||||
// * @param search_key
|
||||
// * fingerprint or user id to search for
|
||||
// * @return master key if found, or 0
|
||||
// */
|
||||
// private static long getMasterKey(String pSearchKey, Bundle pReturn) {
|
||||
// if (pSearchKey == null || pSearchKey.length() != 8) {
|
||||
// return 0;
|
||||
// }
|
||||
// ArrayList<String> keyList = new ArrayList<String>();
|
||||
// keyList.add(pSearchKey);
|
||||
// long[] keys = getMasterKey(keyList, pReturn);
|
||||
// if (keys.length > 0) {
|
||||
// return keys[0];
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * maps fingerprints or user ids of keys to master keys in database
|
||||
// *
|
||||
// * @param search_keys
|
||||
// * a list of keys (fingerprints or user ids) to look for in database
|
||||
// * @return an array of master keys
|
||||
// */
|
||||
// private static long[] getMasterKey(ArrayList<String> pSearchKeys, Bundle pReturn) {
|
||||
//
|
||||
// HashMap<String, Object> qParams = new HashMap<String, Object>();
|
||||
// qParams.put("columns", new String[] { KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 0
|
||||
// UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 1
|
||||
// });
|
||||
// qParams.put("key_type", Id.database.type_public);
|
||||
//
|
||||
// Cursor mCursor = getKeyEntries(qParams);
|
||||
//
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "going through installed user keys");
|
||||
// ArrayList<Long> masterKeys = new ArrayList<Long>();
|
||||
// while (mCursor.moveToNext()) {
|
||||
// long curMkey = mCursor.getLong(0);
|
||||
// String curUser = mCursor.getString(1);
|
||||
//
|
||||
// String curFprint = PGPHelper.getSmallFingerPrint(curMkey);
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "current user: " + curUser + " (" + curFprint + ")");
|
||||
// if (pSearchKeys.contains(curFprint) || pSearchKeys.contains(curUser)) {
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "master key found for: " + curFprint);
|
||||
// masterKeys.add(curMkey);
|
||||
// pSearchKeys.remove(curFprint);
|
||||
// } else {
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "Installed key " + curFprint
|
||||
// + " is not in the list of public keys to encrypt with");
|
||||
// }
|
||||
// }
|
||||
// mCursor.close();
|
||||
//
|
||||
// long[] masterKeyLongs = new long[masterKeys.size()];
|
||||
// int i = 0;
|
||||
// for (Long key : masterKeys) {
|
||||
// masterKeyLongs[i++] = key;
|
||||
// }
|
||||
//
|
||||
// if (i == 0) {
|
||||
// Log.w(TAG, "Found not one public key");
|
||||
// pReturn.getStringArrayList(ret.WARNINGS.name()).add(
|
||||
// "Searched for public key(s) but found not one");
|
||||
// }
|
||||
//
|
||||
// for (String key : pSearchKeys) {
|
||||
// Log.w(TAG, "Searched for key " + key + " but cannot find it in APG");
|
||||
// pReturn.getStringArrayList(ret.WARNINGS.name()).add(
|
||||
// "Searched for key " + key + " but cannot find it in APG");
|
||||
// }
|
||||
//
|
||||
// return masterKeyLongs;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Add default arguments if missing
|
||||
// *
|
||||
// * @param args
|
||||
// * the bundle to add default parameters to if missing
|
||||
// */
|
||||
// private void addDefaultArguments(String pCall, Bundle pArgs) {
|
||||
// // check whether there are optional elements defined for that call
|
||||
// if (FUNCTIONS_OPTIONAL_ARGS.containsKey(pCall)) {
|
||||
// Preferences preferences = Preferences.getPreferences(getBaseContext(), true);
|
||||
//
|
||||
// Iterator<arg> iter = FUNCTIONS_DEFAULTS.keySet().iterator();
|
||||
// while (iter.hasNext()) {
|
||||
// arg currentArg = iter.next();
|
||||
// String currentKey = currentArg.name();
|
||||
// if (!pArgs.containsKey(currentKey)
|
||||
// && FUNCTIONS_OPTIONAL_ARGS.get(pCall).contains(currentArg)) {
|
||||
// String currentFunctionName = FUNCTIONS_DEFAULTS.get(currentArg);
|
||||
// try {
|
||||
// Class<?> returnType = FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
|
||||
// .getReturnType();
|
||||
// if (returnType == String.class) {
|
||||
// pArgs.putString(currentKey,
|
||||
// (String) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
|
||||
// .invoke(preferences));
|
||||
// } else if (returnType == boolean.class) {
|
||||
// pArgs.putBoolean(currentKey,
|
||||
// (Boolean) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
|
||||
// .invoke(preferences));
|
||||
// } else if (returnType == int.class) {
|
||||
// pArgs.putInt(currentKey,
|
||||
// (Integer) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
|
||||
// .invoke(preferences));
|
||||
// } else {
|
||||
// Log.e(TAG, "Unknown return type " + returnType.toString()
|
||||
// + " for default option");
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "Exception in add_default_arguments " + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * updates a Bundle with default return values
|
||||
// *
|
||||
// * @param pReturn
|
||||
// * the Bundle to update
|
||||
// */
|
||||
// private void addDefaultReturns(Bundle pReturn) {
|
||||
// ArrayList<String> errors = new ArrayList<String>();
|
||||
// ArrayList<String> warnings = new ArrayList<String>();
|
||||
//
|
||||
// pReturn.putStringArrayList(ret.ERRORS.name(), errors);
|
||||
// pReturn.putStringArrayList(ret.WARNINGS.name(), warnings);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * checks for required arguments and adds them to the error if missing
|
||||
// *
|
||||
// * @param function
|
||||
// * the functions required arguments to check for
|
||||
// * @param pArgs
|
||||
// * the Bundle of arguments to check
|
||||
// * @param pReturn
|
||||
// * the bundle to write errors to
|
||||
// */
|
||||
// private void checkForRequiredArgs(String pFunction, Bundle pArgs, Bundle pReturn) {
|
||||
// if (FUNCTIONS_REQUIRED_ARGS.containsKey(pFunction)) {
|
||||
// Iterator<arg> iter = FUNCTIONS_REQUIRED_ARGS.get(pFunction).iterator();
|
||||
// while (iter.hasNext()) {
|
||||
// String curArg = iter.next().name();
|
||||
// if (!pArgs.containsKey(curArg)) {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name())
|
||||
// .add("Argument missing: " + curArg);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (pFunction.equals(call.encrypt_with_passphrase.name())
|
||||
// || pFunction.equals(call.encrypt_with_public_key.name())
|
||||
// || pFunction.equals(call.decrypt.name())) {
|
||||
// // check that either MESSAGE or BLOB are there
|
||||
// if (!pArgs.containsKey(arg.MESSAGE.name()) && !pArgs.containsKey(arg.BLOB.name())) {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
// "Arguments missing: Neither MESSAGE nor BLOG found");
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * checks for unknown arguments and add them to warning if found
|
||||
// *
|
||||
// * @param function
|
||||
// * the functions name to check against
|
||||
// * @param pArgs
|
||||
// * the Bundle of arguments to check
|
||||
// * @param pReturn
|
||||
// * the bundle to write warnings to
|
||||
// */
|
||||
// private void checkForUnknownArgs(String pFunction, Bundle pArgs, Bundle pReturn) {
|
||||
//
|
||||
// HashSet<arg> allArgs = new HashSet<arg>();
|
||||
// if (FUNCTIONS_REQUIRED_ARGS.containsKey(pFunction)) {
|
||||
// allArgs.addAll(FUNCTIONS_REQUIRED_ARGS.get(pFunction));
|
||||
// }
|
||||
// if (FUNCTIONS_OPTIONAL_ARGS.containsKey(pFunction)) {
|
||||
// allArgs.addAll(FUNCTIONS_OPTIONAL_ARGS.get(pFunction));
|
||||
// }
|
||||
//
|
||||
// ArrayList<String> unknownArgs = new ArrayList<String>();
|
||||
// Iterator<String> iter = pArgs.keySet().iterator();
|
||||
// while (iter.hasNext()) {
|
||||
// String curKey = iter.next();
|
||||
// try {
|
||||
// arg curArg = arg.valueOf(curKey);
|
||||
// if (!allArgs.contains(curArg)) {
|
||||
// pReturn.getStringArrayList(ret.WARNINGS.name()).add(
|
||||
// "Unknown argument: " + curKey);
|
||||
// unknownArgs.add(curKey);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// pReturn.getStringArrayList(ret.WARNINGS.name()).add("Unknown argument: " + curKey);
|
||||
// unknownArgs.add(curKey);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // remove unknown arguments so our bundle has just what we need
|
||||
// for (String arg : unknownArgs) {
|
||||
// pArgs.remove(arg);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private boolean prepareArgs(String pCall, Bundle pArgs, Bundle pReturn) {
|
||||
// // PGPMain.initialize(getBaseContext());
|
||||
//
|
||||
// /* add default return values for all functions */
|
||||
// addDefaultReturns(pReturn);
|
||||
//
|
||||
// /* add default arguments if missing */
|
||||
// addDefaultArguments(pCall, pArgs);
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "add_default_arguments");
|
||||
//
|
||||
// /* check for required arguments */
|
||||
// checkForRequiredArgs(pCall, pArgs, pReturn);
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "check_required_args");
|
||||
//
|
||||
// /* check for unknown arguments and add to warning if found */
|
||||
// checkForUnknownArgs(pCall, pArgs, pReturn);
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "check_unknown_args");
|
||||
//
|
||||
// /* return if errors happened */
|
||||
// if (pReturn.getStringArrayList(ret.ERRORS.name()).size() != 0) {
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "Errors after preparing, not executing " + pCall);
|
||||
// pReturn.putInt(ret.ERROR.name(), error.ARGUMENTS_MISSING.shiftedOrdinal());
|
||||
// return false;
|
||||
// }
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "error return");
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private boolean encrypt(Bundle pArgs, Bundle pReturn) {
|
||||
// boolean isBlob = pArgs.containsKey(arg.BLOB.name());
|
||||
//
|
||||
// long pubMasterKeys[] = {};
|
||||
// if (pArgs.containsKey(arg.PUBLIC_KEYS.name())) {
|
||||
// ArrayList<String> list = pArgs.getStringArrayList(arg.PUBLIC_KEYS.name());
|
||||
// ArrayList<String> pubKeys = new ArrayList<String>();
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "Long size: " + list.size());
|
||||
// Iterator<String> iter = list.iterator();
|
||||
// while (iter.hasNext()) {
|
||||
// pubKeys.add(iter.next());
|
||||
// }
|
||||
// pubMasterKeys = getMasterKey(pubKeys, pReturn);
|
||||
// }
|
||||
//
|
||||
// InputStream inStream = null;
|
||||
// if (isBlob) {
|
||||
// ContentResolver cr = getContentResolver();
|
||||
// try {
|
||||
// inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "... exception on opening blob", e);
|
||||
// }
|
||||
// } else {
|
||||
// inStream = new ByteArrayInputStream(pArgs.getString(arg.MESSAGE.name()).getBytes());
|
||||
// }
|
||||
// InputData in = new InputData(inStream, 0); // XXX Size second param?
|
||||
//
|
||||
// OutputStream out = new ByteArrayOutputStream();
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "About to encrypt");
|
||||
// try {
|
||||
// PGPMain.encrypt(getBaseContext(), // context
|
||||
// in, // input stream
|
||||
// out, // output stream
|
||||
// pArgs.getBoolean(arg.ARMORED_OUTPUT.name()), // ARMORED_OUTPUT
|
||||
// pubMasterKeys, // encryption keys
|
||||
// getMasterKey(pArgs.getString(arg.SIGNATURE_KEY.name()), pReturn), // signature
|
||||
// // key
|
||||
// pArgs.getString(arg.PRIVATE_KEY_PASSPHRASE.name()), // signature passphrase
|
||||
// null, // progress
|
||||
// pArgs.getInt(arg.ENCRYPTION_ALGORYTHM.name()), // encryption
|
||||
// pArgs.getInt(arg.HASH_ALGORYTHM.name()), // hash
|
||||
// pArgs.getInt(arg.COMPRESSION.name()), // compression
|
||||
// pArgs.getBoolean(arg.FORCE_V3_SIGNATURE.name()), // mPreferences.getForceV3Signatures(),
|
||||
// pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) // passPhrase
|
||||
// );
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "Exception in encrypt");
|
||||
// String msg = e.getMessage();
|
||||
// if (msg.equals(getBaseContext().getString(R.string.error_noSignaturePassPhrase))) {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
// "Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " missing): "
|
||||
// + msg);
|
||||
// pReturn.putInt(ret.ERROR.name(),
|
||||
// error.PRIVATE_KEY_PASSPHRASE_MISSING.shiftedOrdinal());
|
||||
// } else if (msg.equals(getBaseContext().getString(
|
||||
// R.string.error_couldNotExtractPrivateKey))) {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
// "Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name()
|
||||
// + " probably wrong): " + msg);
|
||||
// pReturn.putInt(ret.ERROR.name(),
|
||||
// error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
|
||||
// } else {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
// "Internal failure (" + e.getClass() + ") in APG when encrypting: "
|
||||
// + e.getMessage());
|
||||
// pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.shiftedOrdinal());
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "Encrypted");
|
||||
// if (isBlob) {
|
||||
// ContentResolver cr = getContentResolver();
|
||||
// try {
|
||||
// OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
|
||||
// .name())));
|
||||
// writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
|
||||
// outStream.close();
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "... exception on writing blob", e);
|
||||
// }
|
||||
// } else {
|
||||
// pReturn.putString(ret.RESULT.name(), out.toString());
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private final IApgService2.Stub mBinder = new IApgService2.Stub() {
|
||||
//
|
||||
// public boolean getKeys(Bundle pArgs, Bundle pReturn) {
|
||||
//
|
||||
// prepareArgs("get_keys", pArgs, pReturn);
|
||||
//
|
||||
// HashMap<String, Object> qParams = new HashMap<String, Object>();
|
||||
// qParams.put("columns", new String[] {
|
||||
// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 0
|
||||
// UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 1
|
||||
// });
|
||||
//
|
||||
// qParams.put("key_type", pArgs.getInt(arg.KEY_TYPE.name()));
|
||||
//
|
||||
// Cursor cursor = getKeyEntries(qParams);
|
||||
// ArrayList<String> fPrints = new ArrayList<String>();
|
||||
// ArrayList<String> ids = new ArrayList<String>();
|
||||
// while (cursor.moveToNext()) {
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "adding key " + PGPHelper.getSmallFingerPrint(cursor.getLong(0)));
|
||||
// fPrints.add(PGPHelper.getSmallFingerPrint(cursor.getLong(0)));
|
||||
// ids.add(cursor.getString(1));
|
||||
// }
|
||||
// cursor.close();
|
||||
//
|
||||
// pReturn.putStringArrayList(ret.FINGERPRINTS.name(), fPrints);
|
||||
// pReturn.putStringArrayList(ret.USER_IDS.name(), ids);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// public boolean encryptWithPublicKey(Bundle pArgs, Bundle pReturn) {
|
||||
// if (!prepareArgs("encrypt_with_public_key", pArgs, pReturn)) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return encrypt(pArgs, pReturn);
|
||||
// }
|
||||
//
|
||||
// public boolean encryptWithPassphrase(Bundle pArgs, Bundle pReturn) {
|
||||
// if (!prepareArgs("encrypt_with_passphrase", pArgs, pReturn)) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return encrypt(pArgs, pReturn);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public boolean decrypt(Bundle pArgs, Bundle pReturn) {
|
||||
// if (!prepareArgs("decrypt", pArgs, pReturn)) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// boolean isBlob = pArgs.containsKey(arg.BLOB.name());
|
||||
//
|
||||
// String passphrase = pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null ? pArgs
|
||||
// .getString(arg.SYMMETRIC_PASSPHRASE.name()) : pArgs
|
||||
// .getString(arg.PRIVATE_KEY_PASSPHRASE.name());
|
||||
//
|
||||
// InputStream inStream = null;
|
||||
// if (isBlob) {
|
||||
// ContentResolver cr = getContentResolver();
|
||||
// try {
|
||||
// inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "... exception on opening blob", e);
|
||||
// }
|
||||
// } else {
|
||||
// inStream = new ByteArrayInputStream(pArgs.getString(arg.MESSAGE.name()).getBytes());
|
||||
// }
|
||||
//
|
||||
// InputData in = new InputData(inStream, 0); // XXX what size in second parameter?
|
||||
// OutputStream out = new ByteArrayOutputStream();
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "About to decrypt");
|
||||
// try {
|
||||
// PGPMain.decrypt(getBaseContext(), in, out, passphrase, null, // progress
|
||||
// pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null // symmetric
|
||||
// );
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "Exception in decrypt");
|
||||
// String msg = e.getMessage();
|
||||
// if (msg.equals(getBaseContext().getString(R.string.error_noSecretKeyFound))) {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add("Cannot decrypt: " + msg);
|
||||
// pReturn.putInt(ret.ERROR.name(), error.NO_MATCHING_SECRET_KEY.shiftedOrdinal());
|
||||
// } else if (msg.equals(getBaseContext().getString(R.string.error_wrongPassPhrase))) {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
// "Cannot decrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name()
|
||||
// + " wrong/missing): " + msg);
|
||||
// pReturn.putInt(ret.ERROR.name(),
|
||||
// error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
|
||||
// } else {
|
||||
// pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
// "Internal failure (" + e.getClass() + ") in APG when decrypting: "
|
||||
// + msg);
|
||||
// pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.shiftedOrdinal());
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// if (LOCAL_LOGV)
|
||||
// Log.v(TAG, "... decrypted");
|
||||
//
|
||||
// if (isBlob) {
|
||||
// ContentResolver cr = getContentResolver();
|
||||
// try {
|
||||
// OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
|
||||
// .name())));
|
||||
// writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()),
|
||||
// outStream);
|
||||
// outStream.close();
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "... exception on writing blob", e);
|
||||
// }
|
||||
// } else {
|
||||
// pReturn.putString(ret.RESULT.name(), out.toString());
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// };
|
||||
//}
|
@ -1,71 +0,0 @@
|
||||
///*
|
||||
// * Licensed 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 org.thialfihar.android.apg.deprecated;
|
||||
//
|
||||
//
|
||||
//import android.content.ContentUris;
|
||||
//import android.content.ContentValues;
|
||||
//import android.content.Context;
|
||||
//import android.database.Cursor;
|
||||
//import android.database.sqlite.SQLiteDatabase;
|
||||
//import android.database.sqlite.SQLiteOpenHelper;
|
||||
//import android.net.Uri;
|
||||
//import org.thialfihar.android.apg.util.Log;
|
||||
//
|
||||
//public class ApgServiceBlobDatabase extends SQLiteOpenHelper {
|
||||
//
|
||||
// private static final String TAG = "ApgServiceBlobDatabase";
|
||||
//
|
||||
// private static final int VERSION = 1;
|
||||
// private static final String NAME = "apg_service_blob_data";
|
||||
// private static final String TABLE = "data";
|
||||
//
|
||||
// public ApgServiceBlobDatabase(Context context) {
|
||||
// super(context, NAME, null, VERSION);
|
||||
// if (ApgService2.LOCAL_LOGD)
|
||||
// Log.d(TAG, "constructor called");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onCreate(SQLiteDatabase db) {
|
||||
// if (ApgService2.LOCAL_LOGD)
|
||||
// Log.d(TAG, "onCreate() called");
|
||||
// db.execSQL("create table " + TABLE + " ( _id integer primary key autoincrement,"
|
||||
// + "key text not null)");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// if (ApgService2.LOCAL_LOGD)
|
||||
// Log.d(TAG, "onUpgrade() called");
|
||||
// // no upgrade necessary yet
|
||||
// }
|
||||
//
|
||||
// public Uri insert(ContentValues vals) {
|
||||
// if (ApgService2.LOCAL_LOGD)
|
||||
// Log.d(TAG, "insert() called");
|
||||
// SQLiteDatabase db = this.getWritableDatabase();
|
||||
// long newId = db.insert(TABLE, null, vals);
|
||||
// return ContentUris.withAppendedId(ApgServiceBlobProvider.CONTENT_URI, newId);
|
||||
// }
|
||||
//
|
||||
// public Cursor query(String id, String key) {
|
||||
// if (ApgService2.LOCAL_LOGD)
|
||||
// Log.d(TAG, "query() called");
|
||||
// SQLiteDatabase db = this.getReadableDatabase();
|
||||
// return db.query(TABLE, new String[] { "_id" }, "_id = ? and key = ?", new String[] { id,
|
||||
// key }, null, null, null);
|
||||
// }
|
||||
//}
|
@ -1,151 +0,0 @@
|
||||
///*
|
||||
// * Licensed 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 org.thialfihar.android.apg.deprecated;
|
||||
//
|
||||
//import org.thialfihar.android.apg.Constants;
|
||||
//
|
||||
//import android.content.ContentProvider;
|
||||
//import android.content.ContentValues;
|
||||
//import android.database.Cursor;
|
||||
//import android.net.Uri;
|
||||
//import android.os.ParcelFileDescriptor;
|
||||
//import org.thialfihar.android.apg.util.Log;
|
||||
//
|
||||
//import java.io.File;
|
||||
//import java.io.FileNotFoundException;
|
||||
//import java.io.IOException;
|
||||
//import java.util.List;
|
||||
//import java.util.UUID;
|
||||
//
|
||||
//public class ApgServiceBlobProvider extends ContentProvider {
|
||||
//
|
||||
// private static final String TAG = "ApgServiceBlobProvider";
|
||||
//
|
||||
// public static final Uri CONTENT_URI = Uri.parse("content://org.thialfihar.android.apg.provider.apgserviceblobprovider");
|
||||
//
|
||||
// private static final String COLUMN_KEY = "key";
|
||||
//
|
||||
// private static final String STORE_PATH = Constants.path.APP_DIR+"/ApgServiceBlobs";
|
||||
//
|
||||
// private ApgServiceBlobDatabase mDb = null;
|
||||
//
|
||||
// public ApgServiceBlobProvider() {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "Constructor called");
|
||||
// File dir = new File(STORE_PATH);
|
||||
// dir.mkdirs();
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "Constructor finished");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int delete(Uri arg0, String arg1, String[] arg2) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "delete() called");
|
||||
// // TODO Auto-generated method stub
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getType(Uri arg0) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "getType() called");
|
||||
// // not needed for now
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Uri insert(Uri uri, ContentValues ignored) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "insert() called");
|
||||
// // ContentValues are actually ignored, because we want to store a blob with no more information
|
||||
// // but have to create an record with the password generated here first
|
||||
//
|
||||
// ContentValues vals = new ContentValues();
|
||||
//
|
||||
// // Insert a random key in the database. This has to provided by the caller when updating or
|
||||
// // getting the blob
|
||||
// String password = UUID.randomUUID().toString();
|
||||
// vals.put(COLUMN_KEY, password);
|
||||
//
|
||||
// Uri insertedUri = mDb.insert(vals);
|
||||
// return Uri.withAppendedPath(insertedUri, password);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean onCreate() {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "onCreate() called");
|
||||
// mDb = new ApgServiceBlobDatabase(getContext());
|
||||
// // TODO Auto-generated method stub
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "query() called");
|
||||
// // TODO Auto-generated method stub
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "update() called");
|
||||
// // TODO Auto-generated method stub
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException, FileNotFoundException {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "openFile() called");
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "... with uri: "+uri.toString());
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "... with mode: "+mode);
|
||||
//
|
||||
// List<String> segments = uri.getPathSegments();
|
||||
// if(segments.size() < 2) {
|
||||
// throw new SecurityException("Password not found in URI");
|
||||
// }
|
||||
// String id = segments.get(0);
|
||||
// String key = segments.get(1);
|
||||
//
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "... got id: "+id);
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "... and key: "+key);
|
||||
//
|
||||
// // get the data
|
||||
// Cursor result = mDb.query(id, key);
|
||||
//
|
||||
// if(result.getCount() == 0) {
|
||||
// // either the key is wrong or no id exists
|
||||
// throw new FileNotFoundException("No file found with that ID and/or password");
|
||||
// }
|
||||
//
|
||||
// File targetFile = new File(STORE_PATH, id);
|
||||
// if(mode.equals("w")) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "... will try to open file w");
|
||||
// if( !targetFile.exists() ) {
|
||||
// try {
|
||||
// targetFile.createNewFile();
|
||||
// } catch (IOException e) {
|
||||
// Log.e(TAG, "... got IEOException on creating new file", e);
|
||||
// throw new FileNotFoundException("Could not create file to write to");
|
||||
// }
|
||||
// }
|
||||
// return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE );
|
||||
// } else if(mode.equals("r")) {
|
||||
// if(ApgService2.LOCAL_LOGD) Log.d(TAG, "... will try to open file r");
|
||||
// if( !targetFile.exists() ) {
|
||||
// throw new FileNotFoundException("Error: Could not find the file requested");
|
||||
// }
|
||||
// return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
//}
|
@ -1,43 +0,0 @@
|
||||
package org.thialfihar.android.apg.deprecated;
|
||||
//package org.thialfihar.android.apg.provider.blob;
|
||||
//
|
||||
//import android.net.Uri;
|
||||
//import android.provider.BaseColumns;
|
||||
//
|
||||
//public class BlobContract {
|
||||
//
|
||||
// interface BlobColumns {
|
||||
// String DATA = "data";
|
||||
// }
|
||||
//
|
||||
// public static final String CONTENT_AUTHORITY = "org.thialfihar.android.apg";
|
||||
//
|
||||
// private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
|
||||
//
|
||||
// public static final String PATH_BLOB = "blob";
|
||||
//
|
||||
// public static class Blobs implements BlobColumns, BaseColumns {
|
||||
// public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_BLOB)
|
||||
// .build();
|
||||
//
|
||||
// /** Use if multiple items get returned */
|
||||
// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.apg.blob";
|
||||
//
|
||||
// /** Use if a single item is returned */
|
||||
// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.apg.blob";
|
||||
//
|
||||
// /** Default "ORDER BY" clause. */
|
||||
// public static final String DEFAULT_SORT = BaseColumns._ID + " ASC";
|
||||
//
|
||||
// public static Uri buildUri(String id) {
|
||||
// return CONTENT_URI.buildUpon().appendPath(id).build();
|
||||
// }
|
||||
//
|
||||
// public static String getId(Uri uri) {
|
||||
// return uri.getLastPathSegment();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private BlobContract() {
|
||||
// }
|
||||
//}
|
@ -1,125 +0,0 @@
|
||||
package org.thialfihar.android.apg.deprecated;
|
||||
|
||||
interface IApgService2 {
|
||||
|
||||
/* All functions fill the returnVals Bundle with the following keys:
|
||||
*
|
||||
* ArrayList<String> "WARNINGS" = Warnings, if any
|
||||
* ArrayList<String> "ERRORS" = Human readable error descriptions, if any
|
||||
* int "ERROR" = Numeric representation of error, if any
|
||||
* starting with 100:
|
||||
* 100: Required argument missing
|
||||
* 101: Generic failure of APG
|
||||
* 102: No matching private key found
|
||||
* 103: Private key's passphrase wrong
|
||||
* 104: Private key's passphrase missing
|
||||
*/
|
||||
|
||||
/* ********************************************************
|
||||
* Encryption
|
||||
* ********************************************************/
|
||||
|
||||
/* All encryption function's arguments
|
||||
*
|
||||
* Bundle params' keys:
|
||||
* (optional/required)
|
||||
* TYPE "STRING KEY" = EXPLANATION / VALUES
|
||||
*
|
||||
* (required)
|
||||
* String "MESSAGE" = Message to encrypt
|
||||
* OR
|
||||
* String "BLOB" = ContentUri to a file handle
|
||||
* with binary data to encrypt
|
||||
* (Attention: file will be overwritten
|
||||
* with encrypted content!)
|
||||
*
|
||||
* (optional)
|
||||
* int "ENCRYPTION_ALGORYTHM" = Encryption Algorithm
|
||||
* 7: AES-128, 8: AES-192, 9: AES-256,
|
||||
* 4: Blowfish, 10: Twofish, 3: CAST5,
|
||||
* 6: DES, 2: Triple DES, 1: IDEA
|
||||
* (optional)
|
||||
* int "HASH_ALGORYTHM" = Hash Algorithm
|
||||
* 1: MD5, 3: RIPEMD-160, 2: SHA-1,
|
||||
* 11: SHA-224, 8: SHA-256, 9: SHA-384,
|
||||
* 10: SHA-512
|
||||
* (optional)
|
||||
* Boolean "ARMORED_OUTPUT" = Armor output
|
||||
*
|
||||
* (optional)
|
||||
* Boolean "FORCE_V3_SIGNATURE" = Force V3 Signatures
|
||||
*
|
||||
* (optional)
|
||||
* int "COMPRESSION" = Compression to use
|
||||
* 0x21070001: none, 1: Zip, 2: Zlib,
|
||||
* 3: BZip2
|
||||
* (optional)
|
||||
* String "SIGNATURE_KEY" = Key to sign with
|
||||
*
|
||||
* (optional)
|
||||
* String "PRIVATE_KEY_PASSPHRASE" = Passphrase for signing key
|
||||
*
|
||||
* Bundle returnVals (in addition to the ERRORS/WARNINGS above):
|
||||
* If "MESSAGE" was set:
|
||||
* String "RESULT" = Encrypted message
|
||||
*/
|
||||
|
||||
/* Additional argument for function below:
|
||||
* (required)
|
||||
* String "SYMMETRIC_PASSPHRASE" = Symmetric passphrase to use
|
||||
*/
|
||||
boolean encryptWithPassphrase(in Bundle params, out Bundle returnVals);
|
||||
|
||||
/* Additional argument:
|
||||
* (required)
|
||||
* ArrayList<String> "PUBLIC_KEYS" = Public keys (8char fingerprint "123ABC12" OR
|
||||
* complete id "Alice Meyer <ab@email.com>")
|
||||
*/
|
||||
boolean encryptWithPublicKey(in Bundle params, out Bundle returnVals);
|
||||
|
||||
/* ********************************************************
|
||||
* Decryption
|
||||
* ********************************************************/
|
||||
|
||||
/* Bundle params:
|
||||
* (required)
|
||||
* String "MESSAGE" = Message to dencrypt
|
||||
* OR
|
||||
* String "BLOB" = ContentUri to a file handle
|
||||
* with binary data to dencrypt
|
||||
* (Attention: file will be overwritten
|
||||
* with dencrypted content!)
|
||||
*
|
||||
* (optional)
|
||||
* String "SYMMETRIC_PASSPHRASE" = Symmetric passphrase for decryption
|
||||
*
|
||||
* (optional)
|
||||
* String "PRIVATE_KEY_PASSPHRASE" = Private keys's passphrase on asymmetric encryption
|
||||
*
|
||||
* Bundle return_vals:
|
||||
* If "MESSAGE" was set:
|
||||
* String "RESULT" = Decrypted message
|
||||
*/
|
||||
boolean decrypt(in Bundle params, out Bundle returnVals);
|
||||
|
||||
/* ********************************************************
|
||||
* Get key information
|
||||
* ********************************************************/
|
||||
|
||||
/* Get info about all available keys
|
||||
*
|
||||
* Bundle params:
|
||||
* (required)
|
||||
* int "KEY_TYPE" = info about what type of keys to return
|
||||
* 0: public keys
|
||||
* 1: private keys
|
||||
*
|
||||
* Returns:
|
||||
* StringArrayList "FINGERPRINTS" = Short fingerprints of keys
|
||||
*
|
||||
* StringArrayList "USER_IDS" = User ids of corresponding fingerprints
|
||||
* (order is the same as in FINGERPRINTS)
|
||||
*/
|
||||
boolean getKeys(in Bundle params, out Bundle returnVals);
|
||||
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.helper;
|
||||
|
||||
import org.thialfihar.android.apg.R;
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
package org.thialfihar.android.apg.helper;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
@ -23,7 +23,6 @@ import java.util.Iterator;
|
||||
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
@ -31,49 +30,9 @@ import org.thialfihar.android.apg.Constants;
|
||||
import org.thialfihar.android.apg.util.Log;
|
||||
|
||||
public class PGPConversionHelper {
|
||||
/**
|
||||
* Converts Vector<PGPSecretKey> to a byte[]
|
||||
*
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public static byte[] PGPSecretKeyListToBytes(ArrayList<PGPSecretKey> keys) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
for (PGPSecretKey key : keys) {
|
||||
try {
|
||||
key.encode(os);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Error while converting PGPSecretKey to byte[]!", e);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] keysBytes = os.toByteArray();
|
||||
|
||||
return keysBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from byte[] to PGPSecretKeyRing
|
||||
*
|
||||
* @param keysBytes
|
||||
* @return
|
||||
*/
|
||||
// public static PGPSecretKeyRing BytesToPGPSecretKeyRing(byte[] keysBytes) {
|
||||
// PGPObjectFactory factory = new PGPObjectFactory(keysBytes);
|
||||
// PGPSecretKeyRing keyRing = null;
|
||||
// try {
|
||||
// if ((keyRing = (PGPSecretKeyRing) factory.nextObject()) == null) {
|
||||
// Log.e(Constants.TAG, "No keys given!");
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// Log.e(Constants.TAG, "Error while converting to PGPSecretKeyRing!", e);
|
||||
// }
|
||||
//
|
||||
// return keyRing;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Convert from byte[] to PGPPublicKeyRing
|
||||
* Convert from byte[] to PGPKeyRing
|
||||
*
|
||||
* @param keysBytes
|
||||
* @return
|
||||
@ -86,7 +45,7 @@ public class PGPConversionHelper {
|
||||
Log.e(Constants.TAG, "No keys given!");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Error while converting to PGPPublicKeyRing!", e);
|
||||
Log.e(Constants.TAG, "Error while converting to PGPKeyRing!", e);
|
||||
}
|
||||
|
||||
return keyRing;
|
||||
@ -114,6 +73,8 @@ public class PGPConversionHelper {
|
||||
/**
|
||||
* Convert from byte[] to PGPSecretKey
|
||||
*
|
||||
* Singles keys are encoded as keyRings with one single key in it by Bouncy Castle
|
||||
*
|
||||
* @param keysBytes
|
||||
* @return
|
||||
*/
|
||||
@ -123,6 +84,25 @@ public class PGPConversionHelper {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from ArrayList<PGPSecretKey> to byte[]
|
||||
*
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public static byte[] PGPSecretKeyArrayListToBytes(ArrayList<PGPSecretKey> keys) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
for (PGPSecretKey key : keys) {
|
||||
try {
|
||||
key.encode(os);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Error while converting ArrayList<PGPSecretKey> to byte[]!", e);
|
||||
}
|
||||
}
|
||||
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from PGPSecretKey to byte[]
|
||||
*
|
||||
|
@ -707,8 +707,7 @@ public class PGPMain {
|
||||
}
|
||||
|
||||
if (signatureKeyId != Id.key.none) {
|
||||
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context,
|
||||
signatureKeyId);
|
||||
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
|
||||
signingKey = PGPHelper.getSigningKey(context, signatureKeyId);
|
||||
if (signingKey == null) {
|
||||
throw new ApgGeneralException(context.getString(R.string.error_signatureFailed));
|
||||
@ -718,8 +717,9 @@ public class PGPMain {
|
||||
throw new ApgGeneralException(
|
||||
context.getString(R.string.error_noSignaturePassPhrase));
|
||||
}
|
||||
if (progress != null)
|
||||
progress.setProgress(R.string.progress_extractingSignatureKey, 0, 100);
|
||||
|
||||
updateProgress(progress, R.string.progress_extractingSignatureKey, 0, 100);
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
|
||||
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
||||
@ -762,8 +762,7 @@ public class PGPMain {
|
||||
PGPV3SignatureGenerator signatureV3Generator = null;
|
||||
|
||||
if (signatureKeyId != Id.key.none) {
|
||||
if (progress != null)
|
||||
progress.setProgress(R.string.progress_preparingSignature, 10, 100);
|
||||
updateProgress(progress, R.string.progress_preparingSignature, 10, 100);
|
||||
|
||||
// content signer based on signing key algorithm and choosen hash algorithm
|
||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||
@ -1079,8 +1078,7 @@ public class PGPMain {
|
||||
if (passphrase == null || passphrase.length() <= 0) {
|
||||
throw new ApgGeneralException("Unable to obtain passphrase");
|
||||
} else {
|
||||
PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByKeyId(context,
|
||||
pubKeyId);
|
||||
PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByKeyId(context, pubKeyId);
|
||||
|
||||
PGPSecretKey signingKey = PGPHelper.getSigningKey(context, masterKeyId);
|
||||
if (signingKey == null) {
|
||||
@ -1505,8 +1503,8 @@ public class PGPMain {
|
||||
} else {
|
||||
signatureKeyId = signature.getKeyID();
|
||||
String userId = null;
|
||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(
|
||||
context, signatureKeyId);
|
||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context,
|
||||
signatureKeyId);
|
||||
if (signKeyRing != null) {
|
||||
userId = PGPHelper.getMainUserId(PGPHelper.getMasterKey(signKeyRing));
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ import org.thialfihar.android.apg.util.Log;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
@ -199,8 +198,7 @@ public class ApgProvider extends ContentProvider {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
final Context context = getContext();
|
||||
mApgDatabase = new ApgDatabase(context);
|
||||
mApgDatabase = new ApgDatabase(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -315,6 +313,7 @@ public class ApgProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.provider;
|
||||
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
public class ApgServiceBlobContract {
|
||||
|
||||
interface BlobsColumns {
|
||||
String KEY = "key";
|
||||
}
|
||||
|
||||
public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".blobs";
|
||||
|
||||
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
|
||||
|
||||
public static class Blobs implements BlobsColumns, BaseColumns {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI;
|
||||
}
|
||||
|
||||
private ApgServiceBlobContract() {
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2011 Markus Doits <markus.doits@googlemail.com>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.provider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
import org.thialfihar.android.apg.provider.ApgServiceBlobContract.BlobsColumns;
|
||||
|
||||
public class ApgServiceBlobDatabase extends SQLiteOpenHelper {
|
||||
private static final String DATABASE_NAME = "apg_blob.db";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
public static final String TABLE = "data";
|
||||
|
||||
public ApgServiceBlobDatabase(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE " + TABLE + " ( " + BaseColumns._ID
|
||||
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + BlobsColumns.KEY + " TEXT NOT NULL)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// no upgrade necessary yet
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2011 Markus Doits <markus.doits@googlemail.com>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.provider;
|
||||
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
import org.thialfihar.android.apg.provider.ApgServiceBlobContract.Blobs;
|
||||
import org.thialfihar.android.apg.provider.ApgServiceBlobContract.BlobsColumns;
|
||||
import org.thialfihar.android.apg.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ApgServiceBlobProvider extends ContentProvider {
|
||||
private static final String STORE_PATH = Constants.path.APP_DIR + "/ApgBlobs";
|
||||
|
||||
private ApgServiceBlobDatabase mBlobDatabase = null;
|
||||
|
||||
public ApgServiceBlobProvider() {
|
||||
File dir = new File(STORE_PATH);
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
mBlobDatabase = new ApgServiceBlobDatabase(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues ignored) {
|
||||
// ContentValues are actually ignored, because we want to store a blob with no more
|
||||
// information but have to create an record with the password generated here first
|
||||
ContentValues vals = new ContentValues();
|
||||
|
||||
// Insert a random key in the database. This has to provided by the caller when updating or
|
||||
// getting the blob
|
||||
String password = UUID.randomUUID().toString();
|
||||
vals.put(BlobsColumns.KEY, password);
|
||||
|
||||
SQLiteDatabase db = mBlobDatabase.getWritableDatabase();
|
||||
long newRowId = db.insert(ApgServiceBlobDatabase.TABLE, null, vals);
|
||||
Uri insertedUri = ContentUris.withAppendedId(Blobs.CONTENT_URI, newRowId);
|
||||
|
||||
return Uri.withAppendedPath(insertedUri, password);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException,
|
||||
FileNotFoundException {
|
||||
Log.d(Constants.TAG, "openFile() called with uri: " + uri.toString() + " and mode: " + mode);
|
||||
|
||||
List<String> segments = uri.getPathSegments();
|
||||
if (segments.size() < 2) {
|
||||
throw new SecurityException("Password not found in URI");
|
||||
}
|
||||
String id = segments.get(0);
|
||||
String key = segments.get(1);
|
||||
|
||||
Log.d(Constants.TAG, "Got id: " + id + " and key: " + key);
|
||||
|
||||
// get the data
|
||||
SQLiteDatabase db = mBlobDatabase.getReadableDatabase();
|
||||
Cursor result = db.query(ApgServiceBlobDatabase.TABLE, new String[] { BaseColumns._ID },
|
||||
BaseColumns._ID + " = ? and " + BlobsColumns.KEY + " = ?",
|
||||
new String[] { id, key }, null, null, null);
|
||||
|
||||
if (result.getCount() == 0) {
|
||||
// either the key is wrong or no id exists
|
||||
throw new FileNotFoundException("No file found with that ID and/or password");
|
||||
}
|
||||
|
||||
File targetFile = new File(STORE_PATH, id);
|
||||
if (mode.equals("w")) {
|
||||
Log.d(Constants.TAG, "Try to open file w");
|
||||
if (!targetFile.exists()) {
|
||||
try {
|
||||
targetFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Got IEOException on creating new file", e);
|
||||
throw new FileNotFoundException("Could not create file to write to");
|
||||
}
|
||||
}
|
||||
return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_WRITE_ONLY
|
||||
| ParcelFileDescriptor.MODE_TRUNCATE);
|
||||
} else if (mode.equals("r")) {
|
||||
Log.d(Constants.TAG, "Try to open file r");
|
||||
if (!targetFile.exists()) {
|
||||
throw new FileNotFoundException("Error: Could not find the file requested");
|
||||
}
|
||||
return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -177,6 +193,7 @@ public class ProviderHelper {
|
||||
* @throws IOException
|
||||
* @throws GeneralException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void saveKeyRing(Context context, PGPPublicKeyRing keyRing) throws IOException {
|
||||
PGPPublicKey masterKey = keyRing.getPublicKey();
|
||||
long masterKeyId = masterKey.getKeyID();
|
||||
@ -232,6 +249,7 @@ public class ProviderHelper {
|
||||
* @throws IOException
|
||||
* @throws GeneralException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void saveKeyRing(Context context, PGPSecretKeyRing keyRing) throws IOException {
|
||||
PGPSecretKey masterKey = keyRing.getSecretKey();
|
||||
long masterKeyId = masterKey.getKeyID();
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@ -17,7 +33,6 @@ import org.thialfihar.android.apg.helper.PGPMain;
|
||||
import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException;
|
||||
import org.thialfihar.android.apg.util.InputData;
|
||||
import org.thialfihar.android.apg.util.Log;
|
||||
import org.thialfihar.android.apg.util.ProgressDialogUpdater;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
@ -32,7 +47,7 @@ import android.os.RemoteException;
|
||||
* - is this service thread safe? Probably not!
|
||||
*
|
||||
*/
|
||||
public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
public class ApgService extends Service {
|
||||
Context mContext;
|
||||
|
||||
@Override
|
||||
@ -53,6 +68,14 @@ public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException {
|
||||
byte[] buffer = new byte[8];
|
||||
int len = 0;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
void encryptAndSignImplementation(byte[] inputBytes, String inputUri, boolean useAsciiArmor,
|
||||
int compression, long[] encryptionKeyIds, String encryptionPassphrase,
|
||||
int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
|
||||
@ -62,6 +85,19 @@ public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
try {
|
||||
// TODO use inputUri
|
||||
|
||||
// InputStream inStream = null;
|
||||
// if (isBlob) {
|
||||
// ContentResolver cr = getContentResolver();
|
||||
// try {
|
||||
// inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "... exception on opening blob", e);
|
||||
// }
|
||||
// } else {
|
||||
// inStream = new ByteArrayInputStream(pArgs.getString(arg.MESSAGE.name()).getBytes());
|
||||
// }
|
||||
// InputData in = new InputData(inStream, 0); // XXX Size second param?
|
||||
|
||||
// build InputData and write into OutputStream
|
||||
InputStream inputStream = new ByteArrayInputStream(inputBytes);
|
||||
long inputLength = inputBytes.length;
|
||||
@ -69,13 +105,26 @@ public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
|
||||
OutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
PGPMain.encryptAndSign(mContext, ApgService.this, input, output, useAsciiArmor,
|
||||
compression, encryptionKeyIds, encryptionPassphrase,
|
||||
symmetricEncryptionAlgorithm, signatureKeyId, signatureHashAlgorithm,
|
||||
signatureForceV3, signaturePassphrase);
|
||||
PGPMain.encryptAndSign(mContext, null, input, output, useAsciiArmor, compression,
|
||||
encryptionKeyIds, encryptionPassphrase, symmetricEncryptionAlgorithm,
|
||||
signatureKeyId, signatureHashAlgorithm, signatureForceV3, signaturePassphrase);
|
||||
|
||||
output.close();
|
||||
|
||||
// if (isBlob) {
|
||||
// ContentResolver cr = getContentResolver();
|
||||
// try {
|
||||
// OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
|
||||
// .name())));
|
||||
// writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
|
||||
// outStream.close();
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "... exception on writing blob", e);
|
||||
// }
|
||||
// } else {
|
||||
// pReturn.putString(ret.RESULT.name(), out.toString());
|
||||
// }
|
||||
|
||||
byte[] outputBytes = ((ByteArrayOutputStream) output).toByteArray();
|
||||
|
||||
// return over handler on client side
|
||||
@ -103,8 +152,8 @@ public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
|
||||
OutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
Bundle outputBundle = PGPMain.decryptAndVerify(mContext, ApgService.this, inputData,
|
||||
outputStream, passphrase, assumeSymmetric);
|
||||
Bundle outputBundle = PGPMain.decryptAndVerify(mContext, null, inputData, outputStream,
|
||||
passphrase, assumeSymmetric);
|
||||
|
||||
outputStream.close();
|
||||
|
||||
@ -148,15 +197,13 @@ public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
try {
|
||||
secretKeyId = PGPMain.getDecryptionKeyId(ApgService.this, inputStream);
|
||||
if (secretKeyId == Id.key.none) {
|
||||
throw new PGPMain.ApgGeneralException(
|
||||
getString(R.string.error_noSecretKeyFound));
|
||||
throw new ApgGeneralException(getString(R.string.error_noSecretKeyFound));
|
||||
}
|
||||
symmetric = false;
|
||||
} catch (PGPMain.NoAsymmetricEncryptionException e) {
|
||||
secretKeyId = Id.key.symmetric;
|
||||
if (!PGPMain.hasSymmetricEncryption(ApgService.this, inputStream)) {
|
||||
throw new PGPMain.ApgGeneralException(
|
||||
getString(R.string.error_noKnownEncryptionFound));
|
||||
throw new ApgGeneralException(getString(R.string.error_noKnownEncryptionFound));
|
||||
}
|
||||
symmetric = true;
|
||||
}
|
||||
@ -276,21 +323,4 @@ public class ApgService extends Service implements ProgressDialogUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(String message, int current, int total) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(int resourceId, int current, int total) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(int current, int total) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.service;
|
||||
|
||||
interface IApgEncryptDecryptHandler {
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.service;
|
||||
|
||||
interface IApgHelperHandler {
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.service;
|
||||
|
||||
import org.thialfihar.android.apg.service.IApgEncryptDecryptHandler;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.service;
|
||||
|
||||
interface IApgSignVerifyHandler {
|
||||
|
@ -422,7 +422,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
||||
data.putString(ApgIntentService.NEW_PASSPHRASE, mNewPassPhrase);
|
||||
data.putStringArrayList(ApgIntentService.USER_IDS, getUserIds(mUserIdsView));
|
||||
ArrayList<PGPSecretKey> keys = getKeys(mKeysView);
|
||||
data.putByteArray(ApgIntentService.KEYS, PGPConversionHelper.PGPSecretKeyListToBytes(keys));
|
||||
data.putByteArray(ApgIntentService.KEYS, PGPConversionHelper.PGPSecretKeyArrayListToBytes(keys));
|
||||
data.putIntegerArrayList(ApgIntentService.KEYS_USAGES, getKeysUsages(mKeysView));
|
||||
data.putLong(ApgIntentService.MASTER_KEY_ID, getMasterKeyId());
|
||||
|
||||
|
@ -116,8 +116,8 @@ public class ExpandableListFragment extends Fragment implements OnCreateContextM
|
||||
pframe.addView(progress, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
root.addView(pframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
root.addView(pframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
@ -127,22 +127,22 @@ public class ExpandableListFragment extends Fragment implements OnCreateContextM
|
||||
TextView tv = new TextView(getActivity());
|
||||
tv.setId(INTERNAL_EMPTY_ID);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
lframe.addView(tv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
lframe.addView(tv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
ExpandableListView lv = new ExpandableListView(getActivity());
|
||||
lv.setId(android.R.id.list);
|
||||
lv.setDrawSelectorOnTop(false);
|
||||
lframe.addView(lv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
lframe.addView(lv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
root.addView(lframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
root.addView(lframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
root.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
root.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
@ -8,6 +8,13 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<Button
|
||||
android:id="@+id/Button02"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="encryptOnClick"
|
||||
android:text="Encrypt" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/intent_demo_create_new_key"
|
||||
android:layout_width="match_parent"
|
||||
@ -50,6 +57,13 @@
|
||||
android:onClick="encryptOnClick"
|
||||
android:text="Encrypt" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/intent_demo_encrypt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="encryptAndReturnOnClick"
|
||||
android:text="Encrypt and return result" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/intent_demo_decrypt"
|
||||
android:layout_width="match_parent"
|
||||
@ -57,6 +71,13 @@
|
||||
android:onClick="decryptOnClick"
|
||||
android:text="Decrypt" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/intent_demo_decrypt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="decryptAndReturnOnClick"
|
||||
android:text="Decrypt and return result" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -70,11 +70,20 @@ public class IntentDemoActivity extends Activity {
|
||||
|
||||
public void encryptOnClick(View view) {
|
||||
mApgIntentHelper.encrypt(mMessageTextView.getText().toString(),
|
||||
mApgData.getEncryptionKeys(), mApgData.getSignatureKeyId());
|
||||
mApgData.getEncryptionKeys(), mApgData.getSignatureKeyId(), false);
|
||||
}
|
||||
|
||||
public void encryptAndReturnOnClick(View view) {
|
||||
mApgIntentHelper.encrypt(mMessageTextView.getText().toString(),
|
||||
mApgData.getEncryptionKeys(), mApgData.getSignatureKeyId(), true);
|
||||
}
|
||||
|
||||
public void decryptOnClick(View view) {
|
||||
mApgIntentHelper.decrypt(mCiphertextTextView.getText().toString());
|
||||
mApgIntentHelper.decrypt(mCiphertextTextView.getText().toString(), false);
|
||||
}
|
||||
|
||||
public void decryptAndReturnOnClick(View view) {
|
||||
mApgIntentHelper.decrypt(mCiphertextTextView.getText().toString(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,19 +17,59 @@
|
||||
|
||||
package org.thialfihar.android.apg.integration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ApgIntentHelper {
|
||||
|
||||
public static final String APG_INTENT_PREFIX = "org.thialfihar.android.apg.intent.";
|
||||
|
||||
// Intents
|
||||
public static final String ACTION_DECRYPT = APG_INTENT_PREFIX + "DECRYPT";
|
||||
public static final String ACTION_ENCRYPT = APG_INTENT_PREFIX + "ENCRYPT";
|
||||
public static final String ACTION_DECRYPT_FILE = APG_INTENT_PREFIX + "DECRYPT_FILE";
|
||||
public static final String ACTION_ENCRYPT_FILE = APG_INTENT_PREFIX + "ENCRYPT_FILE";
|
||||
public static final String ACTION_DECRYPT_AND_RETURN = APG_INTENT_PREFIX + "DECRYPT_AND_RETURN";
|
||||
public static final String ACTION_ENCRYPT_AND_RETURN = APG_INTENT_PREFIX + "ENCRYPT_AND_RETURN";
|
||||
public static final String ACTION_SELECT_PUBLIC_KEYS = APG_INTENT_PREFIX + "SELECT_PUBLIC_KEYS";
|
||||
public static final String ACTION_SELECT_SECRET_KEY = APG_INTENT_PREFIX + "SELECT_SECRET_KEY";
|
||||
public static final String ACTION_CREATE_KEY = APG_INTENT_PREFIX + "CREATE_KEY";
|
||||
public static final String ACTION_EDIT_KEY = APG_INTENT_PREFIX + "EDIT_KEY";
|
||||
|
||||
public static final String EXTRA_TEXT = "text";
|
||||
public static final String EXTRA_DATA = "data";
|
||||
public static final String EXTRA_ERROR = "error";
|
||||
public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage";
|
||||
public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage";
|
||||
public static final String EXTRA_SIGNATURE = "signature";
|
||||
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
|
||||
public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId";
|
||||
public static final String EXTRA_SIGNATURE_SUCCESS = "signatureSuccess";
|
||||
public static final String EXTRA_SIGNATURE_UNKNOWN = "signatureUnknown";
|
||||
public static final String EXTRA_USER_ID = "userId";
|
||||
public static final String EXTRA_USER_IDS = "userIds";
|
||||
public static final String EXTRA_KEY_ID = "keyId";
|
||||
public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryptionKeyIds";
|
||||
public static final String EXTRA_SELECTION = "selection";
|
||||
public static final String EXTRA_MESSAGE = "message";
|
||||
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
|
||||
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
|
||||
public static final String EXTRA_INTENT_VERSION = "intentVersion";
|
||||
|
||||
public static final String RESULT_EXTRA_MASTER_KEY_IDS = "masterKeyIds";
|
||||
public static final String RESULT_EXTRA_USER_IDS = "userIds";
|
||||
|
||||
public static final String INTENT_VERSION = "1";
|
||||
|
||||
public static final int DECRYPT_MESSAGE = 0x21070001;
|
||||
public static final int ENCRYPT_MESSAGE = 0x21070002;
|
||||
public static final int SELECT_PUBLIC_KEYS = 0x21070003;
|
||||
public static final int SELECT_SECRET_KEY = 0x21070004;
|
||||
public static final int CREATE_KEY = 0x21070005;
|
||||
public static final int EDIT_KEY = 0x21070006;
|
||||
|
||||
private Activity activity;
|
||||
|
||||
public ApgIntentHelper(Activity activity) {
|
||||
@ -44,16 +84,16 @@ public class ApgIntentHelper {
|
||||
* @return true when activity was found and executed successfully
|
||||
*/
|
||||
public boolean createNewKey(String userIds, boolean noPassphrase, boolean generateDefaultKeys) {
|
||||
Intent intent = new Intent(Constants.Intent.CREATE_KEY);
|
||||
Intent intent = new Intent(ACTION_CREATE_KEY);
|
||||
if (userIds != null) {
|
||||
intent.putExtra(Constants.EXTRA_USER_IDS, userIds);
|
||||
intent.putExtra(EXTRA_USER_IDS, userIds);
|
||||
}
|
||||
intent.putExtra(Constants.EXTRA_NO_PASSPHRASE, noPassphrase);
|
||||
intent.putExtra(Constants.EXTRA_GENERATE_DEFAULT_KEYS, generateDefaultKeys);
|
||||
intent.putExtra(EXTRA_NO_PASSPHRASE, noPassphrase);
|
||||
intent.putExtra(EXTRA_GENERATE_DEFAULT_KEYS, generateDefaultKeys);
|
||||
|
||||
intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
try {
|
||||
activity.startActivityForResult(intent, Constants.CREATE_KEY);
|
||||
activity.startActivityForResult(intent, CREATE_KEY);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
activityNotFound();
|
||||
@ -77,11 +117,11 @@ public class ApgIntentHelper {
|
||||
* @return true when activity was found and executed successfully
|
||||
*/
|
||||
public boolean editKey(long keyId) {
|
||||
Intent intent = new Intent(Constants.Intent.EDIT_KEY);
|
||||
intent.putExtra(Constants.EXTRA_KEY_ID, keyId);
|
||||
intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION);
|
||||
Intent intent = new Intent(ACTION_EDIT_KEY);
|
||||
intent.putExtra(EXTRA_KEY_ID, keyId);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
try {
|
||||
activity.startActivityForResult(intent, Constants.EDIT_KEY);
|
||||
activity.startActivityForResult(intent, EDIT_KEY);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
activityNotFound();
|
||||
@ -95,10 +135,10 @@ public class ApgIntentHelper {
|
||||
* @return true when activity was found and executed successfully
|
||||
*/
|
||||
public boolean selectSecretKey() {
|
||||
Intent intent = new Intent(Constants.Intent.SELECT_SECRET_KEY);
|
||||
intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION);
|
||||
Intent intent = new Intent(ACTION_SELECT_SECRET_KEY);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
try {
|
||||
activity.startActivityForResult(intent, Constants.SELECT_SECRET_KEY);
|
||||
activity.startActivityForResult(intent, SELECT_SECRET_KEY);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
activityNotFound();
|
||||
@ -118,15 +158,21 @@ public class ApgIntentHelper {
|
||||
* id of the signature key
|
||||
* @return true when activity was found and executed successfully
|
||||
*/
|
||||
public boolean encrypt(String data, long[] encryptionKeyIds, long signatureKeyId) {
|
||||
Intent intent = new Intent(Constants.Intent.ENCRYPT_AND_RETURN);
|
||||
intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION);
|
||||
public boolean encrypt(String data, long[] encryptionKeyIds, long signatureKeyId,
|
||||
boolean returnResult) {
|
||||
Intent intent = new Intent();
|
||||
if (returnResult) {
|
||||
intent.setAction(ACTION_ENCRYPT_AND_RETURN);
|
||||
} else {
|
||||
intent.setAction(ACTION_ENCRYPT);
|
||||
}
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(Constants.EXTRA_TEXT, data);
|
||||
intent.putExtra(Constants.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
|
||||
intent.putExtra(Constants.EXTRA_SIGNATURE_KEY_ID, signatureKeyId);
|
||||
intent.putExtra(EXTRA_TEXT, data);
|
||||
intent.putExtra(EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
|
||||
intent.putExtra(EXTRA_SIGNATURE_KEY_ID, signatureKeyId);
|
||||
try {
|
||||
activity.startActivityForResult(intent, Constants.ENCRYPT_MESSAGE);
|
||||
activity.startActivityForResult(intent, ENCRYPT_MESSAGE);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
activityNotFound();
|
||||
@ -142,16 +188,21 @@ public class ApgIntentHelper {
|
||||
* @param pgpData
|
||||
* @return true when activity was found and executed successfully
|
||||
*/
|
||||
public boolean decrypt(String data) {
|
||||
Intent intent = new Intent(Constants.Intent.DECRYPT_AND_RETURN);
|
||||
intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION);
|
||||
public boolean decrypt(String data, boolean returnResult) {
|
||||
Intent intent = new Intent();
|
||||
if (returnResult) {
|
||||
intent.setAction(ACTION_DECRYPT_AND_RETURN);
|
||||
} else {
|
||||
intent.setAction(ACTION_DECRYPT);
|
||||
}
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
intent.setType("text/plain");
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
intent.putExtra(Constants.EXTRA_TEXT, data);
|
||||
activity.startActivityForResult(intent, Constants.DECRYPT_MESSAGE);
|
||||
intent.putExtra(EXTRA_TEXT, data);
|
||||
activity.startActivityForResult(intent, DECRYPT_MESSAGE);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
activityNotFound();
|
||||
@ -170,44 +221,42 @@ public class ApgIntentHelper {
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data, ApgData apgData) {
|
||||
|
||||
switch (requestCode) {
|
||||
case Constants.SELECT_SECRET_KEY:
|
||||
case SELECT_SECRET_KEY:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
// user canceled!
|
||||
break;
|
||||
}
|
||||
apgData.setSignatureKeyId(data.getLongExtra(Constants.EXTRA_KEY_ID, 0));
|
||||
apgData.setSignatureUserId(data.getStringExtra(Constants.EXTRA_USER_ID));
|
||||
apgData.setSignatureKeyId(data.getLongExtra(EXTRA_KEY_ID, 0));
|
||||
apgData.setSignatureUserId(data.getStringExtra(EXTRA_USER_ID));
|
||||
break;
|
||||
|
||||
case Constants.SELECT_PUBLIC_KEYS:
|
||||
case SELECT_PUBLIC_KEYS:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
apgData.setEncryptionKeys(null);
|
||||
break;
|
||||
}
|
||||
apgData.setEncryptionKeys(data.getLongArrayExtra(Constants.RESULT_EXTRA_MASTER_KEY_IDS));
|
||||
apgData.setEncryptionKeys(data.getLongArrayExtra(RESULT_EXTRA_MASTER_KEY_IDS));
|
||||
break;
|
||||
|
||||
case Constants.ENCRYPT_MESSAGE:
|
||||
case ENCRYPT_MESSAGE:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
apgData.setEncryptionKeys(null);
|
||||
break;
|
||||
}
|
||||
apgData.setEncryptedData(data.getStringExtra(Constants.EXTRA_ENCRYPTED_MESSAGE));
|
||||
apgData.setEncryptedData(data.getStringExtra(EXTRA_ENCRYPTED_MESSAGE));
|
||||
break;
|
||||
|
||||
case Constants.DECRYPT_MESSAGE:
|
||||
case DECRYPT_MESSAGE:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
apgData.setSignatureUserId(data.getStringExtra(Constants.EXTRA_SIGNATURE_USER_ID));
|
||||
apgData.setSignatureKeyId(data.getLongExtra(Constants.EXTRA_SIGNATURE_KEY_ID, 0));
|
||||
apgData.setSignatureSuccess(data.getBooleanExtra(Constants.EXTRA_SIGNATURE_SUCCESS,
|
||||
false));
|
||||
apgData.setSignatureUnknown(data.getBooleanExtra(Constants.EXTRA_SIGNATURE_UNKNOWN,
|
||||
false));
|
||||
apgData.setSignatureUserId(data.getStringExtra(EXTRA_SIGNATURE_USER_ID));
|
||||
apgData.setSignatureKeyId(data.getLongExtra(EXTRA_SIGNATURE_KEY_ID, 0));
|
||||
apgData.setSignatureSuccess(data.getBooleanExtra(EXTRA_SIGNATURE_SUCCESS, false));
|
||||
apgData.setSignatureUnknown(data.getBooleanExtra(EXTRA_SIGNATURE_UNKNOWN, false));
|
||||
|
||||
apgData.setDecryptedData(data.getStringExtra(Constants.EXTRA_DECRYPTED_MESSAGE));
|
||||
apgData.setDecryptedData(data.getStringExtra(EXTRA_DECRYPTED_MESSAGE));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -238,46 +287,23 @@ public class ApgIntentHelper {
|
||||
* @return true when activity was found and executed successfully
|
||||
*/
|
||||
public boolean selectEncryptionKeys(String emails, ApgData apgData) {
|
||||
Intent intent = new Intent(Constants.Intent.SELECT_PUBLIC_KEYS);
|
||||
intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION);
|
||||
Intent intent = new Intent(ACTION_SELECT_PUBLIC_KEYS);
|
||||
intent.putExtra(EXTRA_INTENT_VERSION, INTENT_VERSION);
|
||||
|
||||
long[] initialKeyIds = null;
|
||||
if (apgData == null || !apgData.hasEncryptionKeys()) {
|
||||
List<Long> keyIds = new ArrayList<Long>();
|
||||
if (apgData != null && apgData.hasSignatureKey()) {
|
||||
keyIds.add(apgData.getSignatureKeyId());
|
||||
}
|
||||
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(
|
||||
Constants.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, emails);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null) {
|
||||
while (c.moveToNext()) {
|
||||
keyIds.add(c.getLong(0));
|
||||
}
|
||||
}
|
||||
ContentProviderHelper cPHelper = new ContentProviderHelper(activity);
|
||||
|
||||
initialKeyIds = cPHelper.getPublicKeyIdsFromEmail(emails);
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
if (!keyIds.isEmpty()) {
|
||||
initialKeyIds = new long[keyIds.size()];
|
||||
for (int i = 0, size = keyIds.size(); i < size; ++i) {
|
||||
initialKeyIds[i] = keyIds.get(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
initialKeyIds = apgData.getEncryptionKeys();
|
||||
}
|
||||
intent.putExtra(Constants.EXTRA_SELECTION, initialKeyIds);
|
||||
intent.putExtra(EXTRA_SELECTION, initialKeyIds);
|
||||
|
||||
try {
|
||||
activity.startActivityForResult(intent, Constants.SELECT_PUBLIC_KEYS);
|
||||
activity.startActivityForResult(intent, SELECT_PUBLIC_KEYS);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
activityNotFound();
|
||||
@ -285,162 +311,8 @@ public class ApgIntentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get secret key ids based on a given email.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return key ids
|
||||
*/
|
||||
public long[] getSecretKeyIdsFromEmail(String email) {
|
||||
long ids[] = null;
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS,
|
||||
email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
ids = new long[c.getCount()];
|
||||
while (c.moveToNext()) {
|
||||
ids[c.getPosition()] = c.getLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public key ids based on a given email.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return key ids
|
||||
*/
|
||||
public long[] getPublicKeyIdsFromEmail(String email) {
|
||||
long ids[] = null;
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS,
|
||||
email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
ids = new long[c.getCount()];
|
||||
while (c.moveToNext()) {
|
||||
ids[c.getPosition()] = c.getLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a given email has a secret key.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return true if there is a secret key for this email.
|
||||
*/
|
||||
public boolean hasSecretKeyForEmail(String email) {
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS,
|
||||
email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
c.close();
|
||||
return true;
|
||||
}
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a given email has a public key.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return true if there is a public key for this email.
|
||||
*/
|
||||
public boolean hasPublicKeyForEmail(String email) {
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS,
|
||||
email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
c.close();
|
||||
return true;
|
||||
}
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user id based on the key id.
|
||||
*
|
||||
* @param context
|
||||
* @param keyId
|
||||
* @return user id
|
||||
*/
|
||||
public String getUserId(long keyId) {
|
||||
String userId = null;
|
||||
try {
|
||||
Uri contentUri = ContentUris.withAppendedId(
|
||||
Constants.CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID, keyId);
|
||||
Cursor c = activity.getContentResolver().query(contentUri, new String[] { "user_id" },
|
||||
null, null, null);
|
||||
if (c != null && c.moveToFirst()) {
|
||||
userId = c.getString(0);
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
|
||||
if (userId == null) {
|
||||
userId = "unknown";
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
private void activityNotFound() {
|
||||
Toast.makeText(activity, "APG Activity not found! Is APG installed correctly?",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void insufficientPermissions() {
|
||||
Toast.makeText(activity, "Permission to access APG Provider is missing!", Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.integration;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
public class ApgServiceHelper {
|
||||
|
||||
private final static String BLOB_URI = "content://org.thialfihar.android.apg.provider.apgserviceblobprovider";
|
||||
|
||||
private Context context;
|
||||
|
||||
public ApgServiceHelper(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up binary data to en/decrypt
|
||||
*
|
||||
* @param is
|
||||
* InputStream to get the data from
|
||||
*/
|
||||
public void setBlob(InputStream is) {
|
||||
Log.d(Constants.TAG, "setBlob() called");
|
||||
// 1. get the new contentUri
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
Uri contentUri = cr.insert(Uri.parse(BLOB_URI), new ContentValues());
|
||||
|
||||
// 2. insert binary data
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = cr.openOutputStream(contentUri, "w");
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "... exception on setBlob", e);
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[8];
|
||||
int len = 0;
|
||||
try {
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
Log.d(Constants.TAG, "... write finished, now closing");
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "... error on writing buffer", e);
|
||||
}
|
||||
|
||||
// mArgs.putString("BLOB", contentUri.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the binary result
|
||||
*
|
||||
* <p>
|
||||
* This gets your binary result. It only works if you called {@link #setBlob(InputStream)}
|
||||
* before.
|
||||
*
|
||||
* If you did not call encrypt nor decrypt, this will be the same data as you inputed.
|
||||
* </p>
|
||||
*
|
||||
* @return InputStream of the binary data which was en/decrypted
|
||||
*
|
||||
* @see #setBlob(InputStream)
|
||||
* @see #getResult()
|
||||
*/
|
||||
public InputStream getBlobResult() {
|
||||
// if (mArgs.containsKey("BLOB")) {
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
InputStream in = null;
|
||||
try {
|
||||
// in = cr.openInputStream(Uri.parse(mArgs.getString("BLOB")));
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "Could not return blob in result", e);
|
||||
}
|
||||
return in;
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -17,70 +16,12 @@
|
||||
|
||||
package org.thialfihar.android.apg.integration;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
public class Constants {
|
||||
public static final String NAME = "apg";
|
||||
|
||||
public static final String TAG = "APG Integration Lib";
|
||||
|
||||
public static final String APG_PACKAGE_NAME = "org.thialfihar.android.apg";
|
||||
public static final int MIN_REQUIRED_VERSION = 50;
|
||||
|
||||
public static final String AUTHORITY = "org.thialfihar.android.apg.provider";
|
||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/secret/key_id/");
|
||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/secret/emails/");
|
||||
|
||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/public/key_id/");
|
||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/public/emails/");
|
||||
|
||||
public static final String APG_INTENT_PREFIX = "org.thialfihar.android.apg.intent.";
|
||||
|
||||
public static class Intent {
|
||||
public static final String DECRYPT = APG_INTENT_PREFIX + "DECRYPT";
|
||||
public static final String ENCRYPT = APG_INTENT_PREFIX + "ENCRYPT";
|
||||
public static final String DECRYPT_FILE = APG_INTENT_PREFIX + "DECRYPT_FILE";
|
||||
public static final String ENCRYPT_FILE = APG_INTENT_PREFIX + "ENCRYPT_FILE";
|
||||
public static final String DECRYPT_AND_RETURN = APG_INTENT_PREFIX + "DECRYPT_AND_RETURN";
|
||||
public static final String ENCRYPT_AND_RETURN = APG_INTENT_PREFIX + "ENCRYPT_AND_RETURN";
|
||||
public static final String SELECT_PUBLIC_KEYS = APG_INTENT_PREFIX + "SELECT_PUBLIC_KEYS";
|
||||
public static final String SELECT_SECRET_KEY = APG_INTENT_PREFIX + "SELECT_SECRET_KEY";
|
||||
public static final String CREATE_KEY = APG_INTENT_PREFIX + "CREATE_KEY";
|
||||
public static final String EDIT_KEY = APG_INTENT_PREFIX + "EDIT_KEY";
|
||||
}
|
||||
|
||||
public static final String EXTRA_TEXT = "text";
|
||||
public static final String EXTRA_DATA = "data";
|
||||
public static final String EXTRA_ERROR = "error";
|
||||
public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage";
|
||||
public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage";
|
||||
public static final String EXTRA_SIGNATURE = "signature";
|
||||
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
|
||||
public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId";
|
||||
public static final String EXTRA_SIGNATURE_SUCCESS = "signatureSuccess";
|
||||
public static final String EXTRA_SIGNATURE_UNKNOWN = "signatureUnknown";
|
||||
public static final String EXTRA_USER_ID = "userId";
|
||||
public static final String EXTRA_USER_IDS = "userIds";
|
||||
public static final String EXTRA_KEY_ID = "keyId";
|
||||
public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryptionKeyIds";
|
||||
public static final String EXTRA_SELECTION = "selection";
|
||||
public static final String EXTRA_MESSAGE = "message";
|
||||
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
|
||||
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
|
||||
public static final String EXTRA_INTENT_VERSION = "intentVersion";
|
||||
|
||||
|
||||
public static final String RESULT_EXTRA_MASTER_KEY_IDS = "masterKeyIds";
|
||||
public static final String RESULT_EXTRA_USER_IDS = "userIds";
|
||||
|
||||
public static final String INTENT_VERSION = "1";
|
||||
|
||||
public static final int DECRYPT_MESSAGE = 0x21070001;
|
||||
public static final int ENCRYPT_MESSAGE = 0x21070002;
|
||||
public static final int SELECT_PUBLIC_KEYS = 0x21070003;
|
||||
public static final int SELECT_SECRET_KEY = 0x21070004;
|
||||
public static final int CREATE_KEY = 0x21070005;
|
||||
public static final int EDIT_KEY = 0x21070006;
|
||||
}
|
||||
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
*
|
||||
* Licensed 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 org.thialfihar.android.apg.integration;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ContentProviderHelper {
|
||||
public static final String AUTHORITY = Constants.APG_PACKAGE_NAME;
|
||||
|
||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/public/key_id/");
|
||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/public/emails/");
|
||||
|
||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/secret/key_id/");
|
||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://"
|
||||
+ AUTHORITY + "/key_rings/secret/emails/");
|
||||
|
||||
private Context activity;
|
||||
|
||||
public ContentProviderHelper(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get secret key ids based on a given email.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return key ids
|
||||
*/
|
||||
public long[] getSecretKeyIdsFromEmail(String email) {
|
||||
long ids[] = null;
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(CONTENT_URI_SECRET_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
ids = new long[c.getCount()];
|
||||
while (c.moveToNext()) {
|
||||
ids[c.getPosition()] = c.getLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public key ids based on a given email.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return key ids
|
||||
*/
|
||||
public long[] getPublicKeyIdsFromEmail(String email) {
|
||||
long ids[] = null;
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
ids = new long[c.getCount()];
|
||||
while (c.moveToNext()) {
|
||||
ids[c.getPosition()] = c.getLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a given email has a secret key.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return true if there is a secret key for this email.
|
||||
*/
|
||||
public boolean hasSecretKeyForEmail(String email) {
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(CONTENT_URI_SECRET_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
c.close();
|
||||
return true;
|
||||
}
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out if a given email has a public key.
|
||||
*
|
||||
* @param context
|
||||
* @param email
|
||||
* The email in question.
|
||||
* @return true if there is a public key for this email.
|
||||
*/
|
||||
public boolean hasPublicKeyForEmail(String email) {
|
||||
try {
|
||||
Uri contentUri = Uri.withAppendedPath(CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, email);
|
||||
Cursor c = activity.getContentResolver().query(contentUri,
|
||||
new String[] { "master_key_id" }, null, null, null);
|
||||
if (c != null && c.getCount() > 0) {
|
||||
c.close();
|
||||
return true;
|
||||
}
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user id based on the key id.
|
||||
*
|
||||
* @param context
|
||||
* @param keyId
|
||||
* @return user id
|
||||
*/
|
||||
public String getUserId(long keyId) {
|
||||
String userId = null;
|
||||
try {
|
||||
Uri contentUri = ContentUris.withAppendedId(CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID,
|
||||
keyId);
|
||||
Cursor c = activity.getContentResolver().query(contentUri, new String[] { "user_id" },
|
||||
null, null, null);
|
||||
if (c != null && c.moveToFirst()) {
|
||||
userId = c.getString(0);
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
insufficientPermissions();
|
||||
}
|
||||
|
||||
if (userId == null) {
|
||||
userId = "unknown";
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
private void insufficientPermissions() {
|
||||
Toast.makeText(activity, "Permission to access APG Provider is missing!", Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010-2011 K-9 Mail Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
Loading…
Reference in New Issue
Block a user