treat missing keys (from 404 errors) individually during key import
This commit is contained in:
@@ -47,6 +47,14 @@ public abstract class Keyserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class QueryNotFoundException extends QueryFailedException {
|
||||||
|
private static final long serialVersionUID = 2693768928624654513L;
|
||||||
|
|
||||||
|
public QueryNotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class QueryNeedsRepairException extends CloudSearchFailureException {
|
public static class QueryNeedsRepairException extends CloudSearchFailureException {
|
||||||
private static final long serialVersionUID = 2693768928624654512L;
|
private static final long serialVersionUID = 2693768928624654512L;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -402,6 +402,9 @@ public class ParcelableHkpKeyserver extends Keyserver implements Parcelable {
|
|||||||
throw new Keyserver.QueryFailedException("Unsupported keyserver URI");
|
throw new Keyserver.QueryFailedException("Unsupported keyserver URI");
|
||||||
} catch (HttpError httpError) {
|
} catch (HttpError httpError) {
|
||||||
Log.d(Constants.TAG, "Failed to get key at HkpKeyserver", httpError);
|
Log.d(Constants.TAG, "Failed to get key at HkpKeyserver", httpError);
|
||||||
|
if (httpError.getCode() == 404) {
|
||||||
|
throw new Keyserver.QueryNotFoundException("not found");
|
||||||
|
}
|
||||||
throw new Keyserver.QueryFailedException("not found");
|
throw new Keyserver.QueryFailedException("not found");
|
||||||
}
|
}
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
import org.sufficientlysecure.keychain.keyimport.FacebookKeyserver;
|
import org.sufficientlysecure.keychain.keyimport.FacebookKeyserver;
|
||||||
import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
|
import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
|
||||||
import org.sufficientlysecure.keychain.keyimport.Keyserver;
|
import org.sufficientlysecure.keychain.keyimport.Keyserver;
|
||||||
|
import org.sufficientlysecure.keychain.keyimport.Keyserver.QueryNotFoundException;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||||
import org.sufficientlysecure.keychain.network.orbot.OrbotHelper;
|
import org.sufficientlysecure.keychain.network.orbot.OrbotHelper;
|
||||||
@@ -152,7 +153,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, log);
|
return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
int newKeys = 0, updatedKeys = 0, badKeys = 0, secret = 0;
|
int newKeys = 0, updatedKeys = 0, missingKeys = 0, badKeys = 0, secret = 0;
|
||||||
ArrayList<Long> importedMasterKeyIds = new ArrayList<>();
|
ArrayList<Long> importedMasterKeyIds = new ArrayList<>();
|
||||||
|
|
||||||
ArrayList<CanonicalizedKeyRing> canKeyRings = new ArrayList<>();
|
ArrayList<CanonicalizedKeyRing> canKeyRings = new ArrayList<>();
|
||||||
@@ -170,6 +171,8 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean keyWasDownloaded = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
UncachedKeyRing key = null;
|
UncachedKeyRing key = null;
|
||||||
@@ -178,7 +181,18 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
if (entry.mBytes != null) {
|
if (entry.mBytes != null) {
|
||||||
key = UncachedKeyRing.decodeFromData(entry.mBytes);
|
key = UncachedKeyRing.decodeFromData(entry.mBytes);
|
||||||
} else {
|
} else {
|
||||||
|
try {
|
||||||
key = fetchKeyFromInternet(hkpKeyserver, proxy, log, entry, key);
|
key = fetchKeyFromInternet(hkpKeyserver, proxy, log, entry, key);
|
||||||
|
} catch (QueryNotFoundException e) {
|
||||||
|
// note that this does NOT fire on network errors! those will be logged inline and return in null
|
||||||
|
log.add(LogType.MSG_IMPORT_FETCH_ERROR_NOT_FOUND, 2);
|
||||||
|
missingKeys += 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
keyWasDownloaded = true;
|
||||||
|
|
||||||
if (key.isSecret()) {
|
if (key.isSecret()) {
|
||||||
log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET, 2);
|
log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET, 2);
|
||||||
@@ -186,6 +200,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
log.add(LogType.MSG_IMPORT_FETCH_ERROR, 2);
|
log.add(LogType.MSG_IMPORT_FETCH_ERROR, 2);
|
||||||
@@ -266,6 +281,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
|
|
||||||
// special return case: no new keys at all
|
// special return case: no new keys at all
|
||||||
if (badKeys == 0 && newKeys == 0 && updatedKeys == 0) {
|
if (badKeys == 0 && newKeys == 0 && updatedKeys == 0) {
|
||||||
|
// if keys merely aren't on keyservers, it's just a warning
|
||||||
resultType = ImportKeyResult.RESULT_FAIL_NOTHING;
|
resultType = ImportKeyResult.RESULT_FAIL_NOTHING;
|
||||||
} else {
|
} else {
|
||||||
if (newKeys > 0) {
|
if (newKeys > 0) {
|
||||||
@@ -296,19 +312,28 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportKeyResult result = new ImportKeyResult(resultType, log, newKeys, updatedKeys, badKeys, secret,
|
ImportKeyResult result = new ImportKeyResult(
|
||||||
importedMasterKeyIdsArray);
|
resultType, log, newKeys, updatedKeys, missingKeys, badKeys, secret, importedMasterKeyIdsArray);
|
||||||
|
|
||||||
result.setCanonicalizedKeyRings(canKeyRings);
|
result.setCanonicalizedKeyRings(canKeyRings);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UncachedKeyRing fetchKeyFromInternet(ParcelableHkpKeyserver hkpKeyserver, @NonNull ParcelableProxy proxy,
|
private UncachedKeyRing fetchKeyFromInternet(ParcelableHkpKeyserver hkpKeyserver, @NonNull ParcelableProxy proxy,
|
||||||
OperationLog log, ParcelableKeyRing entry, UncachedKeyRing key) throws PgpGeneralException, IOException {
|
OperationLog log, ParcelableKeyRing entry, UncachedKeyRing key)
|
||||||
|
throws PgpGeneralException, IOException, QueryNotFoundException {
|
||||||
|
QueryNotFoundException queryNotFoundException = null;
|
||||||
|
|
||||||
boolean canFetchFromKeyservers =
|
boolean canFetchFromKeyservers =
|
||||||
hkpKeyserver != null && (entry.mKeyIdHex != null || entry.mExpectedFingerprint != null);
|
hkpKeyserver != null && (entry.mKeyIdHex != null || entry.mExpectedFingerprint != null);
|
||||||
if (canFetchFromKeyservers) {
|
if (canFetchFromKeyservers) {
|
||||||
UncachedKeyRing keyserverKey = fetchKeyFromKeyserver(hkpKeyserver, proxy, log, entry);
|
UncachedKeyRing keyserverKey = null;
|
||||||
|
try {
|
||||||
|
keyserverKey = fetchKeyFromKeyserver(hkpKeyserver, proxy, log, entry);
|
||||||
|
} catch (QueryNotFoundException e) {
|
||||||
|
queryNotFoundException = e;
|
||||||
|
}
|
||||||
|
|
||||||
if (keyserverKey != null) {
|
if (keyserverKey != null) {
|
||||||
key = keyserverKey;
|
key = keyserverKey;
|
||||||
}
|
}
|
||||||
@@ -329,12 +354,17 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
key = mergeKeysOrUseEither(log, 3, key, facebookKey);
|
key = mergeKeysOrUseEither(log, 3, key, facebookKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key == null && queryNotFoundException != null) {
|
||||||
|
throw queryNotFoundException;
|
||||||
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private UncachedKeyRing fetchKeyFromKeyserver(ParcelableHkpKeyserver hkpKeyserver, @NonNull ParcelableProxy proxy,
|
private UncachedKeyRing fetchKeyFromKeyserver(ParcelableHkpKeyserver hkpKeyserver, @NonNull ParcelableProxy proxy,
|
||||||
OperationLog log, ParcelableKeyRing entry) throws PgpGeneralException, IOException {
|
OperationLog log, ParcelableKeyRing entry) throws PgpGeneralException, IOException, Keyserver.QueryNotFoundException {
|
||||||
try {
|
try {
|
||||||
byte[] data;
|
byte[] data;
|
||||||
log.add(LogType.MSG_IMPORT_KEYSERVER, 1, hkpKeyserver);
|
log.add(LogType.MSG_IMPORT_KEYSERVER, 1, hkpKeyserver);
|
||||||
@@ -357,6 +387,8 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
return keyserverKey;
|
return keyserverKey;
|
||||||
|
} catch (Keyserver.QueryNotFoundException e) {
|
||||||
|
throw e;
|
||||||
} catch (Keyserver.QueryFailedException e) {
|
} catch (Keyserver.QueryFailedException e) {
|
||||||
Log.d(Constants.TAG, "query failed", e);
|
Log.d(Constants.TAG, "query failed", e);
|
||||||
log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
|
log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
|
||||||
@@ -473,7 +505,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
private ImportKeyResult multiThreadedKeyImport(ArrayList<ParcelableKeyRing> keyList,
|
private ImportKeyResult multiThreadedKeyImport(ArrayList<ParcelableKeyRing> keyList,
|
||||||
final ParcelableHkpKeyserver keyServer, final ParcelableProxy proxy,
|
final ParcelableHkpKeyserver keyServer, final ParcelableProxy proxy,
|
||||||
final boolean skipSave) {
|
final boolean skipSave) {
|
||||||
|
|
||||||
Log.d(Constants.TAG, "Multi-threaded key import starting");
|
Log.d(Constants.TAG, "Multi-threaded key import starting");
|
||||||
|
|
||||||
final Iterator<ParcelableKeyRing> keyListIterator = keyList.iterator();
|
final Iterator<ParcelableKeyRing> keyListIterator = keyList.iterator();
|
||||||
@@ -540,6 +571,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
private int mBadKeys = 0;
|
private int mBadKeys = 0;
|
||||||
private int mNewKeys = 0;
|
private int mNewKeys = 0;
|
||||||
private int mUpdatedKeys = 0;
|
private int mUpdatedKeys = 0;
|
||||||
|
private int mMissingKeys = 0;
|
||||||
private int mSecret = 0;
|
private int mSecret = 0;
|
||||||
private int mResultType = 0;
|
private int mResultType = 0;
|
||||||
private boolean mHasCancelledResult;
|
private boolean mHasCancelledResult;
|
||||||
@@ -586,6 +618,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
mBadKeys += result.mBadKeys;
|
mBadKeys += result.mBadKeys;
|
||||||
mNewKeys += result.mNewKeys;
|
mNewKeys += result.mNewKeys;
|
||||||
mUpdatedKeys += result.mUpdatedKeys;
|
mUpdatedKeys += result.mUpdatedKeys;
|
||||||
|
mMissingKeys += result.mMissingKeys;
|
||||||
mSecret += result.mSecret;
|
mSecret += result.mSecret;
|
||||||
|
|
||||||
long[] masterKeyIds = result.getImportedMasterKeyIds();
|
long[] masterKeyIds = result.getImportedMasterKeyIds();
|
||||||
@@ -635,7 +668,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImportKeyResult result = new ImportKeyResult(mResultType, mImportLog, mNewKeys,
|
ImportKeyResult result = new ImportKeyResult(mResultType, mImportLog, mNewKeys,
|
||||||
mUpdatedKeys, mBadKeys, mSecret, masterKeyIds);
|
mUpdatedKeys, mMissingKeys, mBadKeys, mSecret, masterKeyIds);
|
||||||
|
|
||||||
result.setCanonicalizedKeyRings(mCanonicalizedKeyRings);
|
result.setCanonicalizedKeyRings(mCanonicalizedKeyRings);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.operations.results;
|
package org.sufficientlysecure.keychain.operations.results;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@@ -33,11 +36,9 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
|
|||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Showable;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Showable;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class ImportKeyResult extends InputPendingResult {
|
public class ImportKeyResult extends InputPendingResult {
|
||||||
|
|
||||||
public final int mNewKeys, mUpdatedKeys, mBadKeys, mSecret;
|
public final int mNewKeys, mUpdatedKeys, mMissingKeys, mBadKeys, mSecret;
|
||||||
public final long[] mImportedMasterKeyIds;
|
public final long[] mImportedMasterKeyIds;
|
||||||
|
|
||||||
// NOT PARCELED
|
// NOT PARCELED
|
||||||
@@ -74,6 +75,10 @@ public class ImportKeyResult extends InputPendingResult {
|
|||||||
return (mResult & RESULT_FAIL_NOTHING) == RESULT_FAIL_NOTHING;
|
return (mResult & RESULT_FAIL_NOTHING) == RESULT_FAIL_NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFailMissing() {
|
||||||
|
return isFailNothing() && mMissingKeys > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long[] getImportedMasterKeyIds() {
|
public long[] getImportedMasterKeyIds() {
|
||||||
return mImportedMasterKeyIds;
|
return mImportedMasterKeyIds;
|
||||||
}
|
}
|
||||||
@@ -82,21 +87,23 @@ public class ImportKeyResult extends InputPendingResult {
|
|||||||
super(source);
|
super(source);
|
||||||
mNewKeys = source.readInt();
|
mNewKeys = source.readInt();
|
||||||
mUpdatedKeys = source.readInt();
|
mUpdatedKeys = source.readInt();
|
||||||
|
mMissingKeys = source.readInt();
|
||||||
mBadKeys = source.readInt();
|
mBadKeys = source.readInt();
|
||||||
mSecret = source.readInt();
|
mSecret = source.readInt();
|
||||||
mImportedMasterKeyIds = source.createLongArray();
|
mImportedMasterKeyIds = source.createLongArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImportKeyResult(int result, OperationLog log) {
|
public ImportKeyResult(int result, OperationLog log) {
|
||||||
this(result, log, 0, 0, 0, 0, new long[]{});
|
this(result, log, 0, 0, 0, 0, 0, new long[]{});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImportKeyResult(int result, OperationLog log,
|
public ImportKeyResult(int result, OperationLog log,
|
||||||
int newKeys, int updatedKeys, int badKeys, int secret,
|
int newKeys, int updatedKeys, int missingKeys, int badKeys, int secret,
|
||||||
long[] importedMasterKeyIds) {
|
long[] importedMasterKeyIds) {
|
||||||
super(result, log);
|
super(result, log);
|
||||||
mNewKeys = newKeys;
|
mNewKeys = newKeys;
|
||||||
mUpdatedKeys = updatedKeys;
|
mUpdatedKeys = updatedKeys;
|
||||||
|
mMissingKeys = missingKeys;
|
||||||
mBadKeys = badKeys;
|
mBadKeys = badKeys;
|
||||||
mSecret = secret;
|
mSecret = secret;
|
||||||
mImportedMasterKeyIds = importedMasterKeyIds;
|
mImportedMasterKeyIds = importedMasterKeyIds;
|
||||||
@@ -108,6 +115,7 @@ public class ImportKeyResult extends InputPendingResult {
|
|||||||
// just assign default values, we won't use them anyway
|
// just assign default values, we won't use them anyway
|
||||||
mNewKeys = 0;
|
mNewKeys = 0;
|
||||||
mUpdatedKeys = 0;
|
mUpdatedKeys = 0;
|
||||||
|
mMissingKeys = 0;
|
||||||
mBadKeys = 0;
|
mBadKeys = 0;
|
||||||
mSecret = 0;
|
mSecret = 0;
|
||||||
mImportedMasterKeyIds = new long[]{};
|
mImportedMasterKeyIds = new long[]{};
|
||||||
@@ -122,6 +130,7 @@ public class ImportKeyResult extends InputPendingResult {
|
|||||||
super.writeToParcel(dest, flags);
|
super.writeToParcel(dest, flags);
|
||||||
dest.writeInt(mNewKeys);
|
dest.writeInt(mNewKeys);
|
||||||
dest.writeInt(mUpdatedKeys);
|
dest.writeInt(mUpdatedKeys);
|
||||||
|
dest.writeInt(mMissingKeys);
|
||||||
dest.writeInt(mBadKeys);
|
dest.writeInt(mBadKeys);
|
||||||
dest.writeInt(mSecret);
|
dest.writeInt(mSecret);
|
||||||
dest.writeLongArray(mImportedMasterKeyIds);
|
dest.writeLongArray(mImportedMasterKeyIds);
|
||||||
@@ -190,17 +199,20 @@ public class ImportKeyResult extends InputPendingResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (isFailMissing()) {
|
||||||
|
duration = 0;
|
||||||
|
style = Style.WARN;
|
||||||
|
str = activity.getResources().getString(R.string.import_warn_missing);
|
||||||
|
} else if (isFailNothing()) {
|
||||||
duration = 0;
|
duration = 0;
|
||||||
style = Style.ERROR;
|
style = Style.ERROR;
|
||||||
if (isFailNothing()) {
|
|
||||||
str = activity.getString((resultType & ImportKeyResult.RESULT_CANCELLED) > 0
|
str = activity.getString((resultType & ImportKeyResult.RESULT_CANCELLED) > 0
|
||||||
? R.string.import_error_nothing_cancelled
|
? R.string.import_error_nothing_cancelled
|
||||||
: R.string.import_error_nothing);
|
: R.string.import_error_nothing);
|
||||||
} else {
|
} else {
|
||||||
str = activity.getResources().getQuantityString(
|
duration = 0;
|
||||||
R.plurals.import_error,
|
style = Style.ERROR;
|
||||||
mBadKeys,
|
str = activity.getResources().getQuantityString(R.plurals.import_error, mBadKeys, mBadKeys);
|
||||||
mBadKeys);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -769,6 +769,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
|
|
||||||
MSG_IMPORT_FETCH_ERROR (LogLevel.ERROR, R.string.msg_import_fetch_error),
|
MSG_IMPORT_FETCH_ERROR (LogLevel.ERROR, R.string.msg_import_fetch_error),
|
||||||
MSG_IMPORT_FETCH_ERROR_DECODE (LogLevel.ERROR, R.string.msg_import_fetch_error_decode),
|
MSG_IMPORT_FETCH_ERROR_DECODE (LogLevel.ERROR, R.string.msg_import_fetch_error_decode),
|
||||||
|
MSG_IMPORT_FETCH_ERROR_NOT_FOUND (LogLevel.ERROR, R.string.msg_import_fetch_error_not_found),
|
||||||
MSG_IMPORT_FETCH_ERROR_KEYSERVER(LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver),
|
MSG_IMPORT_FETCH_ERROR_KEYSERVER(LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver),
|
||||||
MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET (LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver_secret),
|
MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET (LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver_secret),
|
||||||
MSG_IMPORT_FETCH_KEYBASE (LogLevel.INFO, R.string.msg_import_fetch_keybase),
|
MSG_IMPORT_FETCH_KEYBASE (LogLevel.INFO, R.string.msg_import_fetch_keybase),
|
||||||
|
|||||||
@@ -585,6 +585,7 @@
|
|||||||
<item quantity="one">"Import failed!"</item>
|
<item quantity="one">"Import failed!"</item>
|
||||||
<item quantity="other">"Import of %d keys failed!"</item>
|
<item quantity="other">"Import of %d keys failed!"</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="import_warn_missing">"Key not found on keyservers."</string>
|
||||||
<string name="import_error_nothing">"Nothing to import."</string>
|
<string name="import_error_nothing">"Nothing to import."</string>
|
||||||
<string name="import_error_nothing_cancelled">"Import cancelled."</string>
|
<string name="import_error_nothing_cancelled">"Import cancelled."</string>
|
||||||
|
|
||||||
@@ -1337,6 +1338,7 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="msg_import_fetch_error_decode">"Error decoding retrieved keyring!"</string>
|
<string name="msg_import_fetch_error_decode">"Error decoding retrieved keyring!"</string>
|
||||||
<string name="msg_import_fetch_error">"Key could not be retrieved! (Network problems?)"</string>
|
<string name="msg_import_fetch_error">"Key could not be retrieved! (Network problems?)"</string>
|
||||||
|
<string name="msg_import_fetch_error_not_found">"Key not found!"</string>
|
||||||
<string name="msg_import_fetch_error_keyserver">"Could not retrieve key from keyservers: %s"</string>
|
<string name="msg_import_fetch_error_keyserver">"Could not retrieve key from keyservers: %s"</string>
|
||||||
<string name="msg_import_fetch_error_keyserver_secret">"Cannot import secret key from keyserver!"</string>
|
<string name="msg_import_fetch_error_keyserver_secret">"Cannot import secret key from keyserver!"</string>
|
||||||
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
|
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user