Fix many problems with import from files

This commit is contained in:
Dominik Schürmann 2013-01-08 19:19:45 +01:00
parent 6fd44a0ec5
commit 55530597df
6 changed files with 98 additions and 70 deletions

View File

@ -155,6 +155,7 @@
<string name="notValid">not valid</string> <string name="notValid">not valid</string>
<string name="nKeyServers">%s key server(s)</string> <string name="nKeyServers">%s key server(s)</string>
<string name="fingerprint">Fingerprint:</string> <string name="fingerprint">Fingerprint:</string>
<string name="secretKeyring">Secret Keyring:</string>
<!-- choice_lowerCase: capitalized first word, no punctuation --> <!-- choice_lowerCase: capitalized first word, no punctuation -->
<string name="choice_none">None</string> <string name="choice_none">None</string>

View File

@ -137,16 +137,4 @@ public class PGPConversionHelper {
} }
} }
public static PGPKeyRing decodeKeyRing(InputStream is) throws IOException {
InputStream in = PGPUtil.getDecoderStream(is);
PGPObjectFactory objectFactory = new PGPObjectFactory(in);
Object obj = objectFactory.nextObject();
if (obj instanceof PGPKeyRing) {
return (PGPKeyRing) obj;
}
return null;
}
} }

View File

@ -45,6 +45,7 @@ import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData; import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRingCollection;
import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignature;
@ -475,6 +476,13 @@ public class PGPMain {
updateProgress(progress, R.string.progress_done, 100, 100); updateProgress(progress, R.string.progress_done, 100, 100);
} }
/**
* TODO: implement Id.return_value.updated as status when key already existed
*
* @param context
* @param keyring
* @return
*/
public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) { public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) {
int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*) int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
try { try {
@ -543,21 +551,14 @@ public class PGPMain {
PGPException, IOException { PGPException, IOException {
Bundle returnData = new Bundle(); Bundle returnData = new Bundle();
// if (type == Id.type.secret_key) {
// if (progress != null)
updateProgress(progress, R.string.progress_importingSecretKeys, 0, 100); updateProgress(progress, R.string.progress_importingSecretKeys, 0, 100);
// progress.setProgress(R.string.progress_importingSecretKeys, 0, 100);
// } else {
// if (progress != null)
// progress.setProgress(R.string.progress_importingPublicKeys, 0, 100);
// }
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new ApgGeneralException(context.getString(R.string.error_externalStorageNotReady)); throw new ApgGeneralException(context.getString(R.string.error_externalStorageNotReady));
} }
PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream()); PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream());
// need to have access to the bufferedInput, so we can reuse it for the possible // 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 // PGPObject chunks after the first one, e.g. files with several consecutive ASCII
// armour blocks // armour blocks
@ -566,35 +567,47 @@ public class PGPMain {
int oldKeys = 0; int oldKeys = 0;
int badKeys = 0; int badKeys = 0;
try { try {
PGPKeyRing keyring = PGPConversionHelper.decodeKeyRing(bufferedInput);
while (keyring != null) {
int status = Integer.MIN_VALUE; // out of bounds value
// if this key is what we expect it to be, save it // read all available blocks... (asc files can contain many blocks with BEGIN END)
// if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing) while (bufferedInput.available() > 0) {
// || (type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) { InputStream in = PGPUtil.getDecoderStream(bufferedInput);
status = storeKeyRingInCache(context, keyring); PGPObjectFactory objectFactory = new PGPObjectFactory(in);
// }
if (status == Id.return_value.error) { // go through all objects in this block
throw new ApgGeneralException(context.getString(R.string.error_savingKeys)); Object obj;
while ((obj = objectFactory.nextObject()) != null) {
Log.d(Constants.TAG, "Found class: " + obj.getClass());
if (obj instanceof PGPKeyRing) {
PGPKeyRing keyring = (PGPKeyRing) obj;
int status = Integer.MIN_VALUE; // out of bounds value
status = storeKeyRingInCache(context, keyring);
if (status == Id.return_value.error) {
throw new ApgGeneralException(
context.getString(R.string.error_savingKeys));
}
// update the counts to display to the user at the end
if (status == Id.return_value.updated) {
++oldKeys;
} else if (status == Id.return_value.ok) {
++newKeys;
} else if (status == Id.return_value.bad) {
++badKeys;
}
updateProgress(progress,
(int) (100 * progressIn.position() / data.getSize()), 100);
} else {
Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!");
}
} }
// update the counts to display to the user at the end
if (status == Id.return_value.updated) {
++oldKeys;
} else if (status == Id.return_value.ok) {
++newKeys;
} else if (status == Id.return_value.bad) {
++badKeys;
}
updateProgress(progress, (int) (100 * progressIn.position() / data.getSize()), 100);
keyring = PGPConversionHelper.decodeKeyRing(bufferedInput);
} }
} catch (EOFException e) { } catch (Exception e) {
// nothing to do, we are done Log.e(Constants.TAG, "Exception on parsing key file!", e);
} }
returnData.putInt(ApgIntentService.RESULT_IMPORT_ADDED, newKeys); returnData.putInt(ApgIntentService.RESULT_IMPORT_ADDED, newKeys);
@ -658,7 +671,6 @@ public class PGPMain {
if (secretKeyRing != null) { if (secretKeyRing != null) {
secretKeyRing.encode(outSec); secretKeyRing.encode(outSec);
} }
++numKeys;
} }
outSec.close(); outSec.close();
} }

