diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2013-01-07 15:56:56 +0100 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2013-01-07 15:56:56 +0100 |
commit | 9758cb673f7db8c9a5e6951a1afadaaa85b787d6 (patch) | |
tree | eae4fb8739b2aa270bb7890a7a18546f5338a3a5 | |
parent | 05778fd4827fde2bd56686c2fa007adc00ba8176 (diff) | |
download | open-keychain-9758cb673f7db8c9a5e6951a1afadaaa85b787d6.tar.gz open-keychain-9758cb673f7db8c9a5e6951a1afadaaa85b787d6.tar.bz2 open-keychain-9758cb673f7db8c9a5e6951a1afadaaa85b787d6.zip |
Externalize all import actions into ImportKeysActivity
-rw-r--r-- | APG/AndroidManifest.xml | 109 | ||||
-rw-r--r-- | APG/res/layout/import_keys.xml (renamed from APG/res/layout/import_from_qr_code.xml) | 7 | ||||
-rw-r--r-- | APG/res/values/strings.xml | 4 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/Id.java | 13 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java | 6 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java | 272 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/ImportKeysActivity.java | 501 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/KeyListActivity.java | 158 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/KeyListFragment.java | 4 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/KeyListPublicActivity.java | 77 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/KeyListPublicFragment.java | 32 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java | 9 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java | 9 | ||||
-rw-r--r-- | APG/src/org/thialfihar/android/apg/ui/MainActivity.java | 5 | ||||
-rw-r--r-- | README.md | 3 |
15 files changed, 663 insertions, 546 deletions
diff --git a/APG/AndroidManifest.xml b/APG/AndroidManifest.xml index 408e48364..cff694b0f 100644 --- a/APG/AndroidManifest.xml +++ b/APG/AndroidManifest.xml @@ -110,57 +110,6 @@ <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> - <!-- APG's own Actions --> - <intent-filter android:label="@string/intent_import_key" > - <action android:name="org.thialfihar.android.apg.intent.IMPORT" /> - - <category android:name="android.intent.category.DEFAULT" /> - - <data android:mimeType="*/*" /> - </intent-filter> - <!-- Linking "Import key" to file types --> - <intent-filter android:label="@string/intent_import_key" > - <action android:name="android.intent.action.VIEW" /> - - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - - <data android:host="*" /> - <data android:scheme="file" /> - <data android:scheme="content" /> - <data android:mimeType="*/*" /> - <data android:pathPattern=".*\\.gpg" /> - <data android:pathPattern=".*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> - </intent-filter> - <intent-filter android:label="@string/intent_import_key" > - <action android:name="android.intent.action.VIEW" /> - - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - - <data android:host="*" /> - <data android:scheme="file" /> - <data android:scheme="content" /> - <data android:mimeType="*/*" /> - <data android:pathPattern=".*\\.asc" /> - <data android:pathPattern=".*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> - <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> - </intent-filter> <meta-data android:name="android.app.searchable" @@ -349,13 +298,63 @@ android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:label="@string/title_signKey" /> <activity - android:name=".ui.ImportFromQRCodeActivity" + android:name="org.thialfihar.android.apg.ui.ImportKeysActivity" android:configChanges="orientation|screenSize|keyboardHidden|keyboard" - android:label="@string/title_importFromQRCode" > - <intent-filter> - <action android:name="org.thialfihar.android.apg.intent.SCAN_QR_CODE" /> + android:label="@string/title_importFromQRCode" + android:uiOptions="splitActionBarWhenNarrow" > + + <!-- APG's own Actions --> + <intent-filter android:label="@string/intent_import_key" > + <action android:name="org.thialfihar.android.apg.intent.IMPORT" /> + <action android:name="org.thialfihar.android.apg.intent.IMPORT_FROM_QR_CODE" /> + <action android:name="org.thialfihar.android.apg.intent.IMPORT_FROM_NFC" /> + + <category android:name="android.intent.category.DEFAULT" /> + + <data android:mimeType="*/*" /> + </intent-filter> + <!-- Linking "Import key" to file types --> + <intent-filter android:label="@string/intent_import_key" > + <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data android:host="*" /> + <data android:scheme="file" /> + <data android:scheme="content" /> + <data android:mimeType="*/*" /> + <data android:pathPattern=".*\\.gpg" /> + <data android:pathPattern=".*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.gpg" /> + </intent-filter> + <intent-filter android:label="@string/intent_import_key" > + <action android:name="android.intent.action.VIEW" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data android:host="*" /> + <data android:scheme="file" /> + <data android:scheme="content" /> + <data android:mimeType="*/*" /> + <data android:pathPattern=".*\\.asc" /> + <data android:pathPattern=".*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> + <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.asc" /> </intent-filter> </activity> <activity diff --git a/APG/res/layout/import_from_qr_code.xml b/APG/res/layout/import_keys.xml index f20dbbb68..8e107cd96 100644 --- a/APG/res/layout/import_from_qr_code.xml +++ b/APG/res/layout/import_keys.xml @@ -28,13 +28,6 @@ android:text="@string/import_from_qr_code_import_sign_and_upload" /> <Button - android:id="@+id/import_from_qr_code_scan_again" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:onClick="scanAgainOnClick" - android:text="@string/import_from_qr_code_scan_again" /> - - <Button android:id="@+id/import_from_qr_code_finish" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/APG/res/values/strings.xml b/APG/res/values/strings.xml index 215905b3c..709b6da0d 100644 --- a/APG/res/values/strings.xml +++ b/APG/res/values/strings.xml @@ -89,7 +89,9 @@ <string name="menu_managePublicKeys">Manage Public Keyrings</string> <string name="menu_manageSecretKeys">Manage Secret Keyrings</string> <string name="menu_preferences">Settings</string> - <string name="menu_importKeys">Import Keyrings</string> + <string name="menu_importFromFile">Import from file</string> + <string name="menu_importFromQrCode">Import from QR Code</string> + <string name="menu_importFromNfc">Import from NFC</string> <string name="menu_exportKeys">Export All Keyrings</string> <string name="menu_exportKey">Export Keyring</string> <string name="menu_deleteKey">Delete Keyring</string> diff --git a/APG/src/org/thialfihar/android/apg/Id.java b/APG/src/org/thialfihar/android/apg/Id.java index e683f43b4..4d01ef5c4 100644 --- a/APG/src/org/thialfihar/android/apg/Id.java +++ b/APG/src/org/thialfihar/android/apg/Id.java @@ -44,7 +44,6 @@ public final class Id { public static final int about = 0x21070003; public static final int manage_public_keys = 0x21070004; public static final int manage_secret_keys = 0x21070005; - public static final int import_keys = 0x21070006; public static final int export_keys = 0x21070007; public static final int preferences = 0x21070008; public static final int search = 0x21070009; @@ -58,7 +57,9 @@ public final class Id { public static final int cancel = 0x21070017; public static final int save = 0x21070018; public static final int okay = 0x21070019; - + public static final int import_from_file = 0x21070020; + public static final int import_from_qr_code = 0x21070021; + public static final int import_from_nfc = 0x21070022; } } @@ -147,10 +148,10 @@ public final class Id { public static final int export_keys = 0x21070002; } -// public static final class database { -// public static final int type_public = 0; -// public static final int type_secret = 1; -// } + // public static final class database { + // public static final int type_public = 0; + // public static final int type_secret = 1; + // } public static final class type { public static final int public_key = 0x21070001; diff --git a/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java b/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java index 125b557a3..7d715b78b 100644 --- a/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java +++ b/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java @@ -589,7 +589,11 @@ public class ProviderHelper { Log.e(Constants.TAG, "No master keys given!"); } - return output; + if (output.size() > 0) { + return output; + } else { + return null; + } } public static byte[] getPublicKeyRingsAsByteArray(Context context, long[] masterKeyIds) { diff --git a/APG/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java b/APG/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java deleted file mode 100644 index 0e4258829..000000000 --- a/APG/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de> - * Copyright (C) 2011 Senecaso - * - * 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.ui; - -import org.thialfihar.android.apg.Constants; -import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.helper.OtherHelper; -import org.thialfihar.android.apg.service.ApgIntentServiceHandler; -import org.thialfihar.android.apg.service.ApgIntentService; -import org.thialfihar.android.apg.R; - -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; - -import org.thialfihar.android.apg.util.Log; - -import android.view.View; -import android.widget.TextView; -import android.widget.Toast; - -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.MenuItem; -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; - -public class ImportFromQRCodeActivity extends SherlockFragmentActivity { - - // Not used in sourcode, but listed in AndroidManifest! - public static final String SCAN_QR_CODE = Constants.INTENT_PREFIX + "SCAN_QR_CODE"; - - // public static final String EXTRA_KEY_ID = "keyId"; - - private TextView mContentView; - - private String mScannedContent; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.import_from_qr_code); - mContentView = (TextView) findViewById(R.id.import_from_qr_code_content); - - // set actionbar without home button if called from another app - OtherHelper.setActionBarBackButton(this); - - // start scanning - new IntentIntegrator(this).initiateScan(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - - case android.R.id.home: - // app icon in Action Bar clicked; go home - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; - - default: { - return super.onOptionsItemSelected(item); - } - } - } - - // private void importAndSignOld(final long keyId, final String expectedFingerprint) { - // if (expectedFingerprint != null && expectedFingerprint.length() > 0) { - // - // Thread t = new Thread() { - // @Override - // public void run() { - // try { - // // TODO: display some sort of spinner here while the user waits - // - // // TODO: there should be only 1 - // HkpKeyServer server = new HkpKeyServer(mPreferences.getKeyServers()[0]); - // String encodedKey = server.get(keyId); - // - // PGPKeyRing keyring = PGPHelper.decodeKeyRing(new ByteArrayInputStream( - // encodedKey.getBytes())); - // if (keyring != null && keyring instanceof PGPPublicKeyRing) { - // PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring; - // - // // make sure the fingerprints match before we cache this thing - // String actualFingerprint = PGPHelper.convertToHex(publicKeyRing - // .getPublicKey().getFingerprint()); - // if (expectedFingerprint.equals(actualFingerprint)) { - // // store the signed key in our local cache - // int retval = PGPMain.storeKeyRingInCache(publicKeyRing); - // if (retval != Id.return_value.ok - // && retval != Id.return_value.updated) { - // status.putString(EXTRA_ERROR, - // "Failed to store signed key in local cache"); - // } else { - // Intent intent = new Intent(ImportFromQRCodeActivity.this, - // SignKeyActivity.class); - // intent.putExtra(EXTRA_KEY_ID, keyId); - // startActivityForResult(intent, Id.request.sign_key); - // } - // } else { - // status.putString( - // EXTRA_ERROR, - // "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key."); - // } - // } - // } catch (QueryException e) { - // Log.e(TAG, "Failed to query KeyServer", e); - // status.putString(EXTRA_ERROR, "Failed to query KeyServer"); - // status.putInt(Constants.extras.STATUS, Id.message.done); - // } catch (IOException e) { - // Log.e(TAG, "Failed to query KeyServer", e); - // status.putString(EXTRA_ERROR, "Failed to query KeyServer"); - // status.putInt(Constants.extras.STATUS, Id.message.done); - // } - // } - // }; - // - // t.setName("KeyExchange Download Thread"); - // t.setDaemon(true); - // t.start(); - // } - // } - - public void scanAgainOnClick(View view) { - new IntentIntegrator(this).initiateScan(); - } - - public void finishOnClick(View view) { - finish(); - } - - public void importOnClick(View view) { - Log.d(Constants.TAG, "import key started"); - - if (mScannedContent != null) { - // Send all information needed to service to import key in other thread - Intent intent = new Intent(this, ApgIntentService.class); - - intent.putExtra(ApgIntentService.EXTRA_ACTION, ApgIntentService.ACTION_IMPORT_KEY); - - // fill values for this action - Bundle data = new Bundle(); - - data.putInt(ApgIntentService.IMPORT_KEY_TYPE, Id.type.public_key); - - data.putInt(ApgIntentService.TARGET, ApgIntentService.TARGET_BYTES); - data.putByteArray(ApgIntentService.IMPORT_BYTES, mScannedContent.getBytes()); - - intent.putExtra(ApgIntentService.EXTRA_DATA, data); - - // Message is received after importing is done in ApgService - ApgIntentServiceHandler saveHandler = new ApgIntentServiceHandler(this, - R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard ApgHandler first - super.handleMessage(message); - - if (message.arg1 == ApgIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle returnData = message.getData(); - - int added = returnData.getInt(ApgIntentService.RESULT_IMPORT_ADDED); - int updated = returnData.getInt(ApgIntentService.RESULT_IMPORT_UPDATED); - int bad = returnData.getInt(ApgIntentService.RESULT_IMPORT_BAD); - String toastMessage; - if (added > 0 && updated > 0) { - toastMessage = getString(R.string.keysAddedAndUpdated, added, updated); - } else if (added > 0) { - toastMessage = getString(R.string.keysAdded, added); - } else if (updated > 0) { - toastMessage = getString(R.string.keysUpdated, updated); - } else { - toastMessage = getString(R.string.noKeysAddedOrUpdated); - } - Toast.makeText(ImportFromQRCodeActivity.this, toastMessage, - Toast.LENGTH_SHORT).show(); - if (bad > 0) { - AlertDialog.Builder alert = new AlertDialog.Builder( - ImportFromQRCodeActivity.this); - - alert.setIcon(android.R.drawable.ic_dialog_alert); - alert.setTitle(R.string.warning); - alert.setMessage(ImportFromQRCodeActivity.this.getString( - R.string.badKeysEncountered, bad)); - - alert.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - alert.setCancelable(true); - alert.create().show(); - } - } - }; - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(ApgIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } - } - - public void signAndUploadOnClick(View view) { - // first, import! - importOnClick(view); - - // TODO: implement sign and upload! - Toast.makeText(ImportFromQRCodeActivity.this, "Not implemented right now!", - Toast.LENGTH_SHORT).show(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case IntentIntegrator.REQUEST_CODE: { - IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, - data); - if (scanResult != null && scanResult.getFormatName() != null) { - - mScannedContent = scanResult.getContents(); - - mContentView.setText(mScannedContent); - // String[] bits = scanResult.getContents().split(","); - // if (bits.length != 2) { - // return; // dont know how to handle this. Not a valid code - // } - // - // long keyId = Long.parseLong(bits[0]); - // String expectedFingerprint = bits[1]; - - // importAndSign(keyId, expectedFingerprint); - } - - break; - } - - default: { - super.onActivityResult(requestCode, resultCode, data); - } - } - } -} diff --git a/APG/src/org/thialfihar/android/apg/ui/ImportKeysActivity.java b/APG/src/org/thialfihar/android/apg/ui/ImportKeysActivity.java new file mode 100644 index 000000000..bb40d1033 --- /dev/null +++ b/APG/src/org/thialfihar/android/apg/ui/ImportKeysActivity.java @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2011 Senecaso + * + * 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.ui; + +import org.thialfihar.android.apg.Constants; +import org.thialfihar.android.apg.Id; +import org.thialfihar.android.apg.compatibility.DialogFragmentWorkaround; +import org.thialfihar.android.apg.helper.OtherHelper; +import org.thialfihar.android.apg.service.ApgIntentServiceHandler; +import org.thialfihar.android.apg.service.ApgIntentService; +import org.thialfihar.android.apg.R; + +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; + +import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment; +import org.thialfihar.android.apg.ui.dialog.FileDialogFragment; +import org.thialfihar.android.apg.util.Log; + +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + +public class ImportKeysActivity extends SherlockFragmentActivity { + + public static final String ACTION = Constants.INTENT_PREFIX + "IMPORT"; + public static final String ACTION_IMPORT_FROM_FILE = Constants.INTENT_PREFIX + + "IMPORT_FROM_FILE"; + public static final String ACTION_IMPORT_FROM_QR_CODE = Constants.INTENT_PREFIX + + "IMPORT_FROM_QR_CODE"; + public static final String ACTION_IMPORT_FROM_NFC = Constants.INTENT_PREFIX + "IMPORT_FROM_NFC"; + + // only used by IMPORT_AND_RETURN + public static final String EXTRA_TEXT = "text"; + + protected String mImportFilename = Constants.path.APP_DIR + "/"; + + // public static final String EXTRA_KEY_ID = "keyId"; + + protected String mImportData; + protected boolean mDeleteAfterImport = false; + + FileDialogFragment mFileDialog; + + private TextView mContentView; + + private String mScannedContent; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.import_keys); + mContentView = (TextView) findViewById(R.id.import_from_qr_code_content); + + // set actionbar without home button if called from another app + OtherHelper.setActionBarBackButton(this); + + handleActions(getIntent()); + } + + /** + * ActionBar menu is created based on class variables to change it at runtime + * + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(1, Id.menu.option.import_from_file, 0, R.string.menu_importFromFile) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(1, Id.menu.option.import_from_qr_code, 1, R.string.menu_importFromQrCode) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(1, Id.menu.option.import_from_nfc, 2, R.string.menu_importFromNfc) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + + case android.R.id.home: + // app icon in Action Bar clicked; go home + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + + case Id.menu.option.import_from_file: + showImportKeysDialog(); + + return true; + + case Id.menu.option.import_from_qr_code: + importFromQrCode(); + + return true; + + case Id.menu.option.import_from_nfc: + + return true; + + default: + return super.onOptionsItemSelected(item); + + } + } + + protected void handleActions(Intent intent) { + String action = intent.getAction(); + Bundle extras = intent.getExtras(); + + if (extras == null) { + extras = new Bundle(); + } + + /** + * Android Standard Actions + */ + if (Intent.ACTION_VIEW.equals(action)) { + // Android's Action when opening file associated to APG (see AndroidManifest.xml) + // override action to delegate it to APGs ACTION_IMPORT + action = ACTION; + } + + /** + * APG's own Actions + */ + if (ACTION.equals(action)) { + if ("file".equals(intent.getScheme()) && intent.getDataString() != null) { + mImportFilename = intent.getData().getPath(); + } else { + mImportData = intent.getStringExtra(EXTRA_TEXT); + } + importKeys(); + } else if (ACTION_IMPORT_FROM_FILE.equals(action)) { + if ("file".equals(intent.getScheme()) && intent.getDataString() != null) { + mImportFilename = intent.getData().getPath(); + } + showImportKeysDialog(); + } else if (ACTION_IMPORT_FROM_QR_CODE.equals(action)) { + importFromQrCode(); + } else if (ACTION_IMPORT_FROM_NFC.equals(action)) { + + } + } + + private void importFromQrCode() { + new IntentIntegrator(this).initiateScan(); + } + + /** + * Show to dialog from where to import keys + */ + public void showImportKeysDialog() { + // Message is received after file is selected + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == FileDialogFragment.MESSAGE_OKAY) { + Log.d(Constants.TAG, "FileDialogFragment.MESSAGE_OKAY"); + Bundle data = message.getData(); + mImportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); + + mDeleteAfterImport = data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED); + importKeys(); + } + } + }; + + // Create a new Messenger for the communication back + final Messenger messenger = new Messenger(returnHandler); + + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + mFileDialog = FileDialogFragment.newInstance(messenger, + getString(R.string.title_importKeys), + getString(R.string.specifyFileToImportFrom), mImportFilename, null, + Id.request.filename); + + mFileDialog.show(getSupportFragmentManager(), "fileDialog"); + } + }); + } + + /** + * Import keys with mImportData + */ + public void importKeys() { + Log.d(Constants.TAG, "importKeys started"); + + // Send all information needed to service to import key in other thread + Intent intent = new Intent(this, ApgIntentService.class); + + intent.putExtra(ApgIntentService.EXTRA_ACTION, ApgIntentService.ACTION_IMPORT_KEY); + + // fill values for this action + Bundle data = new Bundle(); + + // TODO + data.putInt(ApgIntentService.IMPORT_KEY_TYPE, Id.type.secret_key); + + if (mImportData != null) { + data.putInt(ApgIntentService.TARGET, ApgIntentService.TARGET_BYTES); + data.putByteArray(ApgIntentService.IMPORT_BYTES, mImportData.getBytes()); + } else { + data.putInt(ApgIntentService.TARGET, ApgIntentService.TARGET_FILE); + data.putString(ApgIntentService.IMPORT_FILENAME, mImportFilename); + } + + intent.putExtra(ApgIntentService.EXTRA_DATA, data); + + // Message is received after importing is done in ApgService + ApgIntentServiceHandler saveHandler = new ApgIntentServiceHandler(this, + R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == ApgIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + + int added = returnData.getInt(ApgIntentService.RESULT_IMPORT_ADDED); + int updated = returnData.getInt(ApgIntentService.RESULT_IMPORT_UPDATED); + int bad = returnData.getInt(ApgIntentService.RESULT_IMPORT_BAD); + String toastMessage; + if (added > 0 && updated > 0) { + toastMessage = getString(R.string.keysAddedAndUpdated, added, updated); + } else if (added > 0) { + toastMessage = getString(R.string.keysAdded, added); + } else if (updated > 0) { + toastMessage = getString(R.string.keysUpdated, updated); + } else { + toastMessage = getString(R.string.noKeysAddedOrUpdated); + } + Toast.makeText(ImportKeysActivity.this, toastMessage, Toast.LENGTH_SHORT) + .show(); + if (bad > 0) { + AlertDialog.Builder alert = new AlertDialog.Builder(ImportKeysActivity.this); + + alert.setIcon(android.R.drawable.ic_dialog_alert); + alert.setTitle(R.string.warning); + alert.setMessage(ImportKeysActivity.this.getString( + R.string.badKeysEncountered, bad)); + + alert.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + alert.setCancelable(true); + alert.create().show(); + } else if (mDeleteAfterImport) { + // everything went well, so now delete, if that was turned on + DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment + .newInstance(mImportFilename); + deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); + } + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(ApgIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } + + // private void importAndSignOld(final long keyId, final String expectedFingerprint) { + // if (expectedFingerprint != null && expectedFingerprint.length() > 0) { + // + // Thread t = new Thread() { + // @Override + // public void run() { + // try { + // // TODO: display some sort of spinner here while the user waits + // + // // TODO: there should be only 1 + // HkpKeyServer server = new HkpKeyServer(mPreferences.getKeyServers()[0]); + // String encodedKey = server.get(keyId); + // + // PGPKeyRing keyring = PGPHelper.decodeKeyRing(new ByteArrayInputStream( + // encodedKey.getBytes())); + // if (keyring != null && keyring instanceof PGPPublicKeyRing) { + // PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring; + // + // // make sure the fingerprints match before we cache this thing + // String actualFingerprint = PGPHelper.convertToHex(publicKeyRing + // .getPublicKey().getFingerprint()); + // if (expectedFingerprint.equals(actualFingerprint)) { + // // store the signed key in our local cache + // int retval = PGPMain.storeKeyRingInCache(publicKeyRing); + // if (retval != Id.return_value.ok + // && retval != Id.return_value.updated) { + // status.putString(EXTRA_ERROR, + // "Failed to store signed key in local cache"); + // } else { + // Intent intent = new Intent(ImportFromQRCodeActivity.this, + // SignKeyActivity.class); + // intent.putExtra(EXTRA_KEY_ID, keyId); + // startActivityForResult(intent, Id.request.sign_key); + // } + // } else { + // status.putString( + // EXTRA_ERROR, + // "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key."); + // } + // } + // } catch (QueryException e) { + // Log.e(TAG, "Failed to query KeyServer", e); + // status.putString(EXTRA_ERROR, "Failed to query KeyServer"); + // status.putInt(Constants.extras.STATUS, Id.message.done); + // } catch (IOException e) { + // Log.e(TAG, "Failed to query KeyServer", e); + // status.putString(EXTRA_ERROR, "Failed to query KeyServer"); + // status.putInt(Constants.extras.STATUS, Id.message.done); + // } + // } + // }; + // + // t.setName("KeyExchange Download Thread"); + // t.setDaemon(true); + // t.start(); + // } + // } + + public void scanAgainOnClick(View view) { + new IntentIntegrator(this).initiateScan(); + } + + public void finishOnClick(View view) { + finish(); + } + + public void importOnClick(View view) { + Log.d(Constants.TAG, "import key started"); + + if (mScannedContent != null) { + // Send all information needed to service to import key in other thread + Intent intent = new Intent(this, ApgIntentService.class); + + intent.putExtra(ApgIntentService.EXTRA_ACTION, ApgIntentService.ACTION_IMPORT_KEY); + + // fill values for this action + Bundle data = new Bundle(); + + data.putInt(ApgIntentService.IMPORT_KEY_TYPE, Id.type.public_key); + + data.putInt(ApgIntentService.TARGET, ApgIntentService.TARGET_BYTES); + data.putByteArray(ApgIntentService.IMPORT_BYTES, mScannedContent.getBytes()); + + intent.putExtra(ApgIntentService.EXTRA_DATA, data); + + // Message is received after importing is done in ApgService + ApgIntentServiceHandler saveHandler = new ApgIntentServiceHandler(this, + R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == ApgIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + + int added = returnData.getInt(ApgIntentService.RESULT_IMPORT_ADDED); + int updated = returnData.getInt(ApgIntentService.RESULT_IMPORT_UPDATED); + int bad = returnData.getInt(ApgIntentService.RESULT_IMPORT_BAD); + String toastMessage; + if (added > 0 && updated > 0) { + toastMessage = getString(R.string.keysAddedAndUpdated, added, updated); + } else if (added > 0) { + toastMessage = getString(R.string.keysAdded, added); + } else if (updated > 0) { + toastMessage = getString(R.string.keysUpdated, updated); + } else { + toastMessage = getString(R.string.noKeysAddedOrUpdated); + } + Toast.makeText(ImportKeysActivity.this, toastMessage, Toast.LENGTH_SHORT) + .show(); + if (bad > 0) { + AlertDialog.Builder alert = new AlertDialog.Builder( + ImportKeysActivity.this); + + alert.setIcon(android.R.drawable.ic_dialog_alert); + alert.setTitle(R.string.warning); + alert.setMessage(ImportKeysActivity.this.getString( + R.string.badKeysEncountered, bad)); + + alert.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + alert.setCancelable(true); + alert.create().show(); + } + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(ApgIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } + } + + public void signAndUploadOnClick(View view) { + // first, import! + importOnClick(view); + + // TODO: implement sign and upload! + Toast.makeText(ImportKeysActivity.this, "Not implemented right now!", Toast.LENGTH_SHORT) + .show(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case Id.request.filename: { + if (resultCode == RESULT_OK && data != null) { + try { + String path = data.getData().getPath(); + Log.d(Constants.TAG, "path=" + path); + + // set filename used in export/import dialogs + mFileDialog.setFilename(path); + } catch (NullPointerException e) { + Log.e(Constants.TAG, "Nullpointer while retrieving path!", e); + } + } + return; + } + case IntentIntegrator.REQUEST_CODE: { + IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, + data); + if (scanResult != null && scanResult.getFormatName() != null) { + + mScannedContent = scanResult.getContents(); + + mContentView.setText(mScannedContent); + // String[] bits = scanResult.getContents().split(","); + // if (bits.length != 2) { + // return; // dont know how to handle this. Not a valid code + // } + // + // long keyId = Long.parseLong(bits[0]); + // String expectedFingerprint = bits[1]; + + // importAndSign(keyId, expectedFingerprint); + } + + break; + } + + default: { + super.onActivityResult(requestCode, resultCode, data); + } + } + } +} diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListActivity.java b/APG/src/org/thialfihar/android/apg/ui/KeyListActivity.java index a4f547090..bc345fe90 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyListActivity.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyListActivity.java @@ -23,15 +23,12 @@ import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.compatibility.DialogFragmentWorkaround; import org.thialfihar.android.apg.service.ApgIntentService; import org.thialfihar.android.apg.service.ApgIntentServiceHandler; -import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment; import org.thialfihar.android.apg.ui.dialog.DeleteKeyDialogFragment; import org.thialfihar.android.apg.ui.dialog.FileDialogFragment; import org.thialfihar.android.apg.util.Log; -import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.SearchManager; -import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -45,15 +42,6 @@ import com.actionbarsherlock.view.MenuItem; public class KeyListActivity extends SherlockFragmentActivity { - public static final String ACTION_IMPORT = Constants.INTENT_PREFIX + "IMPORT"; - - public static final String EXTRA_TEXT = "text"; - - // protected View mFilterLayout; - // protected Button mClearFilterButton; - // protected TextView mFilterInfo; - - protected String mImportFilename = Constants.path.APP_DIR + "/"; protected String mExportFilename = Constants.path.APP_DIR + "/"; protected String mImportData; @@ -97,12 +85,9 @@ public class KeyListActivity extends SherlockFragmentActivity { if (searchString != null && searchString.trim().length() == 0) { searchString = null; } - } else if (Intent.ACTION_VIEW.equals(action)) { - // Android's Action when opening file associated to APG (see AndroidManifest.xml) - // override action to delegate it to APGs ACTION_IMPORT - action = ACTION_IMPORT; } + // if (searchString == null) { // mFilterLayout.setVisibility(View.GONE); // } else { @@ -116,17 +101,6 @@ public class KeyListActivity extends SherlockFragmentActivity { // mListAdapter = new KeyListAdapter(this, searchString); // mList.setAdapter(mListAdapter); - /** - * APG's own Actions - */ - if (ACTION_IMPORT.equals(action)) { - if ("file".equals(intent.getScheme()) && intent.getDataString() != null) { - mImportFilename = intent.getData().getPath(); - } else { - mImportData = intent.getStringExtra(EXTRA_TEXT); - } - importKeys(); - } } @Override @@ -160,7 +134,7 @@ public class KeyListActivity extends SherlockFragmentActivity { // TODO: reimplement! // menu.add(3, Id.menu.option.search, 0, R.string.menu_search) // .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - menu.add(0, Id.menu.option.import_keys, 5, R.string.menu_importKeys).setShowAsAction( + menu.add(0, Id.menu.option.import_from_file, 5, R.string.menu_importFromFile).setShowAsAction( MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); menu.add(0, Id.menu.option.export_keys, 6, R.string.menu_exportKeys).setShowAsAction( MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); @@ -179,8 +153,10 @@ public class KeyListActivity extends SherlockFragmentActivity { startActivity(intent); return true; - case Id.menu.option.import_keys: { - showImportKeysDialog(); + case Id.menu.option.import_from_file: { + Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class); + intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_FILE); + startActivityForResult(intentImportFromFile, 0); return true; } @@ -200,40 +176,6 @@ public class KeyListActivity extends SherlockFragmentActivity { } /** - * Show to dialog from where to import keys - */ - public void showImportKeysDialog() { - // Message is received after file is selected - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == FileDialogFragment.MESSAGE_OKAY) { - Log.d(Constants.TAG, "FileDialogFragment.MESSAGE_OKAY"); - Bundle data = message.getData(); - mImportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); - - mDeleteAfterImport = data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED); - importKeys(); - } - } - }; - - // Create a new Messenger for the communication back - final Messenger messenger = new Messenger(returnHandler); - - DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { - public void run() { - mFileDialog = FileDialogFragment.newInstance(messenger, - getString(R.string.title_importKeys), - getString(R.string.specifyFileToImportFrom), mImportFilename, null, - Id.request.filename); - - mFileDialog.show(getSupportFragmentManager(), "fileDialog"); - } - }); - } - - /** * Show dialog where to export keys * * @param keyRingRowId @@ -307,94 +249,6 @@ public class KeyListActivity extends SherlockFragmentActivity { } /** - * Import keys with mImportData - */ - public void importKeys() { - Log.d(Constants.TAG, "importKeys started"); - - // Send all information needed to service to import key in other thread - Intent intent = new Intent(this, ApgIntentService.class); - - intent.putExtra(ApgIntentService.EXTRA_ACTION, ApgIntentService.ACTION_IMPORT_KEY); - - // fill values for this action - Bundle data = new Bundle(); - - data.putInt(ApgIntentService.IMPORT_KEY_TYPE, mKeyType); - - if (mImportData != null) { - data.putInt(ApgIntentService.TARGET, ApgIntentService.TARGET_BYTES); - data.putByteArray(ApgIntentService.IMPORT_BYTES, mImportData.getBytes()); - } else { - data.putInt(ApgIntentService.TARGET, ApgIntentService.TARGET_FILE); - data.putString(ApgIntentService.IMPORT_FILENAME, mImportFilename); - } - - intent.putExtra(ApgIntentService.EXTRA_DATA, data); - - // Message is received after importing is done in ApgService - ApgIntentServiceHandler saveHandler = new ApgIntentServiceHandler(this, - R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard ApgHandler first - super.handleMessage(message); - - if (message.arg1 == ApgIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle returnData = message.getData(); - - int added = returnData.getInt(ApgIntentService.RESULT_IMPORT_ADDED); - int updated = returnData.getInt(ApgIntentService.RESULT_IMPORT_UPDATED); - int bad = returnData.getInt(ApgIntentService.RESULT_IMPORT_BAD); - String toastMessage; - if (added > 0 && updated > 0) { - toastMessage = getString(R.string.keysAddedAndUpdated, added, updated); - } else if (added > 0) { - toastMessage = getString(R.string.keysAdded, added); - } else if (updated > 0) { - toastMessage = getString(R.string.keysUpdated, updated); - } else { - toastMessage = getString(R.string.noKeysAddedOrUpdated); - } - Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show(); - if (bad > 0) { - AlertDialog.Builder alert = new AlertDialog.Builder(KeyListActivity.this); - - alert.setIcon(android.R.drawable.ic_dialog_alert); - alert.setTitle(R.string.warning); - alert.setMessage(KeyListActivity.this.getString( - R.string.badKeysEncountered, bad)); - - alert.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - alert.setCancelable(true); - alert.create().show(); - } else if (mDeleteAfterImport) { - // everything went well, so now delete, if that was turned on - DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment - .newInstance(mImportFilename); - deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); - } - } - }; - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(ApgIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } - - /** * Export keys * * @param keyRingRowId diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListFragment.java b/APG/src/org/thialfihar/android/apg/ui/KeyListFragment.java index 613f32ae9..f8f62287c 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyListFragment.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyListFragment.java @@ -51,8 +51,8 @@ public class KeyListFragment extends ExpandableListFragment { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); - menu.add(0, Id.menu.export, 0, R.string.menu_exportKey); - menu.add(0, Id.menu.delete, 1, R.string.menu_deleteKey); + menu.add(0, Id.menu.export, 5, R.string.menu_exportKey); + menu.add(0, Id.menu.delete, 111, R.string.menu_deleteKey); } @Override diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListPublicActivity.java b/APG/src/org/thialfihar/android/apg/ui/KeyListPublicActivity.java index 6f07b7e8a..50fb64da2 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyListPublicActivity.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyListPublicActivity.java @@ -43,13 +43,14 @@ public class KeyListPublicActivity extends KeyListActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - - menu.add(1, Id.menu.option.scanQRCode, 1, R.string.menu_scanQRCode) - .setIcon(R.drawable.ic_menu_scan_qrcode) + menu.add(1, Id.menu.option.key_server, 1, R.string.menu_keyServer) + .setIcon(R.drawable.ic_menu_search_list) + .setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS); + menu.add(1, Id.menu.option.import_from_qr_code, 2, R.string.menu_importFromQrCode) .setShowAsAction( MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); - menu.add(1, Id.menu.option.key_server, 2, R.string.menu_keyServer) - .setIcon(R.drawable.ic_menu_search_list) + menu.add(1, Id.menu.option.import_from_nfc, 3, R.string.menu_importFromNfc) .setShowAsAction( MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); @@ -64,41 +65,57 @@ public class KeyListPublicActivity extends KeyListActivity { return true; } - case Id.menu.option.scanQRCode: { - Intent intent = new Intent(this, ImportFromQRCodeActivity.class); - intent.setAction(ImportFromQRCodeActivity.SCAN_QR_CODE); - startActivityForResult(intent, Id.request.import_from_qr_code); + case Id.menu.option.import_from_file: { + Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class); + intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_FILE); + startActivityForResult(intentImportFromFile, 0); return true; } - default: { - return super.onOptionsItemSelected(item); - } + case Id.menu.option.import_from_qr_code: { + Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class); + intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_QR_CODE); + startActivityForResult(intentImportFromFile, Id.request.import_from_qr_code); + + return true; } - } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case Id.request.look_up_key_id: { - if (resultCode == RESULT_CANCELED || data == null - || data.getStringExtra(KeyServerQueryActivity.RESULT_EXTRA_TEXT) == null) { - return; - } - - Intent intent = new Intent(this, KeyListPublicActivity.class); - intent.setAction(KeyListPublicActivity.ACTION_IMPORT); - intent.putExtra(KeyListPublicActivity.EXTRA_TEXT, - data.getStringExtra(KeyListActivity.EXTRA_TEXT)); - handleActions(intent); - break; + case Id.menu.option.import_from_nfc: { + Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class); + intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_NFC); + startActivityForResult(intentImportFromFile, 0); + + return true; } default: { - super.onActivityResult(requestCode, resultCode, data); - break; + return super.onOptionsItemSelected(item); } } } + + // @Override + // protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // switch (requestCode) { + // case Id.request.look_up_key_id: { + // if (resultCode == RESULT_CANCELED || data == null + // || data.getStringExtra(KeyServerQueryActivity.RESULT_EXTRA_TEXT) == null) { + // return; + // } + // + // Intent intent = new Intent(this, KeyListPublicActivity.class); + // intent.setAction(KeyListPublicActivity.ACTION_IMPORT); + // intent.putExtra(KeyListPublicActivity.EXTRA_TEXT, + // data.getStringExtra(KeyListActivity.EXTRA_TEXT)); + // handleActions(intent); + // break; + // } + // + // default: { + // super.onActivityResult(requestCode, resultCode, data); + // break; + // } + // } + // } } diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListPublicFragment.java b/APG/src/org/thialfihar/android/apg/ui/KeyListPublicFragment.java index e1a93602c..29c2823a1 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyListPublicFragment.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyListPublicFragment.java @@ -17,6 +17,8 @@ package org.thialfihar.android.apg.ui; +import java.util.ArrayList; + import org.spongycastle.openpgp.PGPPublicKeyRing; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; @@ -26,6 +28,8 @@ import org.thialfihar.android.apg.provider.ApgContract.KeyRings; import org.thialfihar.android.apg.provider.ApgContract.UserIds; import org.thialfihar.android.apg.ui.widget.KeyListAdapter; +import com.google.zxing.integration.android.IntentIntegrator; + import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -37,6 +41,7 @@ import android.view.ContextMenu; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.ExpandableListView; +import android.widget.Toast; import android.widget.ExpandableListView.ExpandableListContextMenuInfo; public class KeyListPublicFragment extends KeyListFragment implements @@ -74,8 +79,10 @@ public class KeyListPublicFragment extends KeyListFragment implements public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, Id.menu.update, 1, R.string.menu_updateKey); - menu.add(0, Id.menu.exportToServer, 1, R.string.menu_exportKeyToServer); - menu.add(0, Id.menu.signKey, 1, R.string.menu_signKey); + menu.add(0, Id.menu.signKey, 2, R.string.menu_signKey); + menu.add(0, Id.menu.exportToServer, 3, R.string.menu_exportKeyToServer); + menu.add(0, Id.menu.share_qr_code, 6, R.string.menu_share); + } @Override @@ -90,8 +97,8 @@ public class KeyListPublicFragment extends KeyListFragment implements switch (item.getItemId()) { case Id.menu.update: long updateKeyId = 0; - PGPPublicKeyRing updateKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(mKeyListActivity, - keyRingRowId); + PGPPublicKeyRing updateKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId( + mKeyListActivity, keyRingRowId); if (updateKeyRing != null) { updateKeyId = PGPHelper.getMasterKey(updateKeyRing).getKeyID(); } @@ -119,8 +126,8 @@ public class KeyListPublicFragment extends KeyListFragment implements case Id.menu.signKey: long keyId = 0; - PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(mKeyListActivity, - keyRingRowId); + PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId( + mKeyListActivity, keyRingRowId); if (signKeyRing != null) { keyId = PGPHelper.getMasterKey(signKeyRing).getKeyID(); } @@ -135,12 +142,25 @@ public class KeyListPublicFragment extends KeyListFragment implements return true; + case Id.menu.share_qr_code: + // get master key id using row id + long masterKeyId = ProviderHelper.getPublicMasterKeyId(mKeyListActivity, keyRingRowId); + shareByQrCode(masterKeyId); + + return true; + default: return super.onContextItemSelected(item); } } + private void shareByQrCode(long masterKeyId) { + ArrayList<String> keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString( + mKeyListActivity, new long[] { masterKeyId }); + new IntentIntegrator(mKeyListActivity).shareText(keyringArmored.get(0)); + } + // These are the rows that we will retrieve. static final String[] PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID, UserIds.USER_ID }; diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java b/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java index 0d12f5fe4..1e852fd54 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java @@ -38,6 +38,7 @@ import android.view.ContextMenu; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.ExpandableListView; +import android.widget.Toast; import android.widget.ExpandableListView.ExpandableListContextMenuInfo; public class KeyListSecretFragment extends KeyListFragment implements @@ -74,9 +75,7 @@ public class KeyListSecretFragment extends KeyListFragment implements @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); - menu.add(0, Id.menu.edit, 0, R.string.menu_editKey); - menu.add(0, Id.menu.share_qr_code, 2, R.string.menu_share); } @Override @@ -97,18 +96,14 @@ public class KeyListSecretFragment extends KeyListFragment implements mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId); return true; - case Id.menu.share_qr_code: - ArrayList<String> keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString( - mKeyListSecretActivity, new long[] { masterKeyId }); - new IntentIntegrator(mKeyListSecretActivity).shareText(keyringArmored.get(0)); - return true; default: return super.onContextItemSelected(item); } } + // These are the rows that we will retrieve. static final String[] PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID, UserIds.USER_ID }; diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java b/APG/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java index 7cd54bf32..bce6785cf 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java @@ -40,6 +40,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.Message; import android.os.Messenger; +import android.provider.ContactsContract.CommonDataKinds.Im; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -187,8 +188,8 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { intent.putExtra(ApgIntentService.EXTRA_DATA, data); // Message is received after querying is done in ApgService - ApgIntentServiceHandler saveHandler = new ApgIntentServiceHandler(this, R.string.progress_querying, - ProgressDialog.STYLE_SPINNER) { + ApgIntentServiceHandler saveHandler = new ApgIntentServiceHandler(this, + R.string.progress_querying, ProgressDialog.STYLE_SPINNER) { public void handleMessage(Message message) { // handle messages by standard ApgHandler first super.handleMessage(message); @@ -227,8 +228,8 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { if (mKeyData != null) { Intent intent = new Intent(KeyServerQueryActivity.this, KeyListPublicActivity.class); - intent.setAction(KeyListActivity.ACTION_IMPORT); - intent.putExtra(KeyListActivity.EXTRA_TEXT, mKeyData); + intent.setAction(ImportKeysActivity.ACTION); + intent.putExtra(ImportKeysActivity.EXTRA_TEXT, mKeyData); startActivity(intent); } } diff --git a/APG/src/org/thialfihar/android/apg/ui/MainActivity.java b/APG/src/org/thialfihar/android/apg/ui/MainActivity.java index 565b6853b..b647299d1 100644 --- a/APG/src/org/thialfihar/android/apg/ui/MainActivity.java +++ b/APG/src/org/thialfihar/android/apg/ui/MainActivity.java @@ -56,9 +56,8 @@ public class MainActivity extends SherlockActivity { } public void scanQrcodeOnClick(View view) { - Intent intent = new Intent(this, ImportFromQRCodeActivity.class); - intent.setAction(ImportFromQRCodeActivity.SCAN_QR_CODE); - startActivityForResult(intent, Id.request.import_from_qr_code); + Intent intent = new Intent(this, ImportKeysActivity.class); + startActivityForResult(intent, 0); } public void helpOnClick(View view) { @@ -80,6 +80,9 @@ Android primitives to exchange data: Intent, Intent with return values, Send (al * android.intent.action.VIEW connected to .gpg and .asc files: Import Key and Decrypt * android.intent.action.SEND connected to all mime types (text/plain and every binary data like files and images): Encrypt and Decrypt * IMPORT +* IMPORT_FROM_FILE +* IMPORT_FROM_QR_CODE +* IMPORT_FROM_NFC * EDIT_KEY * SELECT_PUBLIC_KEYS * SELECT_SECRET_KEY |