mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 11:12:15 -05:00
Import keys with adapter, loader, and new design
This commit is contained in:
parent
7b2de96d15
commit
917c86b524
@ -267,9 +267,7 @@
|
||||
android:label="@string/title_signKey" />
|
||||
<activity
|
||||
android:name=".ui.ImportKeysActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||
android:label="@string/title_importKeys"
|
||||
android:uiOptions="splitActionBarWhenNarrow"
|
||||
android:windowSoftInputMode="stateHidden" >
|
||||
|
||||
<!-- Keychain's own Actions -->
|
||||
|
@ -3,28 +3,37 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/import_keys_server_key_server"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
<Button
|
||||
android:id="@+id/import_keyserver_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" >
|
||||
android:text="@string/menu_keyServer" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/import_keys_server_query"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:inputType="textPersonName|textEmailAddress" />
|
||||
<!-- <Spinner -->
|
||||
<!-- android:id="@+id/import_keys_server_key_server" -->
|
||||
<!-- android:layout_width="fill_parent" -->
|
||||
<!-- android:layout_height="wrap_content" /> -->
|
||||
|
||||
<Button
|
||||
android:id="@+id/import_keys_server_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/btn_search" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- <LinearLayout -->
|
||||
<!-- android:layout_width="fill_parent" -->
|
||||
<!-- android:layout_height="wrap_content" -->
|
||||
<!-- android:orientation="horizontal" > -->
|
||||
|
||||
|
||||
<!-- <EditText -->
|
||||
<!-- android:id="@+id/import_keys_server_query" -->
|
||||
<!-- android:layout_width="0dip" -->
|
||||
<!-- android:layout_height="wrap_content" -->
|
||||
<!-- android:layout_weight="1" -->
|
||||
<!-- android:inputType="textPersonName|textEmailAddress" /> -->
|
||||
|
||||
|
||||
<!-- <Button -->
|
||||
<!-- android:id="@+id/import_keys_server_search" -->
|
||||
<!-- android:layout_width="wrap_content" -->
|
||||
<!-- android:layout_height="wrap_content" -->
|
||||
<!-- android:text="@string/btn_search" /> -->
|
||||
<!-- </LinearLayout> -->
|
||||
|
||||
</LinearLayout>
|
108
OpenPGP-Keychain/res/layout/import_keys_list_entry.xml
Normal file
108
OpenPGP-Keychain/res/layout/import_keys_list_entry.xml
Normal file
@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="3dip"
|
||||
android:paddingRight="?android:attr/scrollbarSize"
|
||||
android:singleLine="true" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/selected"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false" />
|
||||
<!-- focusable and clickable MUST be false to handle click and longClick in ListView Activity -->
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="5dip"
|
||||
android:paddingRight="5dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mainUserId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Main User ID"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fingerprint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="fingerprint"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mainUserIdRest"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="<user@somewhere.com>"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right"
|
||||
android:minWidth="90dip"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="3dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/keyId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="BBBBBBBB"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:typeface="monospace" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/algorithm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="#e00" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="30dip"
|
||||
android:orientation="vertical" >
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_marginRight="?android:attr/scrollbarSize"
|
||||
android:singleLine="true"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:paddingRight="3dip">
|
||||
|
||||
</TextView>
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
<!--
|
||||
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -14,69 +15,66 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:singleLine="true"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:paddingLeft="3dip"
|
||||
android:paddingRight="?android:attr/scrollbarSize"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:layout_width="fill_parent">
|
||||
android:singleLine="true" >
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/selected"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:clickable="false"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="5dip"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="5dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mainUserId"
|
||||
android:text="Main User ID"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Main User ID"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mainUserIdRest"
|
||||
android:text="<user@example.com>"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
android:text="<user@example.com>"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:minWidth="90dip"
|
||||
android:paddingLeft="3dip"
|
||||
android:gravity="right"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right"
|
||||
android:minWidth="90dip"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="3dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/keyId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="BBBBBBBB"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:typeface="monospace"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"/>
|
||||
android:typeface="monospace" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:text="expired"
|
||||
android:textStyle="italic"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
android:text="expired"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textStyle="italic" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -157,7 +157,7 @@
|
||||
<string name="notValid">not valid</string>
|
||||
<string name="nKeyServers">%s key server(s)</string>
|
||||
<string name="fingerprint">Fingerprint:</string>
|
||||
<string name="secretKeyring">Secret Keyring:</string>
|
||||
<string name="secretKey">Secret Key:</string>
|
||||
|
||||
<!-- choice_lowerCase: capitalized first word, no punctuation -->
|
||||
<string name="choice_none">None</string>
|
||||
@ -347,8 +347,8 @@
|
||||
<string name="help_about_version">Version:</string>
|
||||
|
||||
<!-- Import -->
|
||||
<string name="import_import">Import key(s) (only locally)</string>
|
||||
<string name="import_sign_and_upload">Import, Sign, and upload key(s)</string>
|
||||
<string name="import_import">Import selected keys</string>
|
||||
<string name="import_sign_and_upload">Import, Sign, and upload selected keys</string>
|
||||
<string name="import_finish">Finish</string>
|
||||
|
||||
<!-- Intent labels -->
|
||||
|
@ -24,10 +24,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
import org.spongycastle.openpgp.operator.KeyFingerPrintCalculator;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
@ -36,6 +37,7 @@ import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -100,17 +102,23 @@ public class PgpImportExport {
|
||||
}
|
||||
}
|
||||
|
||||
public Bundle importKeyRings(InputData data) throws PgpGeneralException, FileNotFoundException,
|
||||
PGPException, IOException {
|
||||
/**
|
||||
* Imports keys from given data. If keyIds is given only those are imported
|
||||
*
|
||||
* @param data
|
||||
* @param keyIds
|
||||
* @return
|
||||
* @throws PgpGeneralException
|
||||
* @throws FileNotFoundException
|
||||
* @throws PGPException
|
||||
* @throws IOException
|
||||
*/
|
||||
public Bundle importKeyRings(InputData data, ArrayList<Long> keyIds)
|
||||
throws PgpGeneralException, FileNotFoundException, PGPException, IOException {
|
||||
Bundle returnData = new Bundle();
|
||||
|
||||
updateProgress(R.string.progress_importingSecretKeys, 0, 100);
|
||||
|
||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_externalStorageNotReady));
|
||||
}
|
||||
|
||||
PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream());
|
||||
|
||||
// need to have access to the bufferedInput, so we can reuse it for the possible
|
||||
@ -137,7 +145,16 @@ public class PgpImportExport {
|
||||
|
||||
int status = Integer.MIN_VALUE; // out of bounds value
|
||||
|
||||
status = storeKeyRingInCache(keyring);
|
||||
if (keyIds != null) {
|
||||
if (keyIds.contains(keyring.getPublicKey().getKeyID())) {
|
||||
status = storeKeyRingInCache(keyring);
|
||||
} else {
|
||||
Log.d(Constants.TAG, "not selected! key id: "
|
||||
+ keyring.getPublicKey().getKeyID());
|
||||
}
|
||||
} else {
|
||||
status = storeKeyRingInCache(keyring);
|
||||
}
|
||||
|
||||
if (status == Id.return_value.error) {
|
||||
throw new PgpGeneralException(
|
||||
@ -264,11 +281,14 @@ public class PgpImportExport {
|
||||
|
||||
if (save) {
|
||||
ProviderHelper.saveKeyRing(mContext, secretKeyRing);
|
||||
// TODO: preserve certifications (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?)
|
||||
// TODO: preserve certifications
|
||||
// (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?)
|
||||
PGPPublicKeyRing newPubRing = null;
|
||||
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(secretKeyRing.getPublicKeys())) {
|
||||
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(
|
||||
secretKeyRing.getPublicKeys())) {
|
||||
if (newPubRing == null) {
|
||||
newPubRing = new PGPPublicKeyRing(key.getEncoded(), new JcaKeyFingerprintCalculator());
|
||||
newPubRing = new PGPPublicKeyRing(key.getEncoded(),
|
||||
new JcaKeyFingerprintCalculator());
|
||||
}
|
||||
newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key);
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ public class PgpKeyHelper {
|
||||
PGPPublicKey masterKey = null;
|
||||
for (int i = 0; i < encryptKeys.size(); ++i) {
|
||||
PGPPublicKey key = encryptKeys.get(i);
|
||||
if (!isExpired(key) && !key.isRevoked()) {
|
||||
if (!isExpired(key) && !key.isRevoked()) {
|
||||
if (key.isMasterKey()) {
|
||||
masterKey = key;
|
||||
} else {
|
||||
@ -488,7 +488,7 @@ public class PgpKeyHelper {
|
||||
return isSecretKeyPrivateEmpty(secretKey);
|
||||
}
|
||||
|
||||
public static String getSmallFingerPrint(long keyId) {
|
||||
public static String convertKeyIdToHex(long keyId) {
|
||||
String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
|
||||
while (fingerPrint.length() < 8) {
|
||||
fingerPrint = "0" + fingerPrint;
|
||||
@ -496,11 +496,17 @@ public class PgpKeyHelper {
|
||||
return fingerPrint;
|
||||
}
|
||||
|
||||
public static String keyToHex(long keyId) {
|
||||
return getSmallFingerPrint(keyId >> 32) + getSmallFingerPrint(keyId);
|
||||
/**
|
||||
* TODO: what is the difference to the other function?
|
||||
*
|
||||
* @param keyId
|
||||
* @return
|
||||
*/
|
||||
public static String convertKeyToHex(long keyId) {
|
||||
return convertKeyIdToHex(keyId >> 32) + convertKeyIdToHex(keyId);
|
||||
}
|
||||
|
||||
public static long keyFromHex(String data) {
|
||||
public static long convertHexToKeyId(String data) {
|
||||
int len = data.length();
|
||||
String s2 = data.substring(len - 8);
|
||||
String s1 = data.substring(0, len - 8);
|
||||
|
@ -27,7 +27,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
@ -45,6 +47,7 @@ import org.sufficientlysecure.keychain.pgp.PgpOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.KeyServer.KeyInfo;
|
||||
@ -142,7 +145,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
public static final String IMPORT_INPUT_STREAM = "import_input_stream";
|
||||
public static final String IMPORT_FILENAME = "import_filename";
|
||||
public static final String IMPORT_BYTES = "import_bytes";
|
||||
// public static final String IMPORT_KEY_TYPE = "importKeyType";
|
||||
public static final String IMPORT_KEY_LIST = "import_key_list";
|
||||
|
||||
// export key
|
||||
public static final String EXPORT_OUTPUT_STREAM = "export_output_stream";
|
||||
@ -630,11 +633,6 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
/* Input */
|
||||
int target = data.getInt(TARGET);
|
||||
|
||||
// int keyType = Id.type.public_key;
|
||||
// if (data.containsKey(IMPORT_KEY_TYPE)) {
|
||||
// keyType = data.getInt(IMPORT_KEY_TYPE);
|
||||
// }
|
||||
|
||||
/* Operation */
|
||||
InputStream inStream = null;
|
||||
long inLength = -1;
|
||||
@ -666,8 +664,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
|
||||
Bundle resultData = new Bundle();
|
||||
|
||||
ArrayList<Long> keyIds = (ArrayList<Long>) data.getSerializable(IMPORT_KEY_LIST);
|
||||
|
||||
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
|
||||
resultData = pgpImportExport.importKeyRings(inputData);
|
||||
resultData = pgpImportExport.importKeyRings(inputData, keyIds);
|
||||
|
||||
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
|
||||
} catch (Exception e) {
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
@ -29,7 +25,8 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity;
|
||||
import org.sufficientlysecure.keychain.util.KeyValueSpinnerAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
|
||||
import org.sufficientlysecure.keychain.util.AlgorithmNames;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
@ -114,18 +111,10 @@ public class AppSettingsFragment extends Fragment {
|
||||
mHashAlgorithm = (Spinner) view.findViewById(R.id.api_app_settings_hash_algorithm);
|
||||
mCompression = (Spinner) view.findViewById(R.id.api_app_settings_compression);
|
||||
|
||||
HashMap<Integer, String> encryptionMap = new HashMap<Integer, String>();
|
||||
encryptionMap.put(PGPEncryptedData.AES_128, "AES-128");
|
||||
encryptionMap.put(PGPEncryptedData.AES_192, "AES-192");
|
||||
encryptionMap.put(PGPEncryptedData.AES_256, "AES-256");
|
||||
encryptionMap.put(PGPEncryptedData.BLOWFISH, "Blowfish");
|
||||
encryptionMap.put(PGPEncryptedData.TWOFISH, "Twofish");
|
||||
encryptionMap.put(PGPEncryptedData.CAST5, "CAST5");
|
||||
encryptionMap.put(PGPEncryptedData.DES, "DES");
|
||||
encryptionMap.put(PGPEncryptedData.TRIPLE_DES, "Triple DES");
|
||||
encryptionMap.put(PGPEncryptedData.IDEA, "IDEA");
|
||||
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
|
||||
|
||||
encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(), encryptionMap);
|
||||
encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||
algorithmNames.getEncryptionNames());
|
||||
mEncryptionAlgorithm.setAdapter(encryptionAdapter);
|
||||
mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
@ -139,16 +128,7 @@ public class AppSettingsFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
HashMap<Integer, String> hashMap = new HashMap<Integer, String>();
|
||||
hashMap.put(HashAlgorithmTags.MD5, "MD5");
|
||||
hashMap.put(HashAlgorithmTags.RIPEMD160, "RIPEMD-160");
|
||||
hashMap.put(HashAlgorithmTags.SHA1, "SHA-1");
|
||||
hashMap.put(HashAlgorithmTags.SHA224, "SHA-224");
|
||||
hashMap.put(HashAlgorithmTags.SHA256, "SHA-256");
|
||||
hashMap.put(HashAlgorithmTags.SHA384, "SHA-384");
|
||||
hashMap.put(HashAlgorithmTags.SHA512, "SHA-512");
|
||||
|
||||
hashAdapter = new KeyValueSpinnerAdapter(getActivity(), hashMap);
|
||||
hashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
|
||||
mHashAlgorithm.setAdapter(hashAdapter);
|
||||
mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
@ -162,15 +142,8 @@ public class AppSettingsFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
HashMap<Integer, String> compressionMap = new HashMap<Integer, String>();
|
||||
compressionMap.put(Id.choice.compression.none, getString(R.string.choice_none) + " ("
|
||||
+ getString(R.string.fast) + ")");
|
||||
compressionMap.put(Id.choice.compression.zip, "ZIP (" + getString(R.string.fast) + ")");
|
||||
compressionMap.put(Id.choice.compression.zlib, "ZLIB (" + getString(R.string.fast) + ")");
|
||||
compressionMap.put(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.very_slow)
|
||||
+ ")");
|
||||
|
||||
compressionAdapter = new KeyValueSpinnerAdapter(getActivity(), compressionMap);
|
||||
compressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||
algorithmNames.getCompressionNames());
|
||||
mCompression.setAdapter(compressionAdapter);
|
||||
mCompression.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
|
@ -773,7 +773,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
||||
mSignatureKeyId = returnData
|
||||
.getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
|
||||
mUserIdRest.setText("id: "
|
||||
+ PgpKeyHelper.getSmallFingerPrint(mSignatureKeyId));
|
||||
+ PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId));
|
||||
if (userId == null) {
|
||||
userId = getResources().getString(R.string.unknownUserId);
|
||||
}
|
||||
|
@ -17,12 +17,15 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
@ -44,7 +47,6 @@ import android.widget.Toast;
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
public class ImportKeysActivity extends SherlockFragmentActivity implements OnNavigationListener {
|
||||
@ -152,27 +154,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
|
||||
mListFragment.load(importData, importFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* ActionBar menu is created based on class variables to change it at runtime
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(1, Id.menu.option.key_server, 0, R.string.menu_keyServer).setShowAsAction(
|
||||
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
||||
menu.add(1, Id.menu.option.import_from_file, 1, R.string.menu_importFromFile)
|
||||
.setShowAsAction(
|
||||
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
||||
menu.add(1, Id.menu.option.import_from_qr_code, 2, R.string.menu_importFromQrCode)
|
||||
.setShowAsAction(
|
||||
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
||||
menu.add(1, Id.menu.option.import_from_nfc, 3, R.string.menu_importFromNfc)
|
||||
.setShowAsAction(
|
||||
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
@ -184,23 +165,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
|
||||
startActivity(intent);
|
||||
return true;
|
||||
|
||||
case Id.menu.option.key_server:
|
||||
startActivityForResult(new Intent(this, KeyServerQueryActivity.class), 0);
|
||||
|
||||
return true;
|
||||
|
||||
// case Id.menu.option.import_from_file:
|
||||
// showImportFromFileDialog();
|
||||
// return true;
|
||||
|
||||
// case Id.menu.option.import_from_qr_code:
|
||||
// importFromQrCode();
|
||||
// return true;
|
||||
//
|
||||
// case Id.menu.option.import_from_nfc:
|
||||
// importFromNfc();
|
||||
// return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
|
||||
@ -329,8 +293,16 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
|
||||
// fill values for this action
|
||||
Bundle data = new Bundle();
|
||||
|
||||
// TODO: check for key type?
|
||||
// data.putInt(KeychainIntentService.IMPORT_KEY_TYPE, Id.type.secret_key);
|
||||
// get selected key ids
|
||||
List<ImportKeysListEntry> listEntries = mListFragment.getData();
|
||||
ArrayList<Long> selectedKeyIds = new ArrayList<Long>();
|
||||
for (ImportKeysListEntry entry : listEntries) {
|
||||
if (entry.isSelected()) {
|
||||
selectedKeyIds.add(entry.keyId);
|
||||
}
|
||||
}
|
||||
|
||||
data.putSerializable(KeychainIntentService.IMPORT_KEY_LIST, selectedKeyIds);
|
||||
|
||||
if (mListFragment.getKeyBytes() != null) {
|
||||
data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);
|
||||
|
@ -68,8 +68,8 @@ public class ImportKeysFileFragment extends Fragment {
|
||||
// open .asc or .gpg files
|
||||
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
|
||||
// or gpg types!
|
||||
FileHelper.openFile(ImportKeysFileFragment.this, mFilename.getText().toString(), "*/*",
|
||||
Id.request.filename);
|
||||
FileHelper.openFile(ImportKeysFileFragment.this, mFilename.getText().toString(),
|
||||
"*/*", Id.request.filename);
|
||||
}
|
||||
});
|
||||
|
||||
@ -84,7 +84,7 @@ public class ImportKeysFileFragment extends Fragment {
|
||||
|
||||
// set default path
|
||||
String path = Constants.path.APP_DIR + "/";
|
||||
if (getArguments() != null) {
|
||||
if (getArguments() != null && getArguments().containsKey(ARG_PATH)) {
|
||||
path = getArguments().getString(ARG_PATH);
|
||||
}
|
||||
mFilename.setText(path);
|
||||
|
@ -17,38 +17,33 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.ui.widget.ImportKeysListLoader;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleAdapter;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
|
||||
public class ImportKeysListFragment extends SherlockListFragment implements
|
||||
LoaderManager.LoaderCallbacks<List<Map<String, String>>> {
|
||||
// public static final String ARG_IMPORT_DATA = "bytes";
|
||||
// public static final String ARG_IMPORT_FILENAME = "filename";
|
||||
LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> {
|
||||
|
||||
private Activity mActivity;
|
||||
private SimpleAdapter mAdapter;
|
||||
private ImportKeysAdapter mAdapter;
|
||||
|
||||
private byte[] mKeyBytes;
|
||||
private String mImportFilename;
|
||||
|
||||
|
||||
|
||||
public byte[] getKeyBytes() {
|
||||
return mKeyBytes;
|
||||
}
|
||||
@ -57,38 +52,19 @@ public class ImportKeysListFragment extends SherlockListFragment implements
|
||||
return mImportFilename;
|
||||
}
|
||||
|
||||
public List<ImportKeysListEntry> getData() {
|
||||
return mAdapter.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*/
|
||||
public static ImportKeysListFragment newInstance() {
|
||||
ImportKeysListFragment frag = new ImportKeysListFragment();
|
||||
Bundle args = new Bundle();
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView listView, View view, int position, long id) {
|
||||
// Map<String, String> item = (Map<String, String>) listView.getItemAtPosition(position);
|
||||
// String userId = item.get(ImportKeysListLoader.MAP_ATTR_USER_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume is called after rotating
|
||||
*/
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setListShown(false);
|
||||
|
||||
// reload list
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define Adapter and Loader on create of Activity
|
||||
*/
|
||||
@ -96,10 +72,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
mActivity = this.getActivity();
|
||||
|
||||
// mKeyBytes = getArguments().getByteArray(ARG_IMPORT_DATA);
|
||||
// mImportFilename = getArguments().getString(ARG_IMPORT_FILENAME);
|
||||
mActivity = getActivity();
|
||||
|
||||
// register long press context menu
|
||||
registerForContextMenu(getListView());
|
||||
@ -109,11 +82,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements
|
||||
setEmptyText(mActivity.getString(R.string.error_nothingImport));
|
||||
|
||||
// Create an empty adapter we will use to display the loaded data.
|
||||
String[] from = new String[] {};
|
||||
int[] to = new int[] {};
|
||||
List<Map<String, String>> data = new ArrayList<Map<String, String>>();
|
||||
mAdapter = new SimpleAdapter(getActivity(), data, android.R.layout.two_line_list_item,
|
||||
from, to);
|
||||
mAdapter = new ImportKeysAdapter(getActivity());
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
@ -124,39 +93,37 @@ public class ImportKeysListFragment extends SherlockListFragment implements
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
public void load(byte[] importData, String importFilename) {
|
||||
mKeyBytes = importData;
|
||||
mImportFilename = importFilename;
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
// Select checkbox!
|
||||
// Update underlying data and notify adapter of change. The adapter will
|
||||
// update the view automatically.
|
||||
ImportKeysListEntry entry = mAdapter.getItem(position);
|
||||
entry.setSelected(!entry.isSelected());
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void load(byte[] importData, String importFilename) {
|
||||
this.mKeyBytes = importData;
|
||||
this.mImportFilename = importFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<List<Map<String, String>>> onCreateLoader(int id, Bundle args) {
|
||||
public Loader<List<ImportKeysListEntry>> onCreateLoader(int id, Bundle args) {
|
||||
return new ImportKeysListLoader(mActivity, mKeyBytes, mImportFilename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<Map<String, String>>> loader,
|
||||
List<Map<String, String>> data) {
|
||||
// Set the new data in the adapter.
|
||||
// for (String item : data) {
|
||||
// mAdapter.add(item);
|
||||
// }
|
||||
public void onLoadFinished(Loader<List<ImportKeysListEntry>> loader,
|
||||
List<ImportKeysListEntry> data) {
|
||||
Log.d(Constants.TAG, "data: " + data);
|
||||
// TODO: real swapping the data to the already defined adapter doesn't work
|
||||
// Workaround: recreate adapter!
|
||||
// http://stackoverflow.com/questions/2356091/android-add-function-of-arrayadapter-not-working
|
||||
// mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.two_line_list_item,
|
||||
// data);
|
||||
|
||||
String[] from = new String[] { ImportKeysListLoader.MAP_ATTR_USER_ID,
|
||||
ImportKeysListLoader.MAP_ATTR_FINGERPINT };
|
||||
int[] to = new int[] { android.R.id.text1, android.R.id.text2 };
|
||||
mAdapter = new SimpleAdapter(getActivity(), data, android.R.layout.two_line_list_item,
|
||||
from, to);
|
||||
|
||||
// swap in the real data!
|
||||
mAdapter.setData(data);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// The list should now be shown.
|
||||
@ -168,10 +135,9 @@ public class ImportKeysListFragment extends SherlockListFragment implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<List<Map<String, String>>> loader) {
|
||||
public void onLoaderReset(Loader<List<ImportKeysListEntry>> loader) {
|
||||
// Clear the data in the adapter.
|
||||
// Not available in SimpleAdapter!
|
||||
// mAdapter.clear();
|
||||
mAdapter.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,13 +19,17 @@ package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
public class ImportKeysServerFragment extends Fragment {
|
||||
private Button mButton;
|
||||
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
@ -44,8 +48,19 @@ public class ImportKeysServerFragment extends Fragment {
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.import_keys_keyserver_fragment, container, false);
|
||||
View view = inflater.inflate(R.layout.import_keys_keyserver_fragment, container, false);
|
||||
|
||||
mButton = (Button) view.findViewById(R.id.import_keyserver_button);
|
||||
mButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// TODO: use fragment instead of activity, handle onresult here!
|
||||
startActivityForResult(new Intent(getActivity(), KeyServerQueryActivity.class), 0);
|
||||
}
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyListAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyListAdapter;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Intent;
|
||||
|
@ -22,7 +22,7 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyListAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyListAdapter;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
@ -140,7 +140,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
|
||||
if (ACTION_LOOK_UP_KEY_ID.equals(action) || ACTION_LOOK_UP_KEY_ID_AND_RETURN.equals(action)) {
|
||||
long keyId = intent.getLongExtra(EXTRA_KEY_ID, 0);
|
||||
if (keyId != 0) {
|
||||
String query = "0x" + PgpKeyHelper.keyToHex(keyId);
|
||||
String query = "0x" + PgpKeyHelper.convertKeyToHex(keyId);
|
||||
mQuery.setText(query);
|
||||
search(query);
|
||||
}
|
||||
@ -308,7 +308,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
|
||||
mainUserId.setText(userId);
|
||||
}
|
||||
|
||||
keyId.setText(PgpKeyHelper.getSmallFingerPrint(keyInfo.keyId));
|
||||
keyId.setText(PgpKeyHelper.convertKeyIdToHex(keyInfo.keyId));
|
||||
|
||||
if (mainUserIdRest.getText().length() == 0) {
|
||||
mainUserIdRest.setVisibility(View.GONE);
|
||||
|
@ -28,7 +28,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.widget.SelectKeyCursorAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.database.Cursor;
|
||||
|
@ -26,7 +26,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.widget.SelectKeyCursorAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.widget;
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@ -23,32 +23,23 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, String>>> {
|
||||
public static final String MAP_ATTR_USER_ID = "user_id";
|
||||
public static final String MAP_ATTR_FINGERPINT = "fingerprint";
|
||||
|
||||
ArrayList<Map<String, String>> data = new ArrayList<Map<String, String>>();
|
||||
|
||||
public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
|
||||
Context mContext;
|
||||
List<String> mItems;
|
||||
|
||||
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
|
||||
|
||||
byte[] mKeyringBytes;
|
||||
String mImportFilename;
|
||||
@ -61,7 +52,7 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, String>> loadInBackground() {
|
||||
public List<ImportKeysListEntry> loadInBackground() {
|
||||
InputData inputData = null;
|
||||
if (mKeyringBytes != null) {
|
||||
inputData = new InputData(new ByteArrayInputStream(mKeyringBytes), mKeyringBytes.length);
|
||||
@ -76,7 +67,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
|
||||
return data;
|
||||
}
|
||||
|
||||
generateListOfKeyrings(inputData);
|
||||
if (inputData != null)
|
||||
generateListOfKeyrings(inputData);
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -100,12 +92,12 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(List<Map<String, String>> data) {
|
||||
public void deliverResult(List<ImportKeysListEntry> data) {
|
||||
super.deliverResult(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to PGPMain.importKeyRings
|
||||
* Reads all PGPKeyRing objects from input
|
||||
*
|
||||
* @param keyringBytes
|
||||
* @return
|
||||
@ -144,20 +136,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
|
||||
}
|
||||
|
||||
private void addToData(PGPKeyRing keyring) {
|
||||
String userId = PgpKeyHelper.getMainUserId(keyring.getPublicKey());
|
||||
|
||||
if (keyring instanceof PGPSecretKeyRing) {
|
||||
userId = mContext.getString(R.string.secretKeyring) + " " + userId;
|
||||
}
|
||||
|
||||
String fingerprint = PgpKeyHelper.convertFingerprintToHex(keyring.getPublicKey()
|
||||
.getFingerprint());
|
||||
|
||||
Map<String, String> attrs = new HashMap<String, String>();
|
||||
attrs.put(MAP_ATTR_USER_ID, userId);
|
||||
attrs.put(MAP_ATTR_FINGERPINT, mContext.getString(R.string.fingerprint) + "\n"
|
||||
+ fingerprint);
|
||||
data.add(attrs);
|
||||
ImportKeysListEntry item = new ImportKeysListEntry(keyring);
|
||||
data.add(item);
|
||||
}
|
||||
|
||||
}
|
@ -79,7 +79,7 @@ public class LookupUnknownKeyDialogFragment extends DialogFragment {
|
||||
alert.setIcon(android.R.drawable.ic_dialog_alert);
|
||||
alert.setTitle(R.string.title_unknownSignatureKey);
|
||||
alert.setMessage(getString(R.string.lookupUnknownKey,
|
||||
PgpKeyHelper.getSmallFingerPrint(unknownKeyId)));
|
||||
PgpKeyHelper.convertKeyIdToHex(unknownKeyId)));
|
||||
|
||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
|
||||
|
@ -152,8 +152,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
}
|
||||
|
||||
mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(key));
|
||||
String keyId1Str = PgpKeyHelper.getSmallFingerPrint(key.getKeyID());
|
||||
String keyId2Str = PgpKeyHelper.getSmallFingerPrint(key.getKeyID() >> 32);
|
||||
String keyId1Str = PgpKeyHelper.convertKeyIdToHex(key.getKeyID());
|
||||
String keyId2Str = PgpKeyHelper.convertKeyIdToHex(key.getKeyID() >> 32);
|
||||
mKeyId.setText(keyId1Str + " " + keyId2Str);
|
||||
|
||||
Vector<Choice> choices = new Vector<Choice>();
|
||||
|
@ -1,273 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.widget;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.MergeCursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorTreeAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class KeyListAdapter extends CursorTreeAdapter {
|
||||
private Context mContext;
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
protected int mKeyType;
|
||||
|
||||
private static final int CHILD_KEY = 0;
|
||||
private static final int CHILD_USER_ID = 1;
|
||||
private static final int CHILD_FINGERPRINT = 2;
|
||||
|
||||
public KeyListAdapter(Context context, Cursor groupCursor, int keyType) {
|
||||
super(groupCursor, context);
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mKeyType = keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflate new view for group items
|
||||
*/
|
||||
@Override
|
||||
public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
|
||||
return mInflater.inflate(R.layout.key_list_group_item, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds TextViews from group view to results from database group cursor.
|
||||
*/
|
||||
@Override
|
||||
protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) {
|
||||
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
|
||||
|
||||
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
|
||||
mainUserId.setText(R.string.unknownUserId);
|
||||
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
|
||||
mainUserIdRest.setText("");
|
||||
|
||||
String userId = cursor.getString(userIdIndex);
|
||||
if (userId != null) {
|
||||
String[] userIdSplit = OtherHelper.splitUserId(userId);
|
||||
|
||||
if (userIdSplit[1] != null) {
|
||||
mainUserIdRest.setText(userIdSplit[1]);
|
||||
}
|
||||
mainUserId.setText(userIdSplit[0]);
|
||||
}
|
||||
|
||||
if (mainUserId.getText().length() == 0) {
|
||||
mainUserId.setText(R.string.unknownUserId);
|
||||
}
|
||||
|
||||
if (mainUserIdRest.getText().length() == 0) {
|
||||
mainUserIdRest.setVisibility(View.GONE);
|
||||
} else {
|
||||
mainUserIdRest.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflate new view for child items
|
||||
*/
|
||||
@Override
|
||||
public View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup parent) {
|
||||
return mInflater.inflate(R.layout.key_list_child_item, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind TextViews from view of childs based on query results
|
||||
*/
|
||||
@Override
|
||||
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
|
||||
LinearLayout keyLayout = (LinearLayout) view.findViewById(R.id.keyLayout);
|
||||
LinearLayout userIdLayout = (LinearLayout) view.findViewById(R.id.userIdLayout);
|
||||
|
||||
// first entry is fingerprint
|
||||
if (cursor.getPosition() == 0) {
|
||||
// show only userId layout
|
||||
keyLayout.setVisibility(View.GONE);
|
||||
userIdLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
String fingerprint = PgpKeyHelper.getFingerPrint(context,
|
||||
cursor.getLong(cursor.getColumnIndex(Keys.KEY_ID)));
|
||||
fingerprint = fingerprint.replace(" ", "\n");
|
||||
|
||||
TextView userId = (TextView) view.findViewById(R.id.userId);
|
||||
if (userId == null) {
|
||||
Log.d(Constants.TAG, "userId is null!");
|
||||
}
|
||||
userId.setText(context.getString(R.string.fingerprint) + "\n" + fingerprint);
|
||||
} else {
|
||||
// differentiate between keys and userIds in MergeCursor
|
||||
if (cursor.getColumnIndex(Keys.KEY_ID) != -1) {
|
||||
keyLayout.setVisibility(View.VISIBLE);
|
||||
userIdLayout.setVisibility(View.GONE);
|
||||
|
||||
String keyIdStr = PgpKeyHelper.getSmallFingerPrint(cursor.getLong(cursor
|
||||
.getColumnIndex(Keys.KEY_ID)));
|
||||
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
|
||||
cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
|
||||
cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
|
||||
|
||||
TextView keyId = (TextView) view.findViewById(R.id.keyId);
|
||||
keyId.setText(keyIdStr);
|
||||
|
||||
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
|
||||
keyDetails.setText("(" + algorithmStr + ")");
|
||||
|
||||
ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
|
||||
if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
|
||||
masterKeyIcon.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
masterKeyIcon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
|
||||
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
|
||||
certifyIcon.setVisibility(View.GONE);
|
||||
} else {
|
||||
certifyIcon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
|
||||
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
|
||||
encryptIcon.setVisibility(View.GONE);
|
||||
} else {
|
||||
encryptIcon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
|
||||
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
|
||||
signIcon.setVisibility(View.GONE);
|
||||
} else {
|
||||
signIcon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
keyLayout.setVisibility(View.GONE);
|
||||
userIdLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
String userIdStr = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
|
||||
|
||||
TextView userId = (TextView) view.findViewById(R.id.userId);
|
||||
userId.setText(userIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the group cursor, we start cursors for a fingerprint, keys, and userIds, which are
|
||||
* merged together and build the child cursor
|
||||
*/
|
||||
@Override
|
||||
protected Cursor getChildrenCursor(Cursor groupCursor) {
|
||||
final long keyRingRowId = groupCursor.getLong(groupCursor.getColumnIndex(BaseColumns._ID));
|
||||
|
||||
Cursor fingerprintCursor = getChildCursor(keyRingRowId, CHILD_FINGERPRINT);
|
||||
Cursor keyCursor = getChildCursor(keyRingRowId, CHILD_KEY);
|
||||
Cursor userIdCursor = getChildCursor(keyRingRowId, CHILD_USER_ID);
|
||||
|
||||
MergeCursor mergeCursor = new MergeCursor(new Cursor[] { fingerprintCursor, keyCursor,
|
||||
userIdCursor });
|
||||
Log.d(Constants.TAG, "mergeCursor:" + DatabaseUtils.dumpCursorToString(mergeCursor));
|
||||
|
||||
return mergeCursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* This builds a cursor for a specific type of children
|
||||
*
|
||||
* @param keyRingRowId
|
||||
* foreign row id of the keyRing
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private Cursor getChildCursor(long keyRingRowId, int type) {
|
||||
Uri uri = null;
|
||||
String[] projection = null;
|
||||
String sortOrder = null;
|
||||
String selection = null;
|
||||
|
||||
switch (type) {
|
||||
case CHILD_FINGERPRINT:
|
||||
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
|
||||
Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
|
||||
sortOrder = Keys.RANK + " ASC";
|
||||
|
||||
// use only master key for fingerprint
|
||||
selection = Keys.IS_MASTER_KEY + " = 1 ";
|
||||
|
||||
if (mKeyType == Id.type.public_key) {
|
||||
uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
|
||||
} else {
|
||||
uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
|
||||
}
|
||||
break;
|
||||
|
||||
case CHILD_KEY:
|
||||
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
|
||||
Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
|
||||
sortOrder = Keys.RANK + " ASC";
|
||||
|
||||
if (mKeyType == Id.type.public_key) {
|
||||
uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
|
||||
} else {
|
||||
uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHILD_USER_ID:
|
||||
projection = new String[] { UserIds._ID, UserIds.USER_ID, UserIds.RANK, };
|
||||
sortOrder = UserIds.RANK + " ASC";
|
||||
|
||||
// not the main user id
|
||||
selection = UserIds.RANK + " > 0 ";
|
||||
|
||||
if (mKeyType == Id.type.public_key) {
|
||||
uri = UserIds.buildPublicUserIdsUri(String.valueOf(keyRingRowId));
|
||||
} else {
|
||||
uri = UserIds.buildSecretUserIdsUri(String.valueOf(keyRingRowId));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
|
||||
}
|
||||
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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.widget;
|
||||
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class SelectKeyCursorAdapter extends CursorAdapter {
|
||||
|
||||
protected int mKeyType;
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
private ListView mListView;
|
||||
|
||||
public final static String PROJECTION_ROW_AVAILABLE = "available";
|
||||
public final static String PROJECTION_ROW_VALID = "valid";
|
||||
|
||||
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
|
||||
int keyType) {
|
||||
super(context, c, flags);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mListView = listView;
|
||||
mKeyType = keyType;
|
||||
}
|
||||
|
||||
public String getUserId(int position) {
|
||||
mCursor.moveToPosition(position);
|
||||
return mCursor.getString(mCursor.getColumnIndex(UserIds.USER_ID));
|
||||
}
|
||||
|
||||
public long getMasterKeyId(int position) {
|
||||
mCursor.moveToPosition(position);
|
||||
return mCursor.getLong(mCursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
boolean valid = cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_VALID)) > 0;
|
||||
|
||||
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 status = (TextView) view.findViewById(R.id.status);
|
||||
status.setText(R.string.unknownStatus);
|
||||
|
||||
String userId = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
|
||||
if (userId != null) {
|
||||
String[] userIdSplit = OtherHelper.splitUserId(userId);
|
||||
|
||||
if (userIdSplit[1] != null) {
|
||||
mainUserIdRest.setText(userIdSplit[1]);
|
||||
}
|
||||
mainUserId.setText(userIdSplit[0]);
|
||||
}
|
||||
|
||||
long masterKeyId = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
|
||||
keyId.setText(PgpKeyHelper.getSmallFingerPrint(masterKeyId));
|
||||
|
||||
if (mainUserIdRest.getText().length() == 0) {
|
||||
mainUserIdRest.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (mKeyType == Id.type.public_key) {
|
||||
status.setText(R.string.canEncrypt);
|
||||
} else {
|
||||
status.setText(R.string.canSign);
|
||||
}
|
||||
} else {
|
||||
if (cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_AVAILABLE)) > 0) {
|
||||
// has some CAN_ENCRYPT keys, but col(ROW_VALID) = 0, so must be revoked or
|
||||
// expired
|
||||
status.setText(R.string.expired);
|
||||
} else {
|
||||
status.setText(R.string.noKey);
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
|
||||
if (mKeyType == Id.type.public_key) {
|
||||
selected.setVisibility(View.VISIBLE);
|
||||
|
||||
if (!valid) {
|
||||
mListView.setItemChecked(cursor.getPosition(), false);
|
||||
}
|
||||
|
||||
selected.setChecked(mListView.isItemChecked(cursor.getPosition()));
|
||||
selected.setEnabled(valid);
|
||||
} else {
|
||||
selected.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
status.setText(status.getText() + " ");
|
||||
|
||||
view.setEnabled(valid);
|
||||
mainUserId.setEnabled(valid);
|
||||
mainUserIdRest.setEnabled(valid);
|
||||
keyId.setEnabled(valid);
|
||||
status.setEnabled(valid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return mInflater.inflate(R.layout.select_key_item, null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
||||
@SuppressLint("UseSparseArrays")
|
||||
public class AlgorithmNames {
|
||||
Activity mActivity;
|
||||
|
||||
HashMap<Integer, String> mEncryptionNames = new HashMap<Integer, String>();
|
||||
HashMap<Integer, String> mHashNames = new HashMap<Integer, String>();
|
||||
HashMap<Integer, String> mCompressionNames = new HashMap<Integer, String>();
|
||||
|
||||
public AlgorithmNames(Activity context) {
|
||||
super();
|
||||
this.mActivity = context;
|
||||
|
||||
mEncryptionNames.put(PGPEncryptedData.AES_128, "AES-128");
|
||||
mEncryptionNames.put(PGPEncryptedData.AES_192, "AES-192");
|
||||
mEncryptionNames.put(PGPEncryptedData.AES_256, "AES-256");
|
||||
mEncryptionNames.put(PGPEncryptedData.BLOWFISH, "Blowfish");
|
||||
mEncryptionNames.put(PGPEncryptedData.TWOFISH, "Twofish");
|
||||
mEncryptionNames.put(PGPEncryptedData.CAST5, "CAST5");
|
||||
mEncryptionNames.put(PGPEncryptedData.DES, "DES");
|
||||
mEncryptionNames.put(PGPEncryptedData.TRIPLE_DES, "Triple DES");
|
||||
mEncryptionNames.put(PGPEncryptedData.IDEA, "IDEA");
|
||||
|
||||
mHashNames.put(HashAlgorithmTags.MD5, "MD5");
|
||||
mHashNames.put(HashAlgorithmTags.RIPEMD160, "RIPEMD-160");
|
||||
mHashNames.put(HashAlgorithmTags.SHA1, "SHA-1");
|
||||
mHashNames.put(HashAlgorithmTags.SHA224, "SHA-224");
|
||||
mHashNames.put(HashAlgorithmTags.SHA256, "SHA-256");
|
||||
mHashNames.put(HashAlgorithmTags.SHA384, "SHA-384");
|
||||
mHashNames.put(HashAlgorithmTags.SHA512, "SHA-512");
|
||||
|
||||
mCompressionNames.put(Id.choice.compression.none, mActivity.getString(R.string.choice_none)
|
||||
+ " (" + mActivity.getString(R.string.fast) + ")");
|
||||
mCompressionNames.put(Id.choice.compression.zip,
|
||||
"ZIP (" + mActivity.getString(R.string.fast) + ")");
|
||||
mCompressionNames.put(Id.choice.compression.zlib,
|
||||
"ZLIB (" + mActivity.getString(R.string.fast) + ")");
|
||||
mCompressionNames.put(Id.choice.compression.bzip2,
|
||||
"BZIP2 (" + mActivity.getString(R.string.very_slow) + ")");
|
||||
}
|
||||
|
||||
public HashMap<Integer, String> getEncryptionNames() {
|
||||
return mEncryptionNames;
|
||||
}
|
||||
|
||||
public void setEncryptionNames(HashMap<Integer, String> encryptionNames) {
|
||||
this.mEncryptionNames = encryptionNames;
|
||||
}
|
||||
|
||||
public HashMap<Integer, String> getHashNames() {
|
||||
return mHashNames;
|
||||
}
|
||||
|
||||
public void setHashNames(HashMap<Integer, String> hashNames) {
|
||||
this.mHashNames = hashNames;
|
||||
}
|
||||
|
||||
public HashMap<Integer, String> getCompressionNames() {
|
||||
return mCompressionNames;
|
||||
}
|
||||
|
||||
public void setCompressionNames(HashMap<Integer, String> compressionNames) {
|
||||
this.mCompressionNames = compressionNames;
|
||||
}
|
||||
|
||||
}
|
@ -179,8 +179,8 @@ public class HkpKeyServer extends KeyServer {
|
||||
KeyInfo info = new KeyInfo();
|
||||
info.size = Integer.parseInt(matcher.group(1));
|
||||
info.algorithm = matcher.group(2);
|
||||
info.keyId = PgpKeyHelper.keyFromHex(matcher.group(3));
|
||||
info.fingerPrint = PgpKeyHelper.getSmallFingerPrint(info.keyId);
|
||||
info.keyId = PgpKeyHelper.convertHexToKeyId(matcher.group(3));
|
||||
info.fingerPrint = PgpKeyHelper.convertKeyIdToHex(info.keyId);
|
||||
String chunks[] = matcher.group(4).split("-");
|
||||
info.date = new GregorianCalendar(Integer.parseInt(chunks[0]),
|
||||
Integer.parseInt(chunks[1]), Integer.parseInt(chunks[2])).getTime();
|
||||
@ -211,7 +211,7 @@ public class HkpKeyServer extends KeyServer {
|
||||
HttpClient client = new DefaultHttpClient();
|
||||
try {
|
||||
HttpGet get = new HttpGet("http://" + mHost + ":" + mPort
|
||||
+ "/pks/lookup?op=get&search=0x" + PgpKeyHelper.keyToHex(keyId));
|
||||
+ "/pks/lookup?op=get&search=0x" + PgpKeyHelper.convertKeyToHex(keyId));
|
||||
|
||||
HttpResponse response = client.execute(get);
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
@ -235,13 +235,13 @@ public class HkpKeyServer extends KeyServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String armouredText) throws AddKeyException {
|
||||
public void add(String armoredText) throws AddKeyException {
|
||||
HttpClient client = new DefaultHttpClient();
|
||||
try {
|
||||
HttpPost post = new HttpPost("http://" + mHost + ":" + mPort + "/pks/add");
|
||||
|
||||
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
|
||||
nameValuePairs.add(new BasicNameValuePair("keytext", armouredText));
|
||||
nameValuePairs.add(new BasicNameValuePair("keytext", armoredText));
|
||||
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
|
||||
|
||||
HttpResponse response = client.execute(post);
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
|
||||
private final HashMap<Integer, String> mData;
|
||||
private final int[] mKeys;
|
||||
private final String[] mValues;
|
||||
|
||||
static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>> entriesSortedByValues(
|
||||
Map<K, V> map) {
|
||||
SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(
|
||||
new Comparator<Map.Entry<K, V>>() {
|
||||
@Override
|
||||
public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
|
||||
return e1.getValue().compareTo(e2.getValue());
|
||||
}
|
||||
});
|
||||
sortedEntries.addAll(map.entrySet());
|
||||
return sortedEntries;
|
||||
}
|
||||
|
||||
public KeyValueSpinnerAdapter(Context context, HashMap<Integer, String> objects) {
|
||||
// To make the drop down a simple text box
|
||||
super(context, android.R.layout.simple_spinner_item);
|
||||
mData = objects;
|
||||
|
||||
// To make the drop down view a radio button list
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
SortedSet<Map.Entry<Integer, String>> sorted = entriesSortedByValues(objects);
|
||||
|
||||
// Assign hash keys with a position so that we can present and retrieve them
|
||||
int i = 0;
|
||||
mKeys = new int[mData.size()];
|
||||
mValues = new String[mData.size()];
|
||||
for (Map.Entry<Integer, String> entry : sorted) {
|
||||
mKeys[i] = entry.getKey();
|
||||
mValues[i] = entry.getValue();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value
|
||||
*/
|
||||
@Override
|
||||
public String getItem(int position) {
|
||||
// return the value based on the position. This is displayed in the list.
|
||||
return mValues[position];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns item key
|
||||
*/
|
||||
public long getItemId(int position) {
|
||||
// Return an id to represent the item.
|
||||
|
||||
return mKeys[position];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find position from key
|
||||
*/
|
||||
public int getPosition(long itemId) {
|
||||
for (int i = 0; i < mKeys.length; i++) {
|
||||
if ((int) itemId == mKeys[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user