View File

@ -212,13 +212,12 @@ public class ImportKeysActivity extends SherlockFragmentActivity {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
if (message.what == FileDialogFragment.MESSAGE_OKAY) { if (message.what == FileDialogFragment.MESSAGE_OKAY) {
Log.d(Constants.TAG, "FileDialogFragment.MESSAGE_OKAY");
Bundle data = message.getData(); Bundle data = message.getData();
mImportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); mImportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
mDeleteAfterImport = data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED);
Log.d(Constants.TAG, "mImportFilename: " + mImportFilename); Log.d(Constants.TAG, "mImportFilename: " + mImportFilename);
Log.d(Constants.TAG, "mDeleteAfterImport: " + mDeleteAfterImport);
mDeleteAfterImport = data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED);
loadKeyListFragment(); loadKeyListFragment();
} }

View File

@ -127,8 +127,6 @@ public class FileDialogFragment extends DialogFragment {
@Override @Override
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
Log.d(Constants.TAG, "onclock");
dismiss(); dismiss();
boolean checked = false; boolean checked = false;

View File

@ -20,12 +20,20 @@ import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRingCollection;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSecretKeyRingCollection;
import org.spongycastle.openpgp.PGPUtil;
import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.PGPConversionHelper; import org.thialfihar.android.apg.helper.PGPConversionHelper;
@ -46,6 +54,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
public static final String MAP_ATTR_USER_ID = "user_id"; public static final String MAP_ATTR_USER_ID = "user_id";
public static final String MAP_ATTR_FINGERPINT = "fingerprint"; public static final String MAP_ATTR_FINGERPINT = "fingerprint";
ArrayList<Map<String, String>> data = new ArrayList<Map<String, String>>();
Context mContext; Context mContext;
List<String> mItems; List<String> mItems;
@ -73,7 +83,9 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
} }
} }
return generateListOfKeyrings(inputData); generateListOfKeyrings(inputData);
return data;
} }
@Override @Override
@ -105,36 +117,54 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
* @param keyringBytes * @param keyringBytes
* @return * @return
*/ */
private ArrayList<Map<String, String>> generateListOfKeyrings(InputData inputData) { private void generateListOfKeyrings(InputData inputData) {
ArrayList<Map<String, String>> output = new ArrayList<Map<String, String>>();
PositionAwareInputStream progressIn = new PositionAwareInputStream( PositionAwareInputStream progressIn = new PositionAwareInputStream(
inputData.getInputStream()); inputData.getInputStream());
// need to have access to the bufferedInput, so we can reuse it for the possible // 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 // PGPObject chunks after the first one, e.g. files with several consecutive ASCII
// armour blocks // armour blocks
BufferedInputStream bufferedInput = new BufferedInputStream(progressIn); BufferedInputStream bufferedInput = new BufferedInputStream(progressIn);
try { try {
PGPKeyRing keyring = PGPConversionHelper.decodeKeyRing(bufferedInput);
while (keyring != null) {
String userId = PGPHelper.getMainUserId(keyring.getPublicKey());
String fingerprint = PGPHelper.convertFingerprintToHex(keyring.getPublicKey() // read all available blocks... (asc files can contain many blocks with BEGIN END)
.getFingerprint()); while (bufferedInput.available() > 0) {
InputStream in = PGPUtil.getDecoderStream(bufferedInput);
PGPObjectFactory objectFactory = new PGPObjectFactory(in);
Map<String, String> attrs = new HashMap<String, String>(); // go through all objects in this block
attrs.put(MAP_ATTR_USER_ID, userId); Object obj;
attrs.put(MAP_ATTR_FINGERPINT, mContext.getString(R.string.fingerprint) + "\n" while ((obj = objectFactory.nextObject()) != null) {
+ fingerprint); Log.d(Constants.TAG, "Found class: " + obj.getClass());
output.add(attrs);
keyring = PGPConversionHelper.decodeKeyRing(bufferedInput); if (obj instanceof PGPKeyRing) {
PGPKeyRing newKeyring = (PGPKeyRing) obj;
addToData(newKeyring);
} else {
Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!");
}
}
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(Constants.TAG, "Exception", e); Log.e(Constants.TAG, "Exception on parsing key file!", e);
}
}
private void addToData(PGPKeyRing keyring) {
String userId = PGPHelper.getMainUserId(keyring.getPublicKey());
if (keyring instanceof PGPSecretKeyRing) {
userId = mContext.getString(R.string.secretKeyring) + " " + userId;
} }
return output; String fingerprint = PGPHelper.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);
} }
} }