diff options
Diffstat (limited to 'OpenKeychain/src')
27 files changed, 375 insertions, 235 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index 43bed8397..41f1e6997 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -285,9 +285,9 @@ public class HkpKeyserver extends Keyserver {              // group 1 contains the full fingerprint (v4) or the long key id if available              // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr -            String fingerprintOrKeyId = matcher.group(1); +            String fingerprintOrKeyId = matcher.group(1).toLowerCase(Locale.US);              if (fingerprintOrKeyId.length() > 16) { -                entry.setFingerprintHex(fingerprintOrKeyId.toLowerCase(Locale.US)); +                entry.setFingerprintHex(fingerprintOrKeyId);                  entry.setKeyIdHex("0x" + fingerprintOrKeyId.substring(fingerprintOrKeyId.length()                          - 16, fingerprintOrKeyId.length()));              } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index b1bd6a77a..861f93446 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -354,7 +354,7 @@ public class PgpKeyOperation {              subProgressPush(15, 25);              for (int i = 0; i < saveParcel.mAddUserIds.size(); i++) { -                progress(R.string.progress_modify_adduid, (i-1) * (100 / saveParcel.mAddSubKeys.size())); +                progress(R.string.progress_modify_adduid, (i-1) * (100 / saveParcel.mAddUserIds.size()));                  String userId = saveParcel.mAddUserIds.get(i);                  log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent); @@ -399,7 +399,7 @@ public class PgpKeyOperation {              subProgressPush(25, 40);              for (int i = 0; i < saveParcel.mRevokeUserIds.size(); i++) { -                progress(R.string.progress_modify_revokeuid, (i-1) * (100 / saveParcel.mAddSubKeys.size())); +                progress(R.string.progress_modify_revokeuid, (i-1) * (100 / saveParcel.mRevokeUserIds.size()));                  String userId = saveParcel.mRevokeUserIds.get(i);                  log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent, userId); @@ -522,7 +522,7 @@ public class PgpKeyOperation {              subProgressPush(50, 60);              for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) { -                progress(R.string.progress_modify_subkeychange, (i-1) * (100 / saveParcel.mAddSubKeys.size())); +                progress(R.string.progress_modify_subkeychange, (i-1) * (100 / saveParcel.mChangeSubKeys.size()));                  SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);                  log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE,                          indent, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); @@ -583,7 +583,7 @@ public class PgpKeyOperation {              subProgressPush(60, 70);              for (int i = 0; i < saveParcel.mRevokeSubKeys.size(); i++) { -                progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / saveParcel.mAddSubKeys.size())); +                progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / saveParcel.mRevokeSubKeys.size()));                  long revocation = saveParcel.mRevokeSubKeys.get(i);                  log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_REVOKE,                          indent, PgpKeyHelper.convertKeyIdToHex(revocation)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 502e3a70c..690317170 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -300,14 +300,14 @@ public class UncachedKeyRing {                      revocation = zert;                      // more revocations? at least one is superfluous, then.                  } else if (revocation.getCreationTime().before(zert.getCreationTime())) { +                    log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, indent);                      modified = PGPPublicKey.removeCertification(modified, revocation);                      redundantCerts += 1; -                    log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, indent);                      revocation = zert;                  } else { +                    log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, indent);                      modified = PGPPublicKey.removeCertification(modified, zert);                      redundantCerts += 1; -                    log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, indent);                  }              } @@ -331,12 +331,13 @@ public class UncachedKeyRing {                                  indent, "0x" + Integer.toString(zert.getSignatureType(), 16));                          modified = PGPPublicKey.removeCertification(modified, userId, zert);                          badCerts += 1; +                        continue;                      }                      if (cert.getCreationTime().after(now)) {                          // Creation date in the future? No way!                          log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_TIME, indent); -                        modified = PGPPublicKey.removeCertification(modified, zert); +                        modified = PGPPublicKey.removeCertification(modified, userId, zert);                          badCerts += 1;                          continue;                      } @@ -344,7 +345,7 @@ public class UncachedKeyRing {                      if (cert.isLocal()) {                          // Creation date in the future? No way!                          log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_LOCAL, indent); -                        modified = PGPPublicKey.removeCertification(modified, zert); +                        modified = PGPPublicKey.removeCertification(modified, userId, zert);                          badCerts += 1;                          continue;                      } @@ -387,35 +388,35 @@ public class UncachedKeyRing {                              if (selfCert == null) {                                  selfCert = zert;                              } else if (selfCert.getCreationTime().before(cert.getCreationTime())) { -                                modified = PGPPublicKey.removeCertification(modified, userId, selfCert); -                                redundantCerts += 1;                                  log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_DUP,                                          indent, userId); +                                modified = PGPPublicKey.removeCertification(modified, userId, selfCert); +                                redundantCerts += 1;                                  selfCert = zert;                              } else { -                                modified = PGPPublicKey.removeCertification(modified, userId, zert); -                                redundantCerts += 1;                                  log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_DUP,                                          indent, userId); +                                modified = PGPPublicKey.removeCertification(modified, userId, zert); +                                redundantCerts += 1;                              }                              // If there is a revocation certificate, and it's older than this, drop it                              if (revocation != null                                      && revocation.getCreationTime().before(selfCert.getCreationTime())) { +                                log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD, +                                        indent, userId);                                  modified = PGPPublicKey.removeCertification(modified, userId, revocation);                                  revocation = null;                                  redundantCerts += 1; -                                log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD, -                                        indent, userId);                              }                              break;                          case PGPSignature.CERTIFICATION_REVOCATION:                              // If this is older than the (latest) self cert, drop it                              if (selfCert != null && selfCert.getCreationTime().after(zert.getCreationTime())) { -                                modified = PGPPublicKey.removeCertification(modified, userId, zert); -                                redundantCerts += 1;                                  log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD,                                          indent, userId); +                                modified = PGPPublicKey.removeCertification(modified, userId, zert); +                                redundantCerts += 1;                                  continue;                              }                              // first revocation? remember it. @@ -423,16 +424,16 @@ public class UncachedKeyRing {                                  revocation = zert;                                  // more revocations? at least one is superfluous, then.                              } else if (revocation.getCreationTime().before(cert.getCreationTime())) { -                                modified = PGPPublicKey.removeCertification(modified, userId, revocation); -                                redundantCerts += 1;                                  log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_DUP,                                          indent, userId); +                                modified = PGPPublicKey.removeCertification(modified, userId, revocation); +                                redundantCerts += 1;                                  revocation = zert;                              } else { -                                modified = PGPPublicKey.removeCertification(modified, userId, zert); -                                redundantCerts += 1;                                  log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_DUP,                                          indent, userId); +                                modified = PGPPublicKey.removeCertification(modified, userId, zert); +                                redundantCerts += 1;                              }                              break; @@ -442,9 +443,9 @@ public class UncachedKeyRing {                  // If no valid certificate (if only a revocation) remains, drop it                  if (selfCert == null && revocation == null) { -                    modified = PGPPublicKey.removeCertification(modified, userId);                      log.add(LogLevel.ERROR, LogType.MSG_KC_UID_REMOVE,                              indent, userId); +                    modified = PGPPublicKey.removeCertification(modified, userId);                  }              } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index 34de0024d..aa0207a6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -1,5 +1,6 @@  package org.sufficientlysecure.keychain.provider; +import android.database.Cursor;  import android.net.Uri;  import org.sufficientlysecure.keychain.Constants; @@ -33,6 +34,7 @@ public class CachedPublicKeyRing extends KeyRing {          mUri = uri;      } +    @Override      public long getMasterKeyId() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, @@ -59,10 +61,21 @@ public class CachedPublicKeyRing extends KeyRing {          return getMasterKeyId();      } +    public byte[] getFingerprint() throws PgpGeneralException { +        try { +            Object data = mProviderHelper.getGenericData(mUri, +                    KeychainContract.KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); +            return (byte[]) data; +        } catch (ProviderHelper.NotFoundException e) { +            throw new PgpGeneralException(e); +        } +    } + +    @Override      public String getPrimaryUserId() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.USER_ID,                      ProviderHelper.FIELD_TYPE_STRING);              return (String) data;          } catch(ProviderHelper.NotFoundException e) { @@ -74,10 +87,11 @@ public class CachedPublicKeyRing extends KeyRing {          return getPrimaryUserId();      } +    @Override      public boolean isRevoked() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.IS_REVOKED,                      ProviderHelper.FIELD_TYPE_INTEGER);              return (Long) data > 0;          } catch(ProviderHelper.NotFoundException e) { @@ -85,10 +99,11 @@ public class CachedPublicKeyRing extends KeyRing {          }      } +    @Override      public boolean canCertify() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.CAN_CERTIFY,                      ProviderHelper.FIELD_TYPE_INTEGER);              return (Long) data > 0;          } catch(ProviderHelper.NotFoundException e) { @@ -96,21 +111,32 @@ public class CachedPublicKeyRing extends KeyRing {          }      } +    @Override      public long getEncryptId() throws PgpGeneralException {          try { -            Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, -                    ProviderHelper.FIELD_TYPE_INTEGER); -            return (Long) data; -        } catch(ProviderHelper.NotFoundException e) { +            Cursor subkeys = getSubkeys(); +            if (subkeys != null) { +                try { +                    while (subkeys.moveToNext()) { +                        if (subkeys.getInt(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.CAN_ENCRYPT)) != 0) { +                            return subkeys.getLong(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.KEY_ID)); +                        } +                    } +                } finally { +                    subkeys.close(); +                } +            } +        } catch(Exception e) {              throw new PgpGeneralException(e);          } +        throw new PgpGeneralException("No encrypt key found");      } +    @Override      public boolean hasEncrypt() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.HAS_ENCRYPT,                      ProviderHelper.FIELD_TYPE_INTEGER);              return (Long) data > 0;          } catch(ProviderHelper.NotFoundException e) { @@ -118,21 +144,32 @@ public class CachedPublicKeyRing extends KeyRing {          }      } +    @Override      public long getSignId() throws PgpGeneralException {          try { -            Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, -                    ProviderHelper.FIELD_TYPE_INTEGER); -            return (Long) data; -        } catch(ProviderHelper.NotFoundException e) { +            Cursor subkeys = getSubkeys(); +            if (subkeys != null) { +                try { +                    while (subkeys.moveToNext()) { +                        if (subkeys.getInt(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.CAN_SIGN)) != 0) { +                            return subkeys.getLong(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.KEY_ID)); +                        } +                    } +                } finally { +                    subkeys.close(); +                } +            } +        } catch(Exception e) {              throw new PgpGeneralException(e);          } +        throw new PgpGeneralException("No sign key found");      } +    @Override      public boolean hasSign() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.HAS_SIGN,                      ProviderHelper.FIELD_TYPE_INTEGER);              return (Long) data > 0;          } catch(ProviderHelper.NotFoundException e) { @@ -140,10 +177,11 @@ public class CachedPublicKeyRing extends KeyRing {          }      } +    @Override      public int getVerified() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.VERIFIED,                      ProviderHelper.FIELD_TYPE_INTEGER);              return (Integer) data;          } catch(ProviderHelper.NotFoundException e) { @@ -154,12 +192,16 @@ public class CachedPublicKeyRing extends KeyRing {      public boolean hasAnySecret() throws PgpGeneralException {          try {              Object data = mProviderHelper.getGenericData(mUri, -                    KeychainContract.KeyRings.MASTER_KEY_ID, +                    KeychainContract.KeyRings.HAS_ANY_SECRET,                      ProviderHelper.FIELD_TYPE_INTEGER);              return (Long) data > 0;          } catch(ProviderHelper.NotFoundException e) {              throw new PgpGeneralException(e);          } +    } +    private Cursor getSubkeys() throws PgpGeneralException { +        Uri keysUri = KeychainContract.Keys.buildKeysUri(Long.toString(extractOrGetMasterKeyId())); +        return mProviderHelper.getContentResolver().query(keysUri, null, null, null, null);      }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 9b35903f6..aa85577e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1024,4 +1024,8 @@ public class ProviderHelper {              }          }      } + +    public ContentResolver getContentResolver() { +        return mContentResolver; +    }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 8d4717eeb..bcc042146 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -523,6 +523,11 @@ public class KeychainIntentService extends IntentService                  Intent importIntent = new Intent(this, KeychainIntentService.class);                  importIntent.setAction(ACTION_IMPORT_KEYRING); + +                // TODO: don't use FileImportCache +                // externalize import key into function +                FileImportCache cache = new FileImportCache(this); +                cache.writeCache(keyRings);                  Bundle importData = new Bundle();                  // This is not going through binder, nothing to fear of                  importData.putParcelableArrayList(IMPORT_KEY_LIST, keyRings); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 3c69fb071..467e0c14a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -139,7 +139,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements                          Notify.showNotify(CertifyKeyActivity.this, getString(R.string.select_key_to_certify),                                  Notify.Style.ERROR);                      } else { -                        initiateSigning(); +                        initiateCertifying();                      }                  }              } @@ -229,7 +229,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements      /**       * handles the UI bits of the signing process on the UI thread       */ -    private void initiateSigning() { +    private void initiateCertifying() {          // get the user's passphrase for this key (if required)          String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);          if (passphrase == null) { @@ -238,7 +238,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements                          @Override                          public void handleMessage(Message message) {                              if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { -                                startSigning(); +                                startCertifying();                              }                          }                      } @@ -246,15 +246,14 @@ public class CertifyKeyActivity extends ActionBarActivity implements              // bail out; need to wait until the user has entered the passphrase before trying again              return;          } else { -            startSigning(); +            startCertifying();          }      }      /**       * kicks off the actual signing process on a background thread       */ -    private void startSigning() { - +    private void startCertifying() {          // Bail out if there is not at least one user id selected          ArrayList<String> userIds = mUserIdsAdapter.getSelectedUserIds();          if (userIds.isEmpty()) { @@ -279,7 +278,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements          // Message is received after signing is done in KeychainIntentService          KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, -                getString(R.string.progress_signing), ProgressDialog.STYLE_SPINNER) { +                getString(R.string.progress_certifying), ProgressDialog.STYLE_SPINNER) {              public void handleMessage(Message message) {                  // handle messages by standard KeychainIntentServiceHandler first                  super.handleMessage(message); @@ -333,7 +332,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements          // Message is received after uploading is done in KeychainIntentService          KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, -                getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) { +                getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) {              public void handleMessage(Message message) {                  // handle messages by standard KeychainIntentServiceHandler first                  super.handleMessage(message); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index b64480087..f9ed16cba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -145,20 +145,20 @@ public class CreateKeyFinalFragment extends Fragment {                          return;                      } -                    if (mUploadCheckbox.isChecked()) { -                        if (result.getResult() == OperationResultParcel.RESULT_OK) { +                    if (result.getResult() == OperationResultParcel.RESULT_OK) { +                        if (mUploadCheckbox.isChecked()) {                              // result will be displayed after upload                              uploadKey(result);                          } else { -                            // display result on error without finishing activity +                            // TODO: return result                              result.createNotify(getActivity()); + +                            getActivity().setResult(Activity.RESULT_OK); +                            getActivity().finish();                          }                      } else { -                        // TODO: return result +                        // display result on error without finishing activity                          result.createNotify(getActivity()); - -                        getActivity().setResult(Activity.RESULT_OK); -                        getActivity().finish();                      }                  }              } @@ -196,9 +196,8 @@ public class CreateKeyFinalFragment extends Fragment {          intent.setAction(KeychainIntentService.ACTION_UPLOAD_KEYRING);          // set data uri as path to keyring -        Uri blobUri = KeychainContract.KeyRingData.buildPublicKeyRingUri( -                Long.toString(editKeyResult.mRingMasterKeyId) -        ); +        Uri blobUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri( +                editKeyResult.mRingMasterKeyId);          intent.setData(blobUri);          // fill values for this action @@ -212,14 +211,15 @@ public class CreateKeyFinalFragment extends Fragment {          // Message is received after uploading is done in KeychainIntentService          KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), -                getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) { +                getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) {              public void handleMessage(Message message) {                  // handle messages by standard KeychainIntentServiceHandler first                  super.handleMessage(message);                  if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { -                    // TODO: return results - +                    // TODO: not supported by upload? +//                    if (result.getResult() == OperationResultParcel.RESULT_OK) { +                    // TODO: return result                      editKeyResult.createNotify(getActivity());                      Notify.showNotify(getActivity(), R.string.key_send_success, @@ -227,6 +227,10 @@ public class CreateKeyFinalFragment extends Fragment {                      getActivity().setResult(Activity.RESULT_OK);                      getActivity().finish(); +//                    } else { +//                        // display result on error without finishing activity +//                        editKeyResult.createNotify(getActivity()); +//                    }                  }              }          }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index dc0510189..eb807792b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -31,11 +31,14 @@ import android.widget.Button;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;  import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;  import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;  import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.provider.ProviderHelper;  import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify;  import java.util.Vector; @@ -195,22 +198,23 @@ public class EncryptAsymmetricFragment extends Fragment {              mMainUserIdRest.setText("");          } else {              // See if we can get a user_id from a unified query -            String[] userId;              try { -                userId = mProviderHelper.getCachedPublicKeyRing( +                String[] userIdSplit = mProviderHelper.getCachedPublicKeyRing(                          KeyRings.buildUnifiedKeyRingUri(mSecretKeyId)).getSplitPrimaryUserIdWithFallback(); + +                if (userIdSplit[0] != null) { +                    mMainUserId.setText(userIdSplit[0]); +                } else { +                    mMainUserId.setText(R.string.user_id_no_name); +                } +                if (userIdSplit[1] != null) { +                    mMainUserIdRest.setText(userIdSplit[1]); +                } else { +                    mMainUserIdRest.setText(getString(R.string.label_key_id) + ": " +                            + PgpKeyHelper.convertKeyIdToHex(mSecretKeyId)); +                }              } catch (PgpGeneralException e) { -                userId = null; -            } -            if (userId != null && userId[0] != null) { -                mMainUserId.setText(String.format("%#16x", Long.parseLong(userId[0]))); -            } else { -                mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); -            } -            if (userId != null && userId[1] != null) { -                mMainUserIdRest.setText(userId[1]); -            } else { -                mMainUserIdRest.setText(""); +                Notify.showNotify(getActivity(), "Key not found! This is a bug!", Notify.Style.ERROR);              }              mSign.setChecked(true);          } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 524fe2ef2..dbc557f9a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -100,6 +100,7 @@ public class ImportKeysActivity extends ActionBarActivity {      public static final int VIEW_PAGER_HEIGHT = 64; // dp +    private static final int ALL_TABS = -1;      private static final int TAB_KEYSERVER = 0;      private static final int TAB_QR_CODE = 1;      private static final int TAB_FILE = 2; @@ -152,7 +153,7 @@ public class ImportKeysActivity extends ActionBarActivity {          }          Bundle serverBundle = null; -        boolean serverOnly = false; +        int showTabOnly = ALL_TABS;          if (ACTION_IMPORT_KEY.equals(action)) {              /* Keychain's own Actions */ @@ -216,7 +217,7 @@ public class ImportKeysActivity extends ActionBarActivity {                      serverBundle.putString(ImportKeysServerFragment.ARG_QUERY, query);                      serverBundle.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true);                      // display server tab only -                    serverOnly = true; +                    showTabOnly = TAB_KEYSERVER;                      mSwitchToTab = TAB_KEYSERVER;                      // action: search immediately @@ -229,13 +230,20 @@ public class ImportKeysActivity extends ActionBarActivity {                  );                  return;              } -        } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action) -                    || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { +        } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) {              // NOTE: this only displays the appropriate fragment, no actions are taken              mSwitchToTab = TAB_FILE;              // no immediate actions!              startListFragment(savedInstanceState, null, null, null); +        } else if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { +            // NOTE: this only displays the appropriate fragment, no actions are taken +            mSwitchToTab = TAB_FILE; +            // display file tab only +            showTabOnly = TAB_FILE; + +            // no immediate actions! +            startListFragment(savedInstanceState, null, null, null);          } else if (ACTION_IMPORT_KEY_FROM_QR_CODE.equals(action)) {              // also exposed in AndroidManifest @@ -261,10 +269,10 @@ public class ImportKeysActivity extends ActionBarActivity {              startListFragment(savedInstanceState, null, null, null);          } -        initTabs(serverBundle, serverOnly); +        initTabs(serverBundle, showTabOnly);      } -    private void initTabs(Bundle serverBundle, boolean serverOnly) { +    private void initTabs(Bundle serverBundle, int showTabOnly) {          mTabsAdapter = new PagerTabStripAdapter(this);          mViewPager.setAdapter(mTabsAdapter);          mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @@ -287,15 +295,34 @@ public class ImportKeysActivity extends ActionBarActivity {              }          }); -        mTabsAdapter.addTab(ImportKeysServerFragment.class, -                serverBundle, getString(R.string.import_tab_keyserver)); -        if (!serverOnly) { -            mTabsAdapter.addTab(ImportKeysQrCodeFragment.class, -                    null, getString(R.string.import_tab_qr_code)); -            mTabsAdapter.addTab(ImportKeysFileFragment.class, -                    null, getString(R.string.import_tab_direct)); -            mTabsAdapter.addTab(ImportKeysKeybaseFragment.class, -                    null, getString(R.string.import_tab_keybase)); +        switch (showTabOnly) { +            case ALL_TABS: +                // show all tabs +                mTabsAdapter.addTab(ImportKeysServerFragment.class, +                        serverBundle, getString(R.string.import_tab_keyserver)); +                mTabsAdapter.addTab(ImportKeysQrCodeFragment.class, +                        null, getString(R.string.import_tab_qr_code)); +                mTabsAdapter.addTab(ImportKeysFileFragment.class, +                        null, getString(R.string.import_tab_direct)); +                mTabsAdapter.addTab(ImportKeysKeybaseFragment.class, +                        null, getString(R.string.import_tab_keybase)); +                break; +            case TAB_KEYSERVER: +                mTabsAdapter.addTab(ImportKeysServerFragment.class, +                        serverBundle, getString(R.string.import_tab_keyserver)); +                break; +            case TAB_QR_CODE: +                mTabsAdapter.addTab(ImportKeysQrCodeFragment.class, +                        null, getString(R.string.import_tab_qr_code)); +                break; +            case TAB_FILE: +                mTabsAdapter.addTab(ImportKeysFileFragment.class, +                        null, getString(R.string.import_tab_direct)); +                break; +            case TAB_KEYBASE: +                mTabsAdapter.addTab(ImportKeysKeybaseFragment.class, +                        null, getString(R.string.import_tab_keybase)); +                break;          }          // update layout after operations diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index c74f4c96c..50ff5c753 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -74,7 +74,7 @@ public class KeyListActivity extends DrawerActivity {      @Override      public boolean onOptionsItemSelected(MenuItem item) {          switch (item.getItemId()) { -            case R.id.menu_key_list_import: +            case R.id.menu_key_list_add:                  importKeys();                  return true; @@ -82,6 +82,12 @@ public class KeyListActivity extends DrawerActivity {                  createKey();                  return true; +            case R.id.menu_key_list_import_existing_key: +                Intent intentImportExisting = new Intent(this, ImportKeysActivity.class); +                intentImportExisting.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); +                startActivityForResult(intentImportExisting, 0); +                return true; +              case R.id.menu_key_list_export:                  mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);                  return true; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index b0caaa10c..aa17aea3d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -475,41 +475,40 @@ public class KeyListFragment extends LoaderFragment                  }              } -            { // set edit button and revoked info, specific by key type - -                if (cursor.getInt(KeyListFragment.INDEX_HAS_ANY_SECRET) != 0) { -                    // this is a secret key -                    h.mStatus.setVisibility(View.GONE); -                } else { -                    // this is a public key - show if it's revoked, expired, or verified - -                    boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; -                    boolean isExpired = !cursor.isNull(INDEX_EXPIRY) -                            && new Date(cursor.getLong(INDEX_EXPIRY)*1000).before(new Date()); -                    boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; - -                    // Note: order is important! -                    if (isRevoked) { -                        h.mStatus.setImageDrawable( -                                getResources().getDrawable(R.drawable.status_signature_revoked_cutout)); -                        h.mStatus.setColorFilter(getResources().getColor(R.color.android_red_light), -                                PorterDuff.Mode.SRC_ATOP); -                        h.mStatus.setVisibility(View.VISIBLE); -                    } else if (isExpired) { -                        h.mStatus.setImageDrawable( -                                getResources().getDrawable(R.drawable.status_signature_expired_cutout)); -                        h.mStatus.setColorFilter(getResources().getColor(R.color.android_orange_light), -                                PorterDuff.Mode.SRC_ATOP); -                        h.mStatus.setVisibility(View.VISIBLE); -                    } else if (isVerified) { +            { // set edit button and status, specific by key type + +                boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; +                boolean isExpired = !cursor.isNull(INDEX_EXPIRY) +                        && new Date(cursor.getLong(INDEX_EXPIRY)*1000).before(new Date()); +                boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; + +                // Note: order is important! +                if (isRevoked) { +                    h.mStatus.setImageDrawable( +                            getResources().getDrawable(R.drawable.status_signature_revoked_cutout)); +                    h.mStatus.setColorFilter(getResources().getColor(R.color.android_red_dark), +                            PorterDuff.Mode.SRC_ATOP); +                    h.mStatus.setVisibility(View.VISIBLE); +                } else if (isExpired) { +                    h.mStatus.setImageDrawable( +                            getResources().getDrawable(R.drawable.status_signature_expired_cutout)); +                    h.mStatus.setColorFilter(getResources().getColor(R.color.android_orange_dark), +                            PorterDuff.Mode.SRC_ATOP); +                    h.mStatus.setVisibility(View.VISIBLE); +                } else if (isVerified) { +                    if (cursor.getInt(KeyListFragment.INDEX_HAS_ANY_SECRET) != 0) { +                        // this is a secret key +                        h.mStatus.setVisibility(View.GONE); +                    } else { +                        // this is a public key - show if it's verified                          h.mStatus.setImageDrawable(                                  getResources().getDrawable(R.drawable.status_signature_verified_cutout)); -                        h.mStatus.setColorFilter(getResources().getColor(R.color.android_green_light), +                        h.mStatus.setColorFilter(getResources().getColor(R.color.android_green_dark),                                  PorterDuff.Mode.SRC_ATOP);                          h.mStatus.setVisibility(View.VISIBLE); -                    } else { -                        h.mStatus.setVisibility(View.GONE);                      } +                } else { +                    h.mStatus.setVisibility(View.GONE);                  }              } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java index dbd1b7507..57bfc7bd5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java @@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.helper.Preferences;  import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.service.KeychainIntentService;  import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;  import org.sufficientlysecure.keychain.util.Log; @@ -92,7 +93,7 @@ public class UploadKeyActivity extends ActionBarActivity {          intent.setAction(KeychainIntentService.ACTION_UPLOAD_KEYRING);          // set data uri as path to keyring -        Uri blobUri = KeychainContract.KeyRingData.buildPublicKeyRingUri(mDataUri); +        Uri blobUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);          intent.setData(blobUri);          // fill values for this action @@ -105,7 +106,7 @@ public class UploadKeyActivity extends ActionBarActivity {          // Message is received after uploading is done in KeychainIntentService          KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, -                getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) { +                getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) {              public void handleMessage(Message message) {                  // handle messages by standard KeychainIntentServiceHandler first                  super.handleMessage(message); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 03e446723..44a51a75f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -89,8 +89,6 @@ public class ViewKeyActivity extends ActionBarActivity implements      private ImageView mStatusImage;      private View mStatusDivider; -    public static final int REQUEST_CODE_LOOKUP_KEY = 0x00007006; -      // NFC      private NfcAdapter mNfcAdapter;      private NfcAdapter.CreateNdefMessageCallback mNdefCallback; @@ -145,20 +143,27 @@ public class ViewKeyActivity extends ActionBarActivity implements              switchToTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB);          } -        Uri dataUri = getDataUri(); -        if (dataUri == null) { -            Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); +        mDataUri = getIntent().getData(); +        if (mDataUri == null) { +            Log.e(Constants.TAG, "Data missing. Should be uri of key!");              finish();              return;          } +        if (mDataUri.getHost().equals(ContactsContract.AUTHORITY)) { +            mDataUri = ContactHelper.dataUriFromContactUri(this, mDataUri); +        } + +        Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); -        loadData(dataUri); +        // Prepare the loaders. Either re-connect with an existing ones, +        // or start new ones. +        getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); -        initNfc(dataUri); +        initNfc(mDataUri);          mShowAdvancedTabs = false; -        initTabs(dataUri); +        initTabs(mDataUri);          // switch to tab selected by extra          mViewPager.setCurrentItem(switchToTab); @@ -235,24 +240,6 @@ public class ViewKeyActivity extends ActionBarActivity implements          mSlidingTabLayout.setViewPager(mViewPager);      } -    private Uri getDataUri() { -        Uri dataUri = getIntent().getData(); -        if (dataUri != null && dataUri.getHost().equals(ContactsContract.AUTHORITY)) { -            dataUri = ContactHelper.dataUriFromContactUri(this, dataUri); -        } -        return dataUri; -    } - -    private void loadData(Uri dataUri) { -        mDataUri = dataUri; - -        Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); - -        // Prepare the loaders. Either re-connect with an existing ones, -        // or start new ones. -        getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); -    } -      @Override      public boolean onCreateOptionsMenu(Menu menu) {          super.onCreateOptionsMenu(menu); @@ -273,14 +260,6 @@ public class ViewKeyActivity extends ActionBarActivity implements                      startActivity(homeIntent);                      return true;                  } -                case R.id.menu_key_view_update: { -                    updateFromKeyserver(mDataUri, mProviderHelper); -                    return true; -                } -                case R.id.menu_key_view_export_keyserver: { -                    uploadToKeyserver(mDataUri); -                    return true; -                }                  case R.id.menu_key_view_export_file: {                      exportToFile(mDataUri, mExportHelper, mProviderHelper);                      return true; @@ -322,26 +301,6 @@ public class ViewKeyActivity extends ActionBarActivity implements          );      } -    private void uploadToKeyserver(Uri dataUri) throws ProviderHelper.NotFoundException { -        Intent uploadIntent = new Intent(this, UploadKeyActivity.class); -        uploadIntent.setData(dataUri); -        startActivityForResult(uploadIntent, 0); -    } - -    private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper) -            throws ProviderHelper.NotFoundException { -        byte[] blob = (byte[]) providerHelper.getGenericData( -                KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), -                KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); -        String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); - -        Intent queryIntent = new Intent(this, ImportKeysActivity.class); -        queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); -        queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); - -        startActivityForResult(queryIntent, REQUEST_CODE_LOOKUP_KEY); -    } -      private void deleteKey(Uri dataUri, ExportHelper exportHelper) {          // Message is received after key is deleted          Handler returnHandler = new Handler() { @@ -516,19 +475,19 @@ public class ViewKeyActivity extends ActionBarActivity implements                      // Note: order is important                      if (isRevoked) {                          mStatusText.setText(R.string.view_key_revoked); -                        mStatusText.setTextColor(getResources().getColor(R.color.android_red_light)); +                        mStatusText.setTextColor(getResources().getColor(R.color.android_red_dark));                          mStatusImage.setImageDrawable(                                  getResources().getDrawable(R.drawable.status_signature_revoked_cutout)); -                        mStatusImage.setColorFilter(getResources().getColor(R.color.android_red_light), +                        mStatusImage.setColorFilter(getResources().getColor(R.color.android_red_dark),                                  PorterDuff.Mode.SRC_ATOP);                          mStatusDivider.setVisibility(View.VISIBLE);                          mStatusLayout.setVisibility(View.VISIBLE);                      } else if (isExpired) {                          mStatusText.setText(R.string.view_key_expired); -                        mStatusText.setTextColor(getResources().getColor(R.color.android_orange_light)); +                        mStatusText.setTextColor(getResources().getColor(R.color.android_orange_dark));                          mStatusImage.setImageDrawable(                                  getResources().getDrawable(R.drawable.status_signature_expired_cutout)); -                        mStatusImage.setColorFilter(getResources().getColor(R.color.android_orange_light), +                        mStatusImage.setColorFilter(getResources().getColor(R.color.android_orange_dark),                                  PorterDuff.Mode.SRC_ATOP);                          mStatusDivider.setVisibility(View.VISIBLE);                          mStatusLayout.setVisibility(View.VISIBLE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index a156ff5f1..370a7312f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -33,11 +33,13 @@ import android.widget.ListView;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;  import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;  import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;  import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;  import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;  import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.util.Notify; @@ -55,7 +57,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements      private View mActionCertify;      private View mActionCertifyText;      private ImageView mActionCertifyImage; -    private View mActionCertifyDivider; +    private View mActionUpdate;      private ListView mUserIds; @@ -84,7 +86,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements          // make certify image gray, like action icons          mActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light),                  PorterDuff.Mode.SRC_IN); -        mActionCertifyDivider = view.findViewById(R.id.view_key_action_certify_divider); +        mActionUpdate = view.findViewById(R.id.view_key_action_update);          return root;      } @@ -124,6 +126,15 @@ public class ViewKeyMainFragment extends LoaderFragment implements                  editKey(mDataUri);              }          }); +        mActionUpdate.setOnClickListener(new View.OnClickListener() { +            public void onClick(View view) { +                try { +                    updateFromKeyserver(mDataUri, new ProviderHelper(getActivity())); +                } catch (NotFoundException e) { +                    Notify.showNotify(getActivity(), R.string.error_key_not_found, Notify.Style.ERROR); +                } +            } +        });          mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);          mUserIds.setAdapter(mUserIdsAdapter); @@ -254,6 +265,20 @@ public class ViewKeyMainFragment extends LoaderFragment implements          }      } +    private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper) +            throws ProviderHelper.NotFoundException { +        byte[] blob = (byte[]) providerHelper.getGenericData( +                KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), +                KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); +        String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); + +        Intent queryIntent = new Intent(getActivity(), ImportKeysActivity.class); +        queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); +        queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); + +        startActivityForResult(queryIntent, 0); +    } +      private void certify(Uri dataUri) {          Intent signIntent = new Intent(getActivity(), CertifyKeyActivity.class);          signIntent.setData(dataUri); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java index e81d5dbf7..54ab76464 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -49,6 +49,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;  import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;  import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;  import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.util.Notify; @@ -70,6 +71,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements      private View mKeyClipboardButton;      private View mNfcHelpButton;      private View mNfcPrefsButton; +    private View mKeyUploadButton;      ProviderHelper mProviderHelper; @@ -94,6 +96,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements          mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);          mNfcHelpButton = view.findViewById(R.id.view_key_action_nfc_help);          mNfcPrefsButton = view.findViewById(R.id.view_key_action_nfc_prefs); +        mKeyUploadButton = view.findViewById(R.id.view_key_action_upload);          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {              mNfcPrefsButton.setVisibility(View.VISIBLE); @@ -144,6 +147,12 @@ public class ViewKeyShareFragment extends LoaderFragment implements                  showNfcPrefs();              }          }); +        mKeyUploadButton.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                uploadToKeyserver(); +            } +        });          return root;      } @@ -345,4 +354,11 @@ public class ViewKeyShareFragment extends LoaderFragment implements          loadTask.execute();      } + +    private void uploadToKeyserver() { +        Intent uploadIntent = new Intent(getActivity(), UploadKeyActivity.class); +        uploadIntent.setData(mDataUri); +        startActivityForResult(uploadIntent, 0); +    } +  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index c8b74da2e..6d46f3c8f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -188,7 +188,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC                  case Certs.VERIFIED_SECRET:                      vVerified.setImageResource(R.drawable.status_signature_verified_cutout);                      vVerified.setColorFilter( -                            mContext.getResources().getColor(R.color.android_green_light), +                            mContext.getResources().getColor(R.color.android_green_dark),                              PorterDuff.Mode.SRC_IN);                      break;                  case Certs.VERIFIED_SELF: @@ -200,7 +200,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC                  default:                      vVerified.setImageResource(R.drawable.status_signature_invalid_cutout);                      vVerified.setColorFilter( -                            mContext.getResources().getColor(R.color.android_red_light), +                            mContext.getResources().getColor(R.color.android_red_dark),                              PorterDuff.Mode.SRC_IN);                      break;              } diff --git a/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml index 64b3621a4..6814cd259 100644 --- a/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml @@ -37,7 +37,6 @@                  android:layout_height="wrap_content"                  android:layout_marginBottom="8dp"                  android:layout_marginLeft="8dp" -                android:text="Max Mustermann"                  android:textAppearance="?android:attr/textAppearanceMedium" />              <TextView @@ -52,7 +51,6 @@                  android:id="@+id/email"                  android:layout_width="match_parent"                  android:layout_height="wrap_content" -                android:text="max@musterman.com"                  android:textAppearance="?android:attr/textAppearanceMedium"                  android:layout_marginBottom="8dp"                  android:layout_marginLeft="8dp" /> @@ -131,7 +129,7 @@              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_weight="1" -            android:text="@string/title_create_key" +            android:text="@string/btn_create_key"              android:minHeight="?android:attr/listPreferredItemHeight"              android:drawableRight="@drawable/ic_action_new_account"              android:drawablePadding="8dp" diff --git a/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml index 30ccc05ab..588cbb050 100644 --- a/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml @@ -17,20 +17,28 @@              android:orientation="vertical">              <TextView -                android:layout_width="match_parent" +                android:layout_width="wrap_content" +                android:layout_height="wrap_content" +                android:layout_marginTop="16dp" +                android:layout_marginLeft="8dp" +                android:textAppearance="?android:attr/textAppearanceMedium" +                android:text="@string/create_key_text" /> + +            <TextView +                style="@style/SectionHeader" +                android:layout_width="wrap_content"                  android:layout_height="wrap_content" -                android:paddingTop="16dp" -                android:paddingBottom="8dp" -                android:text="@string/create_key_text" -                android:textAppearance="?android:attr/textAppearanceMedium" /> +                android:layout_marginTop="8dp" +                android:text="@string/label_user_id" />              <AutoCompleteTextView                  android:layout_width="match_parent"                  android:layout_height="wrap_content" +                android:layout_marginTop="8dp"                  android:layout_marginBottom="8dp"                  android:imeOptions="actionNext"                  android:inputType="textPersonName" -                android:hint="@string/label_name" +                android:hint="@string/create_key_hint_full_name"                  android:ems="10"                  android:id="@+id/name" /> @@ -44,10 +52,17 @@                  android:ems="10"                  android:inputType="textEmailAddress" /> +            <TextView +                style="@style/SectionHeader" +                android:layout_width="wrap_content" +                android:layout_height="wrap_content" +                android:text="@string/label_passphrase" /> +              <EditText                  android:id="@+id/passphrase"                  android:layout_width="match_parent"                  android:layout_height="wrap_content" +                android:layout_marginTop="8dp"                  android:layout_marginBottom="8dp"                  android:inputType="textPassword"                  android:hint="@string/label_passphrase" @@ -117,7 +132,7 @@              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_weight="1" -            android:text="@string/title_create_key" +            android:text="@string/btn_next"              android:minHeight="?android:attr/listPreferredItemHeight"              android:drawableRight="@drawable/ic_action_new_account"              android:drawablePadding="8dp" diff --git a/OpenKeychain/src/main/res/layout/first_time_activity.xml b/OpenKeychain/src/main/res/layout/first_time_activity.xml index fad1a3b26..2d750c1a7 100644 --- a/OpenKeychain/src/main/res/layout/first_time_activity.xml +++ b/OpenKeychain/src/main/res/layout/first_time_activity.xml @@ -33,9 +33,10 @@                  android:layout_weight="1"                  android:text="@string/first_time_import_key"                  android:minHeight="?android:attr/listPreferredItemHeight" -                android:drawableRight="@drawable/ic_action_download" +                android:drawableRight="@drawable/ic_action_collection"                  android:drawablePadding="8dp"                  android:gravity="center_vertical" +                android:layout_gravity="center_vertical"                  android:clickable="true"                  style="@style/SelectableItem" /> @@ -59,6 +60,7 @@                  android:drawableRight="@drawable/ic_action_new_account"                  android:drawablePadding="8dp"                  android:gravity="center_vertical" +                android:layout_gravity="center_vertical"                  android:clickable="true"                  style="@style/SelectableItem" /> diff --git a/OpenKeychain/src/main/res/layout/key_list_fragment.xml b/OpenKeychain/src/main/res/layout/key_list_fragment.xml index 32b77baac..f1da19b72 100644 --- a/OpenKeychain/src/main/res/layout/key_list_fragment.xml +++ b/OpenKeychain/src/main/res/layout/key_list_fragment.xml @@ -56,6 +56,7 @@              android:textSize="14sp"              android:text="@string/key_list_empty_button_create"              android:drawableLeft="@drawable/ic_action_new_account" +            android:drawablePadding="8dp"              android:background="@drawable/button_edgy"/>          <TextView @@ -73,7 +74,8 @@              android:layout_margin="4dp"              android:textSize="14sp"              android:text="@string/key_list_empty_button_import" -            android:drawableLeft="@drawable/ic_action_download" +            android:drawableLeft="@drawable/ic_action_collection" +            android:drawablePadding="8dp"              android:background="@drawable/button_edgy" />      </LinearLayout> diff --git a/OpenKeychain/src/main/res/layout/key_list_header.xml b/OpenKeychain/src/main/res/layout/key_list_header.xml index 8cb0d4262..4809fc5ab 100644 --- a/OpenKeychain/src/main/res/layout/key_list_header.xml +++ b/OpenKeychain/src/main/res/layout/key_list_header.xml @@ -21,7 +21,7 @@          android:layout_alignParentRight="true"          android:layout_alignParentEnd="true"          android:layout_marginRight="8dp" -        android:visibility="visible" +        android:visibility="gone"          android:textColor="@android:color/darker_gray" />  </RelativeLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/view_key_main_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_main_fragment.xml index b11538ba9..7a54fab05 100644 --- a/OpenKeychain/src/main/res/layout/view_key_main_fragment.xml +++ b/OpenKeychain/src/main/res/layout/view_key_main_fragment.xml @@ -17,7 +17,6 @@              style="@style/SectionHeader"              android:layout_width="wrap_content"              android:layout_height="0dp" -            android:layout_marginBottom="4dp"              android:layout_marginTop="8dp"              android:text="@string/section_user_ids"              android:layout_weight="1" /> @@ -98,7 +97,6 @@              android:id="@+id/view_key_action_encrypt"              android:paddingLeft="8dp"              android:paddingRight="8dp" -            android:layout_marginBottom="8dp"              android:textAppearance="?android:attr/textAppearanceMedium"              android:layout_width="match_parent"              android:layout_height="wrap_content" @@ -111,6 +109,28 @@              android:drawablePadding="8dp"              android:gravity="center_vertical" /> +        <View +            android:layout_width="match_parent" +            android:layout_height="1dip" +            android:background="?android:attr/listDivider" /> + +        <TextView +            android:id="@+id/view_key_action_update" +            android:paddingLeft="8dp" +            android:paddingRight="8dp" +            android:layout_marginBottom="8dp" +            android:textAppearance="?android:attr/textAppearanceMedium" +            android:layout_width="match_parent" +            android:layout_height="wrap_content" +            android:minHeight="?android:attr/listPreferredItemHeight" +            android:clickable="true" +            style="@style/SelectableItem" +            android:text="@string/key_view_action_update" +            android:layout_weight="1" +            android:drawableRight="@drawable/ic_action_download" +            android:drawablePadding="8dp" +            android:gravity="center_vertical" /> +      </LinearLayout>  </ScrollView> diff --git a/OpenKeychain/src/main/res/layout/view_key_share_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_share_fragment.xml index 1cd2b9f1b..a8786c461 100644 --- a/OpenKeychain/src/main/res/layout/view_key_share_fragment.xml +++ b/OpenKeychain/src/main/res/layout/view_key_share_fragment.xml @@ -129,6 +129,29 @@              android:layout_height="1dip"              android:background="?android:attr/listDivider" /> +        <TextView +            android:id="@+id/view_key_action_upload" +            android:paddingLeft="8dp" +            android:paddingRight="8dp" +            android:layout_marginBottom="8dp" +            android:textAppearance="?android:attr/textAppearanceMedium" +            android:layout_width="match_parent" +            android:layout_height="wrap_content" +            android:minHeight="?android:attr/listPreferredItemHeight" +            android:clickable="true" +            style="@style/SelectableItem" +            android:text="@string/key_view_action_upload" +            android:layout_weight="1" +            android:drawableRight="@drawable/ic_action_upload" +            android:drawablePadding="8dp" +            android:gravity="center_vertical" +            android:editable="false" /> + +        <View +            android:layout_width="match_parent" +            android:layout_height="1dip" +            android:background="?android:attr/listDivider" /> +          <LinearLayout              android:id="@+id/view_key_action_nfc_help"              android:layout_width="match_parent" diff --git a/OpenKeychain/src/main/res/menu/key_list.xml b/OpenKeychain/src/main/res/menu/key_list.xml index e865df182..056dd5986 100644 --- a/OpenKeychain/src/main/res/menu/key_list.xml +++ b/OpenKeychain/src/main/res/menu/key_list.xml @@ -10,7 +10,7 @@          app:showAsAction="collapseActionView|ifRoom" />      <item -        android:id="@+id/menu_key_list_import" +        android:id="@+id/menu_key_list_add"          app:showAsAction="ifRoom|withText"          android:icon="@drawable/ic_action_add_person"          android:title="@string/menu_add_keys" /> @@ -27,6 +27,11 @@          android:title="@string/menu_create_key" />      <item +        android:id="@+id/menu_key_list_import_existing_key" +        app:showAsAction="never" +        android:title="@string/menu_import_existing_key" /> + +    <item          android:id="@+id/menu_key_list_debug_read"          app:showAsAction="never"          android:title="Debug / DB restore" diff --git a/OpenKeychain/src/main/res/menu/key_view.xml b/OpenKeychain/src/main/res/menu/key_view.xml index 64877d725..5a156b5ac 100644 --- a/OpenKeychain/src/main/res/menu/key_view.xml +++ b/OpenKeychain/src/main/res/menu/key_view.xml @@ -3,23 +3,6 @@      xmlns:app="http://schemas.android.com/apk/res-auto">      <item -        android:id="@+id/menu_key_keyserver" -        android:icon="@drawable/ic_action_cloud" -        app:showAsAction="always" -        android:title="@string/menu_key_server"> -        <menu> -            <item -                android:id="@+id/menu_key_view_update" -                app:showAsAction="never" -                android:title="@string/menu_update_key" /> -            <item -                android:id="@+id/menu_key_view_export_keyserver" -                app:showAsAction="never" -                android:title="@string/menu_export_key_to_server" /> -        </menu> -    </item> - -    <item          android:id="@+id/menu_key_view_export_file"          android:icon="@drawable/ic_action_import_export"          app:showAsAction="never" diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index bcd4d3bbc..d06712699 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -2,12 +2,12 @@  <resources>      <!-- title --> -    <string name="title_select_recipients">Select Public Key</string> -    <string name="title_select_secret_key">Select Secret Key</string> +    <string name="title_select_recipients">Select Keys</string> +    <string name="title_select_secret_key">Select Your Key</string>      <string name="title_encrypt">Encrypt</string>      <string name="title_decrypt">Decrypt</string>      <string name="title_authentication">Passphrase</string> -    <string name="title_create_key">Create Key</string> +    <string name="title_create_key">Create My Key</string>      <string name="title_edit_key">Edit Key</string>      <string name="title_preferences">Preferences</string>      <string name="title_api_registered_apps">Apps</string> @@ -71,18 +71,17 @@      <string name="btn_encryption_advanced_settings_hide">Hide advanced settings</string>      <string name="btn_share_encrypted_signed">Share encrypted/signed message…</string>      <string name="btn_view_cert_key">View certification key</string> +    <string name="btn_create_key">Create key</string>      <!-- menu -->      <string name="menu_preferences">Settings</string>      <string name="menu_help">Help</string>      <string name="menu_export_key">Export to file</string>      <string name="menu_delete_key">Delete key</string> -    <string name="menu_create_key">Create key</string> -    <string name="menu_create_key_expert">Create key (expert)</string> +    <string name="menu_create_key">Create my key</string> +    <string name="menu_import_existing_key">Import existing key</string>      <string name="menu_search">Search</string>      <string name="menu_key_server">Keyserver…</string> -    <string name="menu_update_key">Update from keyserver</string> -    <string name="menu_export_key_to_server">Upload to key server</string>      <string name="menu_share">Share…</string>      <string name="menu_share_title_fingerprint">Share fingerprint…</string>      <string name="menu_share_title">Share whole key…</string> @@ -217,7 +216,7 @@      <string name="ask_save_changed_key">You have made changes to the keyring, would you like to save it?</string>      <string name="ask_empty_id_ok">You have added an empty identity, are you sure you want to continue?</string>      <string name="public_key_deletetion_confirmation">Do you really want to delete the public key \'%s\'?\nYou can\'t undo this!</string> -    <string name="also_export_secret_keys">Also export secret keys?</string> +    <string name="also_export_secret_keys">Also export secret keys</string>      <string name="key_exported">Successfully exported 1 key.</string>      <string name="keys_exported">Successfully exported %d keys.</string> @@ -299,6 +298,7 @@      <string name="progress_saving">saving…</string>      <string name="progress_importing">importing…</string>      <string name="progress_exporting">exporting…</string> +    <string name="progress_uploading">uploading…</string>      <string name="progress_building_key">building key…</string>      <string name="progress_certifying_master_key">certifying master key…</string>      <string name="progress_building_master_key">building master ring…</string> @@ -339,6 +339,7 @@      <string name="progress_processing_signature">processing signature…</string>      <string name="progress_verifying_signature">verifying signature…</string>      <string name="progress_signing">signing…</string> +    <string name="progress_certifying">certifying…</string>      <string name="progress_reading_data">reading data…</string>      <string name="progress_finding_key">finding key…</string>      <string name="progress_decompressing_data">decompressing data…</string> @@ -347,7 +348,6 @@      <!-- action strings -->      <string name="hint_public_keys">Name/Email/Key ID…</string> -    <string name="hint_secret_keys">Search Secret Keys</string>      <string name="action_share_key_with">Share Key with…</string>      <string name="hint_keybase_search">Name/Keybase.io username…</string> @@ -448,7 +448,7 @@      <string name="api_settings_package_signature">SHA-256 of Package Signature</string>      <string name="api_settings_accounts">Accounts</string>      <string name="api_settings_accounts_empty">No accounts attached to this app.</string> -    <string name="api_create_account_text">The app requests the creation of a new account. Please select an existing private key or create a new one.\nApps are restricted to the usage of keys you select here!</string> +    <string name="api_create_account_text">The app requests the creation of a new account. Please select one of your existing keys or create a new one.\nApps are restricted to the usage of keys you select here!</string>      <string name="api_register_text">The displayed app wants to encrypt/decrypt messages and sign them in your name.\nAllow access?\n\nWARNING: If you do not know why this screen appeared, disallow access! You can revoke access later using the \'Apps\' screen.</string>      <string name="api_register_allow">Allow access</string>      <string name="api_register_disallow">Disallow access</string> @@ -475,14 +475,16 @@      <string name="key_list_empty_text2">You can start by</string>      <string name="key_list_empty_text3">or</string>      <string name="key_list_empty_button_create">creating your own key</string> -    <string name="key_list_empty_button_import">importing keys.</string> +    <string name="key_list_empty_button_import">importing an existing key.</string>      <!-- Key view -->      <string name="key_view_action_edit">Edit key</string>      <string name="key_view_action_encrypt">Encrypt with this key</string>      <string name="key_view_action_certify">Certify identities</string> +    <string name="key_view_action_update">Update from keyserver</string>      <string name="key_view_action_share_with">Share with…</string>      <string name="key_view_action_share_nfc">Share over NFC by holding the devices back to back</string> +    <string name="key_view_action_upload">Upload to key server</string>      <string name="key_view_tab_main">Main Info</string>      <string name="key_view_tab_share">Share</string>      <string name="key_view_tab_keys">Subkeys</string> @@ -504,12 +506,13 @@      </string-array>      <!-- Create key --> -    <string name="create_key_text">Enter Full Name, Email and a Passphrase.</string>      <string name="create_key_upload">Upload key to keyserver</string>      <string name="create_key_empty">This field is required</string>      <string name="create_key_passphrases_not_equal">Passphrases do not match</string>      <string name="create_key_final_text">You entered the following credentials:</string>      <string name="create_key_final_robot_text">Creating a key may take a while, have a cup of coffee in the meantime…\n(3 subkeys, RSA, 4096 bit)</string> +    <string name="create_key_text">Enter your full name, email address, and choose a passhrase.</string> +    <string name="create_key_hint_full_name">Full Name, e.g. Max Mustermann</string>      <!-- View key -->      <string name="view_key_revoked">This key has been revoked!</string> @@ -525,9 +528,6 @@      <string name="drawer_close">Close navigation drawer</string>      <string name="edit">Edit</string>      <string name="my_keys">My Keys</string> -    <string name="label_secret_key">Secret Key</string> -    <string name="secret_key_yes">available</string> -    <string name="secret_key_no">unavailable</string>      <!-- hints -->      <string name="encrypt_content_edit_text_hint">Write message here to encrypt and/or sign…</string> @@ -729,7 +729,7 @@      <string name="error_key_processing">Error processing key!</string>      <string name="no_subkey">subkey unavailable</string>      <string name="key_stripped">stripped</string> -    <string name="secret_cannot_multiple">Secret keys can only be deleted individually!</string> +    <string name="secret_cannot_multiple">Your own keys can only be deleted individually!</string>      <string name="title_view_cert">View Certificate Details</string>      <string name="unknown_algorithm">unknown</string>      <string name="can_sign_not">cannot sign</string> @@ -740,8 +740,8 @@      <!-- First Time -->      <string name="first_time_text1">Take back your privacy with OpenKeychain!</string> -    <string name="first_time_create_key">Create Key</string> -    <string name="first_time_import_key">Import Key</string> +    <string name="first_time_create_key">Create my key</string> +    <string name="first_time_import_key">Import existing key</string>      <string name="first_time_skip">Skip Setup</string>  </resources>  | 
