diff options
Diffstat (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter')
3 files changed, 399 insertions, 0 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java new file mode 100644 index 000000000..26416057c --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +import java.util.List; + +import org.sufficientlysecure.keychain.R; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; + +public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> { + protected LayoutInflater mInflater; + protected Activity mActivity; + + protected List<ImportKeysListEntry> data; + + public ImportKeysAdapter(Activity activity) { + super(activity, -1); + mActivity = activity; + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @SuppressLint("NewApi") + public void setData(List<ImportKeysListEntry> data) { + clear(); + if (data != null) { + if (Build.VERSION.SDK_INT >= 11) { + addAll(data); + } else { + for (ImportKeysListEntry entry : data) { + add(entry); + } + } + this.data = data; + } + } + + public List<ImportKeysListEntry> getData() { + return data; + } + + @Override + public boolean hasStableIds() { + return true; + } + + public View getView(int position, View convertView, ViewGroup parent) { + ImportKeysListEntry entry = data.get(position); + + View view = mInflater.inflate(R.layout.import_keys_list_entry, null); + + TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); + mainUserId.setText(R.string.unknownUserId); + TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); + mainUserIdRest.setText(""); + TextView keyId = (TextView) view.findViewById(R.id.keyId); + keyId.setText(R.string.noKey); + TextView fingerprint = (TextView) view.findViewById(R.id.fingerprint); + TextView algorithm = (TextView) view.findViewById(R.id.algorithm); + algorithm.setText(""); + TextView status = (TextView) view.findViewById(R.id.status); + status.setText(""); + + String userId = entry.userIds.get(0); + if (userId != null) { + String chunks[] = userId.split(" <", 2); + userId = chunks[0]; + if (chunks.length > 1) { + mainUserIdRest.setText("<" + chunks[1]); + } + if (entry.secretKey) { + userId = mActivity.getString(R.string.secretKey) + " " + userId; + mainUserId.setTextColor(Color.RED); + } + mainUserId.setText(userId); + } + + keyId.setText(entry.hexKeyId); + fingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint); + + if (mainUserIdRest.getText().length() == 0) { + mainUserIdRest.setVisibility(View.GONE); + } + + algorithm.setText("" + entry.bitStrength + "/" + entry.algorithm); + + if (entry.revoked) { + status.setText("revoked"); + } else { + status.setVisibility(View.GONE); + } + + LinearLayout ll = (LinearLayout) view.findViewById(R.id.list); + if (entry.userIds.size() == 1) { + ll.setVisibility(View.GONE); + } else { + boolean first = true; + boolean second = true; + for (String uid : entry.userIds) { + if (first) { + first = false; + continue; + } + if (!second) { + View sep = new View(mActivity); + sep.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 1)); + sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark); + ll.addView(sep); + } + TextView uidView = (TextView) mInflater.inflate( + R.layout.import_keys_list_entry_user_id, null); + uidView.setText(uid); + ll.addView(uidView); + second = false; + } + } + + CheckBox cBox = (CheckBox) view.findViewById(R.id.selected); + cBox.setChecked(entry.isSelected()); + + return view; + } + +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java new file mode 100644 index 000000000..1a100a585 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +import java.io.Serializable; +import java.util.ArrayList; + +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.util.AlgorithmNames; +import org.sufficientlysecure.keychain.util.IterableIterator; + +public class ImportKeysListEntry implements Serializable { + private static final long serialVersionUID = -7797972103284992662L; + public ArrayList<String> userIds; + public long keyId; + + public boolean revoked; + // public Date date; + public String fingerPrint; + public String hexKeyId; + public int bitStrength; + public String algorithm; + public boolean secretKey; + AlgorithmNames algorithmNames; + + private boolean selected; + + /** + * Constructor for later querying from keyserver + */ + public ImportKeysListEntry() { + secretKey = false; + userIds = new ArrayList<String>(); + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + /** + * Constructor based on key object, used for import from NFC, QR Codes, files + * + * @param pgpKey + */ + @SuppressWarnings("unchecked") + public ImportKeysListEntry(PGPKeyRing pgpKeyRing) { + // selected is default + this.selected = true; + + if (pgpKeyRing instanceof PGPSecretKeyRing) { + secretKey = true; + } else { + secretKey = false; + } + + userIds = new ArrayList<String>(); + for (String userId : new IterableIterator<String>(pgpKeyRing.getPublicKey().getUserIDs())) { + userIds.add(userId); + } + this.keyId = pgpKeyRing.getPublicKey().getKeyID(); + + this.revoked = pgpKeyRing.getPublicKey().isRevoked(); + this.fingerPrint = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey() + .getFingerprint()); + this.hexKeyId = PgpKeyHelper.convertKeyIdToHex(keyId); + this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength(); + int algorithm = pgpKeyRing.getPublicKey().getAlgorithm(); + if (algorithm == PGPPublicKey.RSA_ENCRYPT || algorithm == PGPPublicKey.RSA_GENERAL + || algorithm == PGPPublicKey.RSA_SIGN) { + this.algorithm = "RSA"; + } else if (algorithm == PGPPublicKey.DSA) { + this.algorithm = "DSA"; + } else if (algorithm == PGPPublicKey.ELGAMAL_ENCRYPT + || algorithm == PGPPublicKey.ELGAMAL_GENERAL) { + this.algorithm = "ElGamal"; + } else if (algorithm == PGPPublicKey.EC || algorithm == PGPPublicKey.ECDSA) { + this.algorithm = "ECC"; + } else { + // TODO: with resources + this.algorithm = "unknown"; + } + } +}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java new file mode 100644 index 000000000..2e5239a93 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPUtil; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.InputData; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.PositionAwareInputStream; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; + +public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> { + Context mContext; + + ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>(); + + byte[] mKeyringBytes; + String mImportFilename; + + public ImportKeysListLoader(Context context, byte[] keyringBytes, String importFilename) { + super(context); + this.mContext = context; + this.mKeyringBytes = keyringBytes; + this.mImportFilename = importFilename; + } + + @Override + public List<ImportKeysListEntry> loadInBackground() { + InputData inputData = null; + if (mKeyringBytes != null) { + inputData = new InputData(new ByteArrayInputStream(mKeyringBytes), mKeyringBytes.length); + } else if (mImportFilename != null) { + try { + inputData = new InputData(new FileInputStream(mImportFilename), + mImportFilename.length()); + } catch (FileNotFoundException e) { + Log.e(Constants.TAG, "Failed to init FileInputStream!", e); + } + } else { + return data; + } + + if (inputData != null) + generateListOfKeyrings(inputData); + + return data; + } + + @Override + protected void onReset() { + super.onReset(); + + // Ensure the loader is stopped + onStopLoading(); + } + + @Override + protected void onStartLoading() { + forceLoad(); + } + + @Override + protected void onStopLoading() { + cancelLoad(); + } + + @Override + public void deliverResult(List<ImportKeysListEntry> data) { + super.deliverResult(data); + } + + /** + * Reads all PGPKeyRing objects from input + * + * @param keyringBytes + * @return + */ + private void generateListOfKeyrings(InputData inputData) { + PositionAwareInputStream progressIn = new PositionAwareInputStream( + inputData.getInputStream()); + + // need to have access to the bufferedInput, so we can reuse it for the possible + // PGPObject chunks after the first one, e.g. files with several consecutive ASCII + // armour blocks + BufferedInputStream bufferedInput = new BufferedInputStream(progressIn); + try { + + // read all available blocks... (asc files can contain many blocks with BEGIN END) + while (bufferedInput.available() > 0) { + InputStream in = PGPUtil.getDecoderStream(bufferedInput); + PGPObjectFactory objectFactory = new PGPObjectFactory(in); + + // go through all objects in this block + Object obj; + while ((obj = objectFactory.nextObject()) != null) { + Log.d(Constants.TAG, "Found class: " + obj.getClass()); + + if (obj instanceof PGPKeyRing) { + PGPKeyRing newKeyring = (PGPKeyRing) obj; + addToData(newKeyring); + } else { + Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); + } + } + } + } catch (Exception e) { + Log.e(Constants.TAG, "Exception on parsing key file!", e); + } + } + + private void addToData(PGPKeyRing keyring) { + ImportKeysListEntry item = new ImportKeysListEntry(keyring); + data.add(item); + } + +} |