diff options
author | mar-v-in <github@rvin.mooo.com> | 2014-07-01 00:15:30 +0200 |
---|---|---|
committer | mar-v-in <github@rvin.mooo.com> | 2014-07-01 00:15:30 +0200 |
commit | d1d414c006aa6b7b80b25b34f0c75a92a9603a85 (patch) | |
tree | 6375bd8a5436c866824190318d10d183d8548ab6 /OpenKeychain/src | |
parent | 38823b73a31ae0fb82d7e385c141f1170127c4dd (diff) | |
parent | a9010045889d307ede37d154b0a2fece566c1845 (diff) | |
download | open-keychain-d1d414c006aa6b7b80b25b34f0c75a92a9603a85.tar.gz open-keychain-d1d414c006aa6b7b80b25b34f0c75a92a9603a85.tar.bz2 open-keychain-d1d414c006aa6b7b80b25b34f0c75a92a9603a85.zip |
Merge branch 'master' into improve-file-more
Conflicts:
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
Diffstat (limited to 'OpenKeychain/src')
112 files changed, 2177 insertions, 620 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index c6e528f4d..3ce200008 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -59,6 +59,7 @@ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> + <uses-permission android:name="android.permission.READ_PROFILE" /> <!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! --> <application @@ -80,6 +81,11 @@ </intent-filter> </activity> <activity + android:name=".ui.WizardActivity" + android:configChanges="orientation|screenSize|keyboardHidden|keyboard" + android:label="@string/title_wizard" + android:windowSoftInputMode="stateHidden" /> + <activity android:name=".ui.EditKeyActivity" android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:label="@string/title_edit_key" diff --git a/OpenKeychain/src/main/assets/fontawesome-webfont.ttf b/OpenKeychain/src/main/assets/fontawesome-webfont.ttf Binary files differdeleted file mode 100644 index 7ec2e1de8..000000000 --- a/OpenKeychain/src/main/assets/fontawesome-webfont.ttf +++ /dev/null diff --git a/OpenKeychain/src/main/assets/sks-keyservers.netCA.cer b/OpenKeychain/src/main/assets/sks-keyservers.netCA.cer new file mode 100644 index 000000000..24a2ad2e8 --- /dev/null +++ b/OpenKeychain/src/main/assets/sks-keyservers.netCA.cer @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u +ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw +MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP +c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr +cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I +6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj +MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F +45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS +FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx +Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4 +aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx +MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y +u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9 +p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP +fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G +A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY +TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR +OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u +gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/ +X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5 +gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB +UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04 +lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT +BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB +cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U +f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G +ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph +WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg== +-----END CERTIFICATE----- diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 8074ad2ee..eeb9fa389 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -68,10 +68,12 @@ public final class Constants { public static final String LANGUAGE = "language"; public static final String FORCE_V3_SIGNATURES = "forceV3Signatures"; public static final String KEY_SERVERS = "keyServers"; + public static final String KEY_SERVERS_DEFAULT_VERSION = "keyServersDefaultVersion"; } public static final class Defaults { - public static final String KEY_SERVERS = "pool.sks-keyservers.net, subkeys.pgp.net, pgp.mit.edu"; + public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, subkeys.pgp.net, hkps://pgp.mit.edu"; + public static final int KEY_SERVERS_VERSION = 2; } public static final class DrawerItems { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index d28c4d63c..be9c1e405 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -26,6 +26,8 @@ import android.graphics.drawable.Drawable; import android.os.Environment; import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.helper.TlsHelper; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PRNGFixes; @@ -78,6 +80,11 @@ public class KeychainApplication extends Application { getApplicationContext().getResources().getColor(R.color.emphasis)); setupAccountAsNeeded(this); + + // Update keyserver list as needed + Preferences.getPreferences(this).updateKeyServers(); + + TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer"); } public static void setupAccountAsNeeded(Context context) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index d8a7e8427..e639824ec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -22,8 +22,10 @@ import android.accounts.AccountManager; import android.content.*; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.provider.ContactsContract; import android.util.Patterns; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; @@ -58,7 +60,27 @@ public class ContactHelper { ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?"; public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?"; - public static List<String> getMailAccounts(Context context) { + public static List<String> getPossibleUserEmails(Context context) { + Set<String> accountMails = getAccountEmails(context); + accountMails.addAll(getMainProfileContactEmails(context)); + // now return the Set (without duplicates) as a List + return new ArrayList<String>(accountMails); + } + + public static List<String> getPossibleUserNames(Context context) { + Set<String> accountMails = getAccountEmails(context); + Set<String> names = getContactNamesFromEmails(context, accountMails); + names.addAll(getMainProfileContactName(context)); + return new ArrayList<String>(names); + } + + /** + * Get emails from AccountManager + * + * @param context + * @return + */ + private static Set<String> getAccountEmails(Context context) { final Account[] accounts = AccountManager.get(context).getAccounts(); final Set<String> emailSet = new HashSet<String>(); for (Account account : accounts) { @@ -66,7 +88,118 @@ public class ContactHelper { emailSet.add(account.name); } } - return new ArrayList<String>(emailSet); + return emailSet; + } + + /** + * Search for contact names based on a list of emails (to find out the names of the + * device owner based on the email addresses from AccountsManager) + * + * @param context + * @param emails + * @return + */ + private static Set<String> getContactNamesFromEmails(Context context, Set<String> emails) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + Set<String> names = new HashSet<String>(); + for (String email : emails) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query( + ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.Contacts.DISPLAY_NAME}, + ContactsContract.CommonDataKinds.Email.ADDRESS + "=?", + new String[]{email}, null + ); + if (profileCursor == null) return null; + + Set<String> currNames = new HashSet<String>(); + while (profileCursor.moveToNext()) { + String name = profileCursor.getString(1); + Log.d(Constants.TAG, "name" + name); + if (name != null) { + currNames.add(name); + } + } + profileCursor.close(); + names.addAll(currNames); + } + return names; + } else { + return new HashSet<String>(); + } + } + + /** + * Retrieves the emails of the primary profile contact + * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html + * + * @param context + * @return + */ + private static Set<String> getMainProfileContactEmails(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query( + Uri.withAppendedPath( + ContactsContract.Profile.CONTENT_URI, + ContactsContract.Contacts.Data.CONTENT_DIRECTORY), + new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.CommonDataKinds.Email.IS_PRIMARY}, + + // Selects only email addresses + ContactsContract.Contacts.Data.MIMETYPE + "=?", + new String[]{ + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, + }, + // Show primary rows first. Note that there won't be a primary email address if the + // user hasn't specified one. + ContactsContract.Contacts.Data.IS_PRIMARY + " DESC" + ); + if (profileCursor == null) return null; + + Set<String> emails = new HashSet<String>(); + while (profileCursor.moveToNext()) { + String email = profileCursor.getString(0); + if (email != null) { + emails.add(email); + } + } + profileCursor.close(); + return emails; + } else { + return new HashSet<String>(); + } + } + + /** + * Retrieves the name of the primary profile contact + * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html + * + * @param context + * @return + */ + private static List<String> getMainProfileContactName(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI, + new String[]{ContactsContract.Profile.DISPLAY_NAME}, + null, null, null); + if (profileCursor == null) return null; + + Set<String> names = new HashSet<String>(); + // should only contain one entry! + while (profileCursor.moveToNext()) { + String name = profileCursor.getString(0); + if (name != null) { + names.add(name); + } + } + profileCursor.close(); + return new ArrayList<String>(names); + } else { + return new ArrayList<String>(); + } } public static List<String> getContactMails(Context context) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index c82c5e115..6f3d38ccd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -169,4 +169,22 @@ public class Preferences { editor.putString(Constants.Pref.KEY_SERVERS, rawData); editor.commit(); } + + public void updateKeyServers() { + if (mSharedPreferences.getInt(Constants.Pref.KEY_SERVERS_DEFAULT_VERSION, 0) != + Constants.Defaults.KEY_SERVERS_VERSION) { + String[] servers = getKeyServers(); + for (int i = 0; i < servers.length; i++) { + if (servers[i].equals("pool.sks-keyservers.net")) { + servers[i] = "hkps://hkps.pool.sks-keyservers.net"; + } else if (servers[i].equals("pgp.mit.edu")) { + servers[i] = "hkps://pgp.mit.edu"; + } + } + setKeyServers(servers); + mSharedPreferences.edit() + .putInt(Constants.Pref.KEY_SERVERS_DEFAULT_VERSION, Constants.Defaults.KEY_SERVERS_VERSION) + .commit(); + } + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java new file mode 100644 index 000000000..4b09af04d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2013-2014 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.helper; + +import android.content.res.AssetManager; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.*; +import java.util.HashMap; +import java.util.Map; + +public class TlsHelper { + + public static class TlsHelperException extends Exception { + public TlsHelperException(Exception e) { + super(e); + } + } + + private static Map<String, byte[]> sStaticCA = new HashMap<String, byte[]>(); + + public static void addStaticCA(String domain, byte[] certificate) { + sStaticCA.put(domain, certificate); + } + + public static void addStaticCA(String domain, AssetManager assetManager, String name) { + try { + InputStream is = assetManager.open(name); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int reads = is.read(); + + while(reads != -1){ + baos.write(reads); + reads = is.read(); + } + + is.close(); + + addStaticCA(domain, baos.toByteArray()); + } catch (IOException e) { + Log.w(Constants.TAG, e); + } + } + + public static URLConnection openConnection(URL url) throws IOException, TlsHelperException { + if (url.getProtocol().equals("https")) { + for (String domain : sStaticCA.keySet()) { + if (url.getHost().endsWith(domain)) { + return openCAConnection(sStaticCA.get(domain), url); + } + } + } + return url.openConnection(); + } + + /** + * Opens a Connection that will only accept certificates signed with a specific CA and skips common name check. + * This is required for some distributed Keyserver networks like sks-keyservers.net + * + * @param certificate The X.509 certificate used to sign the servers certificate + * @param url Connection target + */ + public static HttpsURLConnection openCAConnection(byte[] certificate, URL url) + throws TlsHelperException, IOException { + try { + // Load CA + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate ca = cf.generateCertificate(new ByteArrayInputStream(certificate)); + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry("ca", ca); + + // Create a TrustManager that trusts the CAs in our KeyStore + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init(keyStore); + + // Create an SSLContext that uses our TrustManager + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, tmf.getTrustManagers(), null); + + // Tell the URLConnection to use a SocketFactory from our SSLContext + HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(context.getSocketFactory()); + + return urlConnection; + } catch (CertificateException e) { + throw new TlsHelperException(e); + } catch (NoSuchAlgorithmException e) { + throw new TlsHelperException(e); + } catch (KeyStoreException e) { + throw new TlsHelperException(e); + } catch (KeyManagementException e) { + throw new TlsHelperException(e); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index e49085a0e..44679ba18 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -22,37 +22,23 @@ import de.measite.minidns.Client; import de.measite.minidns.Question; import de.measite.minidns.Record; import de.measite.minidns.record.SRV; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.helper.TlsHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.util.Log; +import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.GregorianCalendar; -import java.util.List; import java.util.Locale; import java.util.TimeZone; import java.util.regex.Matcher; @@ -200,48 +186,37 @@ public class HkpKeyserver extends Keyserver { return mSecure ? "https://" : "http://"; } - private String query(String request) throws QueryFailedException, HttpError { - List<String> urls = new ArrayList<String>(); - if (mSecure) { - urls.add(getUrlPrefix() + mHost + ":" + mPort + request); - } else { - InetAddress ips[]; - try { - ips = InetAddress.getAllByName(mHost); - } catch (UnknownHostException e) { - throw new QueryFailedException(e.toString()); - } - for (InetAddress ip : ips) { - // Note: This is actually not HTTP 1.1 compliant, as we hide the real "Host" value, - // but Android's HTTPUrlConnection does not support any other way to set - // Socket's remote IP address... - urls.add(getUrlPrefix() + ip.getHostAddress() + ":" + mPort + request); - } + private HttpURLConnection openConnection(URL url) throws IOException { + HttpURLConnection conn = null; + try { + conn = (HttpURLConnection) TlsHelper.openConnection(url); + } catch (TlsHelper.TlsHelperException e) { + Log.w(Constants.TAG, e); + } + if (conn == null) { + conn = (HttpURLConnection) url.openConnection(); } + conn.setConnectTimeout(5000); + conn.setReadTimeout(25000); + return conn; + } - for (String url : urls) { - try { - Log.d(Constants.TAG, "hkp keyserver query: " + url); - URL realUrl = new URL(url); - HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); - conn.setConnectTimeout(5000); - conn.setReadTimeout(25000); - conn.connect(); - int response = conn.getResponseCode(); - if (response >= 200 && response < 300) { - return readAll(conn.getInputStream(), conn.getContentEncoding()); - } else { - String data = readAll(conn.getErrorStream(), conn.getContentEncoding()); - throw new HttpError(response, data); - } - } catch (MalformedURLException e) { - // nothing to do, try next IP - } catch (IOException e) { - // nothing to do, try next IP + private String query(String request) throws QueryFailedException, HttpError { + try { + URL url = new URL(getUrlPrefix() + mHost + ":" + mPort + request); + Log.d(Constants.TAG, "hkp keyserver query: " + url); + HttpURLConnection conn = openConnection(url); + conn.connect(); + int response = conn.getResponseCode(); + if (response >= 200 && response < 300) { + return readAll(conn.getInputStream(), conn.getContentEncoding()); + } else { + String data = readAll(conn.getErrorStream(), conn.getContentEncoding()); + throw new HttpError(response, data); } + } catch (IOException e) { + throw new QueryFailedException("querying server(s) for '" + mHost + "' failed"); } - - throw new QueryFailedException("querying server(s) for '" + mHost + "' failed"); } @Override @@ -341,52 +316,44 @@ public class HkpKeyserver extends Keyserver { @Override public String get(String keyIdHex) throws QueryFailedException { - HttpClient client = new DefaultHttpClient(); + String request = "/pks/lookup?op=get&options=mr&search=" + keyIdHex; + Log.d(Constants.TAG, "hkp keyserver get: " + request); + String data; try { - String query = getUrlPrefix() + mHost + ":" + mPort + - "/pks/lookup?op=get&options=mr&search=" + keyIdHex; - Log.d(Constants.TAG, "hkp keyserver get: " + query); - HttpGet get = new HttpGet(query); - HttpResponse response = client.execute(get); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new QueryFailedException("not found"); - } - - HttpEntity entity = response.getEntity(); - InputStream is = entity.getContent(); - String data = readAll(is, EntityUtils.getContentCharSet(entity)); - Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data); - if (matcher.find()) { - return matcher.group(1); - } - } catch (IOException e) { - // nothing to do, better luck on the next keyserver - } finally { - client.getConnectionManager().shutdown(); + data = query(request); + } catch (HttpError httpError) { + throw new QueryFailedException("not found"); + } + Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data); + if (matcher.find()) { + return matcher.group(1); } - return null; } @Override public void add(String armoredKey) throws AddKeyException { - HttpClient client = new DefaultHttpClient(); try { String query = getUrlPrefix() + mHost + ":" + mPort + "/pks/add"; - HttpPost post = new HttpPost(query); - Log.d(Constants.TAG, "hkp keyserver add: " + query); - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); - nameValuePairs.add(new BasicNameValuePair("keytext", armoredKey)); - post.setEntity(new UrlEncodedFormEntity(nameValuePairs)); - - HttpResponse response = client.execute(post); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + String params; + try { + params = "keytext=" + URLEncoder.encode(armoredKey, "utf8"); + } catch (UnsupportedEncodingException e) { throw new AddKeyException(); } + Log.d(Constants.TAG, "hkp keyserver add: " + query); + + HttpURLConnection connection = openConnection(new URL(query)); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.setRequestProperty("Content-Length", Integer.toString(params.getBytes().length)); + connection.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); + wr.writeBytes(params); + wr.flush(); + wr.close(); } catch (IOException e) { - // nothing to do, better luck on the next keyserver - } finally { - client.getConnectionManager().shutdown(); + throw new AddKeyException(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java index c50d92f7a..6fc55cfb8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -123,11 +123,16 @@ public class PgpImportExport { } /** Imports keys from given data. If keyIds is given only those are imported */ - public ImportResult importKeyRings(List<ParcelableKeyRing> entries) - throws PgpGeneralException, PGPException, IOException { + public ImportResult importKeyRings(List<ParcelableKeyRing> entries) { updateProgress(R.string.progress_importing, 0, 100); + // If there aren't even any keys, do nothing here. + if (entries == null || entries.size() == 0) { + return new ImportResult( + ImportResult.RESULT_FAIL_NOTHING, mProviderHelper.getLog(), 0, 0, 0); + } + int newKeys = 0, oldKeys = 0, badKeys = 0; int position = 0; @@ -165,6 +170,9 @@ public class PgpImportExport { newKeys += 1; } + } catch (IOException e) { + Log.e(Constants.TAG, "Encountered bad key on import!", e); + ++badKeys; } catch (PgpGeneralException e) { Log.e(Constants.TAG, "Encountered bad key on import!", e); ++badKeys; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 9b3e5bc54..1b59e7cc0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -33,7 +33,6 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor; @@ -51,7 +50,6 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Primes; import java.io.IOException; @@ -65,7 +63,6 @@ import java.security.SignatureException; import java.util.Arrays; import java.util.Calendar; import java.util.Date; -import java.util.List; import java.util.TimeZone; /** @@ -268,18 +265,18 @@ public class PgpKeyOperation { // 4a. For each subkey change, generate new subkey binding certificate for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) { log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE, - new String[]{PgpKeyHelper.convertKeyIdToHex(change.mKeyId)}, indent); + indent, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId); if (sKey == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING, - new String[]{PgpKeyHelper.convertKeyIdToHex(change.mKeyId)}, indent + 1); + indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); return null; } PGPPublicKey pKey = sKey.getPublicKey(); if (change.mExpiry != null && new Date(change.mExpiry).before(new Date())) { log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_PAST_EXPIRY, - new String[]{PgpKeyHelper.convertKeyIdToHex(change.mKeyId)}, indent + 1); + indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); return null; } @@ -293,11 +290,11 @@ public class PgpKeyOperation { // 4b. For each subkey revocation, generate new subkey revocation certificate for (long revocation : saveParcel.revokeSubKeys) { log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_REVOKE, - new String[] { PgpKeyHelper.convertKeyIdToHex(revocation) }, indent); + indent, PgpKeyHelper.convertKeyIdToHex(revocation)); PGPSecretKey sKey = sKR.getSecretKey(revocation); if (sKey == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING, - new String[] { PgpKeyHelper.convertKeyIdToHex(revocation) }, indent+1); + indent+1, PgpKeyHelper.convertKeyIdToHex(revocation)); return null; } PGPPublicKey pKey = sKey.getPublicKey(); @@ -321,7 +318,7 @@ public class PgpKeyOperation { log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent); PGPSecretKey sKey = createKey(add.mAlgorithm, add.mKeysize, passphrase, false); log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID, - new String[] { PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID()) }, indent+1); + indent+1, PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); PGPPublicKey pKey = sKey.getPublicKey(); PGPSignature cert = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 371202217..441e2762a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -207,7 +207,7 @@ public class UncachedKeyRing { public UncachedKeyRing canonicalize(OperationLog log, int indent) { log.add(LogLevel.START, isSecret() ? LogType.MSG_KC_SECRET : LogType.MSG_KC_PUBLIC, - new String[]{PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())}, indent); + indent, PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())); indent += 1; final Date now = new Date(); @@ -220,7 +220,7 @@ public class UncachedKeyRing { { log.add(LogLevel.DEBUG, LogType.MSG_KC_MASTER, - new String[]{PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())}, indent); + indent, PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())); indent += 1; PGPPublicKey modified = masterKey; @@ -240,9 +240,7 @@ public class UncachedKeyRing { if (type != PGPSignature.KEY_REVOCATION) { // Unknown type, just remove - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TYPE, new String[]{ - "0x" + Integer.toString(type, 16) - }, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TYPE, indent, "0x" + Integer.toString(type, 16)); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; @@ -250,7 +248,7 @@ public class UncachedKeyRing { if (cert.getCreationTime().after(now)) { // Creation date in the future? No way! - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TIME, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TIME, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; @@ -258,7 +256,7 @@ public class UncachedKeyRing { if (cert.isLocal()) { // Creation date in the future? No way! - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_LOCAL, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_LOCAL, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; @@ -267,13 +265,13 @@ public class UncachedKeyRing { try { cert.init(masterKey); if (!cert.verifySignature(masterKey)) { - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; } } catch (PgpGeneralException e) { - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_ERR, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_ERR, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; @@ -286,12 +284,12 @@ public class UncachedKeyRing { } else if (revocation.getCreationTime().before(zert.getCreationTime())) { modified = PGPPublicKey.removeCertification(modified, revocation); redundantCerts += 1; - log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, null, indent); + log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, indent); revocation = zert; } else { modified = PGPPublicKey.removeCertification(modified, zert); redundantCerts += 1; - log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, null, indent); + log.add(LogLevel.INFO, LogType.MSG_KC_REVOKE_DUP, indent); } } @@ -312,16 +310,14 @@ public class UncachedKeyRing { && type != PGPSignature.POSITIVE_CERTIFICATION && type != PGPSignature.CERTIFICATION_REVOCATION) { log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_TYPE, - new String[] { - "0x" + Integer.toString(zert.getSignatureType(), 16) - }, indent); + indent, "0x" + Integer.toString(zert.getSignatureType(), 16)); modified = PGPPublicKey.removeCertification(modified, userId, zert); badCerts += 1; } if (cert.getCreationTime().after(now)) { // Creation date in the future? No way! - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TIME, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TIME, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; @@ -329,7 +325,7 @@ public class UncachedKeyRing { if (cert.isLocal()) { // Creation date in the future? No way! - log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_LOCAL, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_LOCAL, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; continue; @@ -340,7 +336,7 @@ public class UncachedKeyRing { // never mind any further for public keys, but remove them from secret ones if (isSecret()) { log.add(LogLevel.WARN, LogType.MSG_KC_UID_FOREIGN, - new String[] { PgpKeyHelper.convertKeyIdToHex(certId) }, indent); + indent, PgpKeyHelper.convertKeyIdToHex(certId)); modified = PGPPublicKey.removeCertification(modified, userId, zert); badCerts += 1; } @@ -352,14 +348,14 @@ public class UncachedKeyRing { cert.init(masterKey); if (!cert.verifySignature(masterKey, userId)) { log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD, - new String[] { userId }, indent); + indent, userId); modified = PGPPublicKey.removeCertification(modified, userId, zert); badCerts += 1; continue; } } catch (PgpGeneralException e) { log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_ERR, - new String[] { userId }, indent); + indent, userId); modified = PGPPublicKey.removeCertification(modified, userId, zert); badCerts += 1; continue; @@ -376,13 +372,13 @@ public class UncachedKeyRing { modified = PGPPublicKey.removeCertification(modified, userId, selfCert); redundantCerts += 1; log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_DUP, - new String[] { userId }, indent); + indent, userId); selfCert = zert; } else { modified = PGPPublicKey.removeCertification(modified, userId, zert); redundantCerts += 1; log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_DUP, - new String[] { userId }, indent); + indent, userId); } // If there is a revocation certificate, and it's older than this, drop it if (revocation != null @@ -391,7 +387,7 @@ public class UncachedKeyRing { revocation = null; redundantCerts += 1; log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD, - new String[] { userId }, indent); + indent, userId); } break; @@ -401,7 +397,7 @@ public class UncachedKeyRing { modified = PGPPublicKey.removeCertification(modified, userId, zert); redundantCerts += 1; log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD, - new String[] { userId }, indent); + indent, userId); continue; } // first revocation? remember it. @@ -412,13 +408,13 @@ public class UncachedKeyRing { modified = PGPPublicKey.removeCertification(modified, userId, revocation); redundantCerts += 1; log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_DUP, - new String[] { userId }, indent); + indent, userId); revocation = zert; } else { modified = PGPPublicKey.removeCertification(modified, userId, zert); redundantCerts += 1; log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_DUP, - new String[] { userId }, indent); + indent, userId); } break; @@ -430,13 +426,13 @@ public class UncachedKeyRing { if (selfCert == null && revocation == null) { modified = PGPPublicKey.removeCertification(modified, userId); log.add(LogLevel.ERROR, LogType.MSG_KC_UID_REVOKE_DUP, - new String[] { userId }, indent); + indent, userId); } } // If NO user ids remain, error out! if (!modified.getUserIDs().hasNext()) { - log.add(LogLevel.ERROR, LogType.MSG_KC_FATAL_NO_UID, null, indent); + log.add(LogLevel.ERROR, LogType.MSG_KC_FATAL_NO_UID, indent); return null; } @@ -453,7 +449,7 @@ public class UncachedKeyRing { continue; } log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB, - new String[]{PgpKeyHelper.convertKeyIdToHex(key.getKeyID())}, indent); + indent, PgpKeyHelper.convertKeyIdToHex(key.getKeyID())); indent += 1; // A subkey needs exactly one subkey binding certificate, and optionally one revocation // certificate. @@ -468,29 +464,27 @@ public class UncachedKeyRing { // filter out bad key types... if (cert.getKeyId() != masterKey.getKeyID()) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_KEYID, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_KEYID, indent); badCerts += 1; continue; } if (type != PGPSignature.SUBKEY_BINDING && type != PGPSignature.SUBKEY_REVOCATION) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TYPE, new String[]{ - "0x" + Integer.toString(type, 16) - }, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TYPE, indent, "0x" + Integer.toString(type, 16)); badCerts += 1; continue; } if (cert.getCreationTime().after(now)) { // Creation date in the future? No way! - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TIME, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TIME, indent); badCerts += 1; continue; } if (cert.isLocal()) { // Creation date in the future? No way! - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_LOCAL, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_LOCAL, indent); badCerts += 1; continue; } @@ -501,12 +495,12 @@ public class UncachedKeyRing { try { cert.init(masterKey); if (!cert.verifySignature(masterKey, key)) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD, indent); badCerts += 1; continue; } } catch (PgpGeneralException e) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_ERR, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_ERR, indent); badCerts += 1; continue; } @@ -526,19 +520,19 @@ public class UncachedKeyRing { if (subsig.verifySignature(masterKey, key)) { ok = true; } else { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_PRIMARY_BAD, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_PRIMARY_BAD, indent); badCerts += 1; continue uids; } } } if (!ok) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_PRIMARY_NONE, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_PRIMARY_NONE, indent); badCerts += 1; continue; } } catch (Exception e) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_PRIMARY_BAD_ERR, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_PRIMARY_BAD_ERR, indent); badCerts += 1; continue; } @@ -565,12 +559,12 @@ public class UncachedKeyRing { try { cert.init(masterKey); if (!cert.verifySignature(key)) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_REVOKE_BAD, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_REVOKE_BAD, indent); badCerts += 1; continue; } } catch (PgpGeneralException e) { - log.add(LogLevel.WARN, LogType.MSG_KC_SUB_REVOKE_BAD_ERR, null, indent); + log.add(LogLevel.WARN, LogType.MSG_KC_SUB_REVOKE_BAD_ERR, indent); badCerts += 1; continue; } @@ -591,7 +585,7 @@ public class UncachedKeyRing { ring = replacePublicKey(ring, modified); log.add(LogLevel.ERROR, LogType.MSG_KC_SUB_NO_CERT, - new String[]{ PgpKeyHelper.convertKeyIdToHex(key.getKeyID()) }, indent); + indent, PgpKeyHelper.convertKeyIdToHex(key.getKeyID())); indent -= 1; continue; } @@ -608,17 +602,17 @@ public class UncachedKeyRing { } if (badCerts > 0 && redundantCerts > 0) { + // multi plural would make this complex, just leaving this as is... log.add(LogLevel.OK, LogType.MSG_KC_SUCCESS_BAD_AND_RED, - new String[] { Integer.toString(badCerts), - Integer.toString(redundantCerts) }, indent); + indent, Integer.toString(badCerts), Integer.toString(redundantCerts)); } else if (badCerts > 0) { log.add(LogLevel.OK, LogType.MSG_KC_SUCCESS_BAD, - new String[] { Integer.toString(badCerts) }, indent); + indent, badCerts); } else if (redundantCerts > 0) { log.add(LogLevel.OK, LogType.MSG_KC_SUCCESS_REDUNDANT, - new String[] { Integer.toString(redundantCerts) }, indent); + indent, redundantCerts); } else { - log.add(LogLevel.OK, LogType.MSG_KC_SUCCESS, null, indent); + log.add(LogLevel.OK, LogType.MSG_KC_SUCCESS, indent); } return new UncachedKeyRing(ring, true); @@ -638,13 +632,13 @@ public class UncachedKeyRing { public UncachedKeyRing merge(UncachedKeyRing other, OperationLog log, int indent) { log.add(LogLevel.DEBUG, isSecret() ? LogType.MSG_MG_SECRET : LogType.MSG_MG_PUBLIC, - new String[]{ PgpKeyHelper.convertKeyIdToHex(getMasterKeyId()) }, indent); + indent, PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())); indent += 1; long masterKeyId = other.getMasterKeyId(); if (getMasterKeyId() != masterKeyId) { - log.add(LogLevel.ERROR, LogType.MSG_MG_HETEROGENEOUS, null, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_HETEROGENEOUS, indent); return null; } @@ -683,7 +677,7 @@ public class UncachedKeyRing { final PGPPublicKey resultKey = result.getPublicKey(key.getKeyID()); if (resultKey == null) { - log.add(LogLevel.DEBUG, LogType.MSG_MG_NEW_SUBKEY, null, indent); + log.add(LogLevel.DEBUG, LogType.MSG_MG_NEW_SUBKEY, indent); result = replacePublicKey(result, key); continue; } @@ -751,12 +745,12 @@ public class UncachedKeyRing { } log.add(LogLevel.DEBUG, LogType.MSG_MG_FOUND_NEW, - new String[] { Integer.toString(newCerts) }, indent); + indent, Integer.toString(newCerts)); return new UncachedKeyRing(result); } catch (IOException e) { - log.add(LogLevel.ERROR, LogType.MSG_MG_FATAL_ENCODE, null, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_FATAL_ENCODE, indent); return null; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index ceaa93f9b..7a63ec3d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -165,10 +165,10 @@ public class KeychainDatabase extends SQLiteOpenHelper { // make sure this is only done once, on the first instance! boolean iAmIt = false; - synchronized(apgHack) { - if(!apgHack) { + synchronized(KeychainDatabase.class) { + if(!KeychainDatabase.apgHack) { iAmIt = true; - apgHack = true; + KeychainDatabase.apgHack = true; } } // if it's us, do the import @@ -206,6 +206,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { try { db.execSQL("ALTER TABLE keys ADD COLUMN has_secret BOOLEAN"); } catch (Exception e) { + // never mind, the column probably already existed } } } @@ -261,8 +262,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { cursor = db.rawQuery("SELECT key_ring_data FROM key_rings WHERE type = 1 OR EXISTS (" + " SELECT 1 FROM key_rings d2 WHERE key_rings.master_key_id = d2.master_key_id" + " AND d2.type = 1) ORDER BY type ASC", null); - Log.d(Constants.TAG, "Importing " + cursor.getCount() + " secret keyrings from apg.db..."); if (cursor != null) { + Log.d(Constants.TAG, "Importing " + cursor.getCount() + " secret keyrings from apg.db..."); for (int i = 0; i < cursor.getCount(); i++) { cursor.moveToPosition(i); byte[] data = cursor.getBlob(0); @@ -285,8 +286,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { + " SELECT 1 FROM key_rings d2 WHERE key_rings.master_key_id = d2.master_key_id AND" + " d2.type = 1)) DESC, type DESC", null); // import from old database - Log.d(Constants.TAG, "Importing " + cursor.getCount() + " keyrings from apg.db..."); if (cursor != null) { + Log.d(Constants.TAG, "Importing " + cursor.getCount() + " keyrings from apg.db..."); for (int i = 0; i < cursor.getCount(); i++) { cursor.moveToPosition(i); byte[] data = cursor.getBlob(0); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index f4e19d21a..28495d51d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -116,12 +116,12 @@ public class ProviderHelper { public void log(LogLevel level, LogType type) { if(mLog != null) { - mLog.add(level, type, null, mIndent); + mLog.add(level, type, mIndent); } } - public void log(LogLevel level, LogType type, String[] parameters) { + public void log(LogLevel level, LogType type, Object... parameters) { if(mLog != null) { - mLog.add(level, type, parameters, mIndent); + mLog.add(level, type, mIndent, parameters); } } @@ -320,9 +320,9 @@ public class ProviderHelper { int rank = 0; for (UncachedPublicKey key : new IterableIterator<UncachedPublicKey>(keyRing.getPublicKeys())) { long keyId = key.getKeyId(); - log(LogLevel.DEBUG, keyId == masterKeyId ? LogType.MSG_IP_MASTER : LogType.MSG_IP_SUBKEY, new String[]{ + log(LogLevel.DEBUG, keyId == masterKeyId ? LogType.MSG_IP_MASTER : LogType.MSG_IP_SUBKEY, PgpKeyHelper.convertKeyIdToHex(keyId) - }); + ); mIndent += 1; ContentValues values = new ContentValues(); @@ -343,36 +343,36 @@ public class ProviderHelper { if (c) { if (e) { log(LogLevel.DEBUG, s ? LogType.MSG_IP_MASTER_FLAGS_CES - : LogType.MSG_IP_MASTER_FLAGS_CEX, null); + : LogType.MSG_IP_MASTER_FLAGS_CEX); } else { log(LogLevel.DEBUG, s ? LogType.MSG_IP_MASTER_FLAGS_CXS - : LogType.MSG_IP_MASTER_FLAGS_CXX, null); + : LogType.MSG_IP_MASTER_FLAGS_CXX); } } else { if (e) { log(LogLevel.DEBUG, s ? LogType.MSG_IP_MASTER_FLAGS_XES - : LogType.MSG_IP_MASTER_FLAGS_XEX, null); + : LogType.MSG_IP_MASTER_FLAGS_XEX); } else { log(LogLevel.DEBUG, s ? LogType.MSG_IP_MASTER_FLAGS_XXS - : LogType.MSG_IP_MASTER_FLAGS_XXX, null); + : LogType.MSG_IP_MASTER_FLAGS_XXX); } } } else { if (c) { if (e) { log(LogLevel.DEBUG, s ? LogType.MSG_IP_SUBKEY_FLAGS_CES - : LogType.MSG_IP_SUBKEY_FLAGS_CEX, null); + : LogType.MSG_IP_SUBKEY_FLAGS_CEX); } else { log(LogLevel.DEBUG, s ? LogType.MSG_IP_SUBKEY_FLAGS_CXS - : LogType.MSG_IP_SUBKEY_FLAGS_CXX, null); + : LogType.MSG_IP_SUBKEY_FLAGS_CXX); } } else { if (e) { log(LogLevel.DEBUG, s ? LogType.MSG_IP_SUBKEY_FLAGS_XES - : LogType.MSG_IP_SUBKEY_FLAGS_XEX, null); + : LogType.MSG_IP_SUBKEY_FLAGS_XEX); } else { log(LogLevel.DEBUG, s ? LogType.MSG_IP_SUBKEY_FLAGS_XXS - : LogType.MSG_IP_SUBKEY_FLAGS_XXX, null); + : LogType.MSG_IP_SUBKEY_FLAGS_XXX); } } } @@ -385,11 +385,11 @@ public class ProviderHelper { if (key.isExpired()) { log(LogLevel.DEBUG, keyId == masterKeyId ? LogType.MSG_IP_MASTER_EXPIRED : LogType.MSG_IP_SUBKEY_EXPIRED, - new String[]{ expiryDate.toString() }); + expiryDate.toString()); } else { log(LogLevel.DEBUG, keyId == masterKeyId ? LogType.MSG_IP_MASTER_EXPIRES : LogType.MSG_IP_SUBKEY_EXPIRES, - new String[] { expiryDate.toString() }); + expiryDate.toString()); } } @@ -405,9 +405,7 @@ public class ProviderHelper { // classify and order user ids. primary are moved to the front, revoked to the back, // otherwise the order in the keyfile is preserved. - log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING, new String[]{ - Integer.toString(trustedKeys.size()) - }); + log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size()); mIndent += 1; List<UserIdItem> uids = new ArrayList<UserIdItem>(); for (String userId : new IterableIterator<String>( @@ -418,7 +416,7 @@ public class ProviderHelper { int unknownCerts = 0; - log(LogLevel.INFO, LogType.MSG_IP_UID_PROCESSING, new String[]{ userId }); + log(LogLevel.INFO, LogType.MSG_IP_UID_PROCESSING, userId); mIndent += 1; // look through signatures for this specific key for (WrappedSignature cert : new IterableIterator<WrappedSignature>( @@ -447,10 +445,10 @@ public class ProviderHelper { cert.init(trustedKey); if (cert.verifySignature(masterKey, userId)) { item.trustedCerts.add(cert); - log(LogLevel.INFO, LogType.MSG_IP_UID_CERT_GOOD, new String[] { + log(LogLevel.INFO, LogType.MSG_IP_UID_CERT_GOOD, PgpKeyHelper.convertKeyIdToHexShort(trustedKey.getKeyId()), trustedKey.getPrimaryUserId() - }); + ); } else { log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_BAD); } @@ -459,16 +457,13 @@ public class ProviderHelper { unknownCerts += 1; } catch (PgpGeneralException e) { - log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_ERROR, new String[]{ - PgpKeyHelper.convertKeyIdToHex(cert.getKeyId()) - }); + log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_ERROR, + PgpKeyHelper.convertKeyIdToHex(cert.getKeyId())); } } if (unknownCerts > 0) { - log(LogLevel.DEBUG, LogType.MSG_IP_UID_CERTS_UNKNOWN, new String[]{ - Integer.toString(unknownCerts) - }); + log(LogLevel.DEBUG, LogType.MSG_IP_UID_CERTS_UNKNOWN, unknownCerts); } mIndent -= 1; @@ -574,8 +569,7 @@ public class ProviderHelper { } long masterKeyId = keyRing.getMasterKeyId(); - log(LogLevel.START, LogType.MSG_IS, - new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) }); + log(LogLevel.START, LogType.MSG_IS, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; try { @@ -625,18 +619,18 @@ public class ProviderHelper { int upd = mContentResolver.update(uri, values, Keys.KEY_ID + " = ?", new String[]{Long.toString(id)}); if (upd == 1) { - log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_OK, new String[]{ + log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_OK, PgpKeyHelper.convertKeyIdToHex(id) - }); + ); } else { - log(LogLevel.WARN, LogType.MSG_IS_SUBKEY_NONEXISTENT, new String[]{ + log(LogLevel.WARN, LogType.MSG_IS_SUBKEY_NONEXISTENT, PgpKeyHelper.convertKeyIdToHex(id) - }); + ); } } else { - log(LogLevel.INFO, LogType.MSG_IS_SUBKEY_STRIPPED, new String[]{ + log(LogLevel.INFO, LogType.MSG_IS_SUBKEY_STRIPPED, PgpKeyHelper.convertKeyIdToHex(id) - }); + ); } } mIndent -= 1; @@ -654,8 +648,6 @@ public class ProviderHelper { } - - @Deprecated public SaveKeyringResult savePublicKeyRing(UncachedKeyRing keyRing) { return savePublicKeyRing(keyRing, new NullProgressable()); } @@ -669,8 +661,7 @@ public class ProviderHelper { try { long masterKeyId = publicRing.getMasterKeyId(); - log(LogLevel.START, LogType.MSG_IP, - new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) }); + log(LogLevel.START, LogType.MSG_IP, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; // If there is an old keyring, merge it @@ -694,8 +685,8 @@ public class ProviderHelper { // Early breakout if nothing changed if (Arrays.hashCode(publicRing.getEncoded()) == Arrays.hashCode(oldPublicRing.getEncoded())) { - log(LogLevel.OK, LogType.MSG_IP_SUCCESS_IDENTICAL, null); - return new SaveKeyringResult(SaveKeyringResult.RESULT_OK, mLog); + log(LogLevel.OK, LogType.MSG_IP_SUCCESS_IDENTICAL); + return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog); } } catch (NotFoundException e) { // Not an issue, just means we are dealing with a new keyring. @@ -754,8 +745,7 @@ public class ProviderHelper { try { long masterKeyId = secretRing.getMasterKeyId(); - log(LogLevel.START, LogType.MSG_IS, - new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) }); + log(LogLevel.START, LogType.MSG_IS, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; // If there is an old secret key, merge it. @@ -780,8 +770,8 @@ public class ProviderHelper { if (Arrays.hashCode(secretRing.getEncoded()) == Arrays.hashCode(oldSecretRing.getEncoded())) { log(LogLevel.OK, LogType.MSG_IS_SUCCESS_IDENTICAL, - new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) }); - return new SaveKeyringResult(SaveKeyringResult.RESULT_OK, mLog); + PgpKeyHelper.convertKeyIdToHex(masterKeyId) ); + return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog); } } catch (NotFoundException e) { // Not an issue, just means we are dealing with a new keyring @@ -812,7 +802,7 @@ public class ProviderHelper { } } catch (NotFoundException e) { - log(LogLevel.DEBUG, LogType.MSG_IS_PUBRING_GENERATE, null); + log(LogLevel.DEBUG, LogType.MSG_IS_PUBRING_GENERATE); publicRing = secretRing.extractPublicKeyRing(); } @@ -833,7 +823,7 @@ public class ProviderHelper { return new SaveKeyringResult(result, mLog); } catch (IOException e) { - log(LogLevel.ERROR, LogType.MSG_IS_FAIL_IO_EXC, null); + log(LogLevel.ERROR, LogType.MSG_IS_FAIL_IO_EXC); return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); } finally { mIndent -= 1; @@ -842,21 +832,6 @@ public class ProviderHelper { } /** - * Saves (or updates) a pair of public and secret KeyRings in the database - */ - @Deprecated // scheduled for deletion after merge with new-edit branch - public void savePairedKeyRing(UncachedKeyRing pubRing, UncachedKeyRing secRing) throws IOException { - long masterKeyId = pubRing.getMasterKeyId(); - - // delete secret keyring (so it isn't unnecessarily saved by public-savePublicKeyRing below) - mContentResolver.delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null); - - // save public keyring - internalSavePublicKeyRing(pubRing, null, true); - internalSaveSecretKeyRing(secRing); - } - - /** * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing */ private ContentProviderOperation diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java index cb58f8734..e49c11e08 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java @@ -28,8 +28,7 @@ import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Spinner; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.Button; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -57,7 +56,7 @@ public class AccountSettingsFragment extends Fragment implements private Spinner mCompression; private SelectSecretKeyLayoutFragment mSelectKeyFragment; - private BootstrapButton mCreateKeyButton; + private Button mCreateKeyButton; KeyValueSpinnerAdapter mEncryptionAdapter; KeyValueSpinnerAdapter mHashAdapter; @@ -107,7 +106,7 @@ public class AccountSettingsFragment extends Fragment implements .findViewById(R.id.api_account_settings_encryption_algorithm); mHashAlgorithm = (Spinner) view.findViewById(R.id.api_account_settings_hash_algorithm); mCompression = (Spinner) view.findViewById(R.id.api_account_settings_compression); - mCreateKeyButton = (BootstrapButton) view.findViewById(R.id.api_account_settings_create_key); + mCreateKeyButton = (Button) view.findViewById(R.id.api_account_settings_create_key); mCreateKeyButton.setOnClickListener(new View.OnClickListener() { @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index f88df5301..7f91ab490 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -59,23 +59,23 @@ public class OperationResultParcel implements Parcelable { public static class LogEntryParcel implements Parcelable { public final LogLevel mLevel; public final LogType mType; - public final String[] mParameters; + public final Object[] mParameters; public final int mIndent; - public LogEntryParcel(LogLevel level, LogType type, String[] parameters, int indent) { + public LogEntryParcel(LogLevel level, LogType type, int indent, Object... parameters) { mLevel = level; mType = type; mParameters = parameters; mIndent = indent; } - public LogEntryParcel(LogLevel level, LogType type, String[] parameters) { - this(level, type, parameters, 0); + public LogEntryParcel(LogLevel level, LogType type, Object... parameters) { + this(level, type, 0, parameters); } public LogEntryParcel(Parcel source) { mLevel = LogLevel.values()[source.readInt()]; mType = LogType.values()[source.readInt()]; - mParameters = source.createStringArray(); + mParameters = (Object[]) source.readSerializable(); mIndent = source.readInt(); } @@ -88,7 +88,7 @@ public class OperationResultParcel implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mLevel.ordinal()); dest.writeInt(mType.ordinal()); - dest.writeStringArray(mParameters); + dest.writeSerializable(mParameters); dest.writeInt(mIndent); } @@ -164,8 +164,8 @@ public class OperationResultParcel implements Parcelable { MSG_IP_UID_CERT_BAD (R.string.msg_ip_uid_cert_bad), MSG_IP_UID_CERT_ERROR (R.string.msg_ip_uid_cert_error), MSG_IP_UID_CERT_GOOD (R.string.msg_ip_uid_cert_good), - MSG_IP_UID_CERTS_UNKNOWN (R.string.msg_ip_uid_certs_unknown), - MSG_IP_UID_CLASSIFYING (R.string.msg_ip_uid_classifying), + MSG_IP_UID_CERTS_UNKNOWN (R.plurals.msg_ip_uid_certs_unknown), + MSG_IP_UID_CLASSIFYING (R.plurals.msg_ip_uid_classifying), MSG_IP_UID_REORDER(R.string.msg_ip_uid_reorder), MSG_IP_UID_PROCESSING (R.string.msg_ip_uid_processing), MSG_IP_UID_REVOKED (R.string.msg_ip_uid_revoked), @@ -209,9 +209,9 @@ public class OperationResultParcel implements Parcelable { MSG_KC_SUB_REVOKE_BAD_ERR (R.string.msg_kc_sub_revoke_bad_err), MSG_KC_SUB_REVOKE_BAD (R.string.msg_kc_sub_revoke_bad), MSG_KC_SUB_REVOKE_DUP (R.string.msg_kc_sub_revoke_dup), - MSG_KC_SUCCESS_BAD (R.string.msg_kc_success_bad), + MSG_KC_SUCCESS_BAD (R.plurals.msg_kc_success_bad), MSG_KC_SUCCESS_BAD_AND_RED (R.string.msg_kc_success_bad_and_red), - MSG_KC_SUCCESS_REDUNDANT (R.string.msg_kc_success_redundant), + MSG_KC_SUCCESS_REDUNDANT (R.plurals.msg_kc_success_redundant), MSG_KC_SUCCESS (R.string.msg_kc_success), MSG_KC_UID_BAD_ERR (R.string.msg_kc_uid_bad_err), MSG_KC_UID_BAD_LOCAL (R.string.msg_kc_uid_bad_local), @@ -296,13 +296,13 @@ public class OperationResultParcel implements Parcelable { public static class OperationLog extends ArrayList<LogEntryParcel> { /// Simple convenience method - public void add(LogLevel level, LogType type, String[] parameters, int indent) { + public void add(LogLevel level, LogType type, int indent, Object... parameters) { Log.d(Constants.TAG, type.toString()); - add(new OperationResultParcel.LogEntryParcel(level, type, parameters, indent)); + add(new OperationResultParcel.LogEntryParcel(level, type, indent, parameters)); } public void add(LogLevel level, LogType type, int indent) { - add(new OperationResultParcel.LogEntryParcel(level, type, null, indent)); + add(new OperationResultParcel.LogEntryParcel(level, type, indent, (Object[]) null)); } public boolean containsWarnings() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 6c44b01f1..fd3d4ed00 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -1,6 +1,19 @@ package org.sufficientlysecure.keychain.service; +import android.app.Activity; +import android.content.Intent; import android.os.Parcel; +import android.os.Parcelable; +import android.view.View; + +import com.github.johnpersano.supertoasts.SuperCardToast; +import com.github.johnpersano.supertoasts.SuperToast; +import com.github.johnpersano.supertoasts.util.OnClickWrapper; +import com.github.johnpersano.supertoasts.util.Style; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.LogDisplayActivity; +import org.sufficientlysecure.keychain.ui.LogDisplayFragment; public abstract class OperationResults { @@ -67,6 +80,87 @@ public abstract class OperationResults { } }; + public void displayNotify(final Activity activity) { + + int resultType = getResult(); + + String str; + int duration, color; + + // Not an overall failure + if ((resultType & ImportResult.RESULT_ERROR) == 0) { + String withWarnings; + + // Any warnings? + if ((resultType & ImportResult.RESULT_WITH_WARNINGS) > 0) { + duration = 0; + color = Style.ORANGE; + withWarnings = activity.getResources().getString(R.string.import_with_warnings); + } else { + duration = SuperToast.Duration.LONG; + color = Style.GREEN; + withWarnings = ""; + } + + // New and updated keys + if (this.isOkBoth()) { + str = activity.getResources().getQuantityString( + R.plurals.import_keys_added_and_updated_1, mNewKeys, mNewKeys); + str += activity.getResources().getQuantityString( + R.plurals.import_keys_added_and_updated_2, mUpdatedKeys, mUpdatedKeys, withWarnings); + } else if (isOkUpdated()) { + str = activity.getResources().getQuantityString( + R.plurals.import_keys_updated, mUpdatedKeys, mUpdatedKeys, withWarnings); + } else if (isOkNew()) { + str = activity.getResources().getQuantityString( + R.plurals.import_keys_added, mNewKeys, mNewKeys, withWarnings); + } else { + duration = 0; + color = Style.RED; + str = "internal error"; + } + + } else { + duration = 0; + color = Style.RED; + if (isFailNothing()) { + str = activity.getString(R.string.import_error_nothing); + } else { + str = activity.getString(R.string.import_error); + } + } + + // TODO: externalize into Notify class? + boolean button = getLog() != null && !getLog().isEmpty(); + SuperCardToast toast = new SuperCardToast(activity, + button ? SuperToast.Type.BUTTON : SuperToast.Type.STANDARD, + Style.getStyle(color, SuperToast.Animations.POPUP)); + toast.setText(str); + toast.setDuration(duration); + toast.setIndeterminate(duration == 0); + toast.setSwipeToDismiss(true); + // If we have a log and it's non-empty, show a View Log button + if (button) { + toast.setButtonIcon(R.drawable.ic_action_view_as_list, + activity.getResources().getString(R.string.import_view_log)); + toast.setButtonTextColor(activity.getResources().getColor(R.color.black)); + toast.setTextColor(activity.getResources().getColor(R.color.black)); + toast.setOnClickWrapper(new OnClickWrapper("supercardtoast", + new SuperToast.OnClickListener() { + @Override + public void onClick(View view, Parcelable token) { + Intent intent = new Intent( + activity, LogDisplayActivity.class); + intent.putExtra(LogDisplayFragment.EXTRA_RESULT, ImportResult.this); + activity.startActivity(intent); + } + } + )); + } + toast.show(); + + } + } public static class SaveKeyringResult extends OperationResultParcel { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/KeyringTestingHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/KeyringTestingHelper.java index d4bc6c541..a565f0707 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/KeyringTestingHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/KeyringTestingHelper.java @@ -5,9 +5,10 @@ import android.content.Context; import org.sufficientlysecure.keychain.pgp.NullProgressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.service.OperationResults; +import java.util.Collection; + /** * Helper for tests of the Keyring import in ProviderHelper. */ @@ -19,13 +20,11 @@ public class KeyringTestingHelper { this.context = robolectricContext; } - public boolean addKeyring() throws Exception { + public boolean addKeyring(Collection<String> blobFiles) throws Exception { ProviderHelper providerHelper = new ProviderHelper(context); -// providerHelper.insertApiApp(new AppSettings("robo-test-package", new byte[]{5, 4, 3, 2, 1})); - - byte[] data = TestDataUtil.readFully(getClass().getResourceAsStream("/public-key-for-sample.blob")); + byte[] data = TestDataUtil.readAllFully(blobFiles); UncachedKeyRing ring = UncachedKeyRing.decodeFromData(data); long masterKeyId = ring.getMasterKeyId(); @@ -45,6 +44,7 @@ public class KeyringTestingHelper { return saveSuccess; } + private void retrieveKeyAndExpectNotFound(ProviderHelper providerHelper, long masterKeyId) { try { providerHelper.getWrappedPublicKeyRing(masterKeyId); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/TestDataUtil.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/TestDataUtil.java index 06dc08eab..9e6ede761 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/TestDataUtil.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/testsupport/TestDataUtil.java @@ -3,6 +3,7 @@ package org.sufficientlysecure.keychain.testsupport; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Collection; /** * Misc support functions. Would just use Guava / Apache Commons but @@ -10,9 +11,14 @@ import java.io.InputStream; */ public class TestDataUtil { public static byte[] readFully(InputStream input) { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + appendToOutput(input, output); + return output.toByteArray(); + } + + private static void appendToOutput(InputStream input, ByteArrayOutputStream output) { byte[] buffer = new byte[8192]; int bytesRead; - ByteArrayOutputStream output = new ByteArrayOutputStream(); try { while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); @@ -20,6 +26,19 @@ public class TestDataUtil { } catch (IOException e) { throw new RuntimeException(e); } + } + + public static byte[] readAllFully(Collection<String> inputResources) { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + for (String inputResource : inputResources) { + appendToOutput(getResourceAsStream(inputResource), output); + } return output.toByteArray(); } + + + public static InputStream getResourceAsStream(String resourceName) { + return TestDataUtil.class.getResourceAsStream(resourceName); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 3df3b24b2..430f85b6f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -29,8 +29,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.ImageButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -53,7 +52,7 @@ public class DecryptFileFragment extends DecryptFragment { // view private TextView mFilename; private CheckBox mDeleteAfter; - private BootstrapButton mBrowse; + private ImageButton mBrowse; private View mDecryptButton; // model @@ -68,7 +67,7 @@ public class DecryptFileFragment extends DecryptFragment { View view = inflater.inflate(R.layout.decrypt_file_fragment, container, false); mFilename = (TextView) view.findViewById(R.id.decrypt_file_filename); - mBrowse = (BootstrapButton) view.findViewById(R.id.decrypt_file_browse); + mBrowse = (ImageButton) view.findViewById(R.id.decrypt_file_browse); mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_file_delete_after_decryption); mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt); mBrowse.setOnClickListener(new View.OnClickListener() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index f67e54cf3..6b8358538 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -29,8 +29,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.Button; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.R; @@ -52,7 +51,7 @@ public class DecryptFragment extends Fragment { protected TextView mUserId; protected TextView mUserIdRest; - protected BootstrapButton mLookupKey; + protected Button mLookupKey; @Override @@ -65,7 +64,7 @@ public class DecryptFragment extends Fragment { mSignatureStatusImage = (ImageView) getView().findViewById(R.id.ic_signature_status); mUserId = (TextView) getView().findViewById(R.id.mainUserId); mUserIdRest = (TextView) getView().findViewById(R.id.mainUserIdRest); - mLookupKey = (BootstrapButton) getView().findViewById(R.id.lookup_key); + mLookupKey = (Button) getView().findViewById(R.id.lookup_key); mLookupKey.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java index 9a5050eba..586442bb0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java @@ -37,8 +37,7 @@ import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.FontAwesomeText; +import android.widget.ImageView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -79,10 +78,10 @@ public class DrawerActivity extends ActionBarActivity { } NavItem mItemIconTexts[] = new NavItem[]{ - new NavItem("fa-user", getString(R.string.nav_keys)), - new NavItem("fa-lock", getString(R.string.nav_encrypt)), - new NavItem("fa-unlock", getString(R.string.nav_decrypt)), - new NavItem("fa-android", getString(R.string.nav_apps))}; + new NavItem(R.drawable.ic_action_person, getString(R.string.nav_keys)), + new NavItem(R.drawable.ic_action_secure, getString(R.string.nav_encrypt)), + new NavItem(R.drawable.ic_action_not_secure, getString(R.string.nav_decrypt)), + new NavItem(R.drawable.ic_action_view_as_list, getString(R.string.nav_apps))}; mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.drawer_list_item, mItemIconTexts)); @@ -239,10 +238,15 @@ public class DrawerActivity extends ActionBarActivity { } private class NavItem { - public String icon; + public int icon; // res-id public String title; - public NavItem(String icon, String title) { + /** + * NavItem constructor + * @param icon The icons resource-id + * @param title The title of the menu entry + */ + public NavItem(int icon, String title) { super(); this.icon = icon; this.title = title; @@ -271,7 +275,7 @@ public class DrawerActivity extends ActionBarActivity { row = inflater.inflate(mLayoutResourceId, parent, false); holder = new NavItemHolder(); - holder.mImg = (FontAwesomeText) row.findViewById(R.id.drawer_item_icon); + holder.mImg = (ImageView) row.findViewById(R.id.drawer_item_icon); holder.mTxtTitle = (TextView) row.findViewById(R.id.drawer_item_text); row.setTag(holder); @@ -281,7 +285,7 @@ public class DrawerActivity extends ActionBarActivity { NavItem item = mData[position]; holder.mTxtTitle.setText(item.title); - holder.mImg.setIcon(item.icon); + holder.mImg.setImageResource(item.icon); return row; } @@ -289,7 +293,7 @@ public class DrawerActivity extends ActionBarActivity { } static class NavItemHolder { - FontAwesomeText mImg; + ImageView mImg; TextView mTxtTitle; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 4309e3505..d734c31db 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -34,13 +34,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout; import android.widget.Toast; -import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; @@ -97,7 +97,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener private boolean mNeedsSaving; private boolean mIsBrandNewKeyring = false; - private BootstrapButton mChangePassphrase; + private Button mChangePassphrase; private CheckBox mNoPassphrase; @@ -372,7 +372,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener setContentView(R.layout.edit_key_activity); // find views - mChangePassphrase = (BootstrapButton) findViewById(R.id.edit_key_btn_change_passphrase); + mChangePassphrase = (Button) findViewById(R.id.edit_key_btn_change_passphrase); mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase); // Build layout based on given userIds and keys diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java index f2b5e68eb..b45e8a6bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java @@ -20,19 +20,13 @@ package org.sufficientlysecure.keychain.ui; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; -import android.view.View; -import android.view.View.OnClickListener; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.remote.ui.AccountsListFragment; import org.sufficientlysecure.keychain.util.Log; public class EditKeyActivityNew extends ActionBarActivity { - private Uri mDataUri; - private EditKeyFragment mEditKeyFragment; @Override @@ -41,25 +35,6 @@ public class EditKeyActivityNew extends ActionBarActivity { setContentView(R.layout.edit_key_activity_new); -// // Inflate a "Done"/"Cancel" custom action bar view -// ActionBarHelper.setTwoButtonView(getSupportActionBar(), -// R.string.btn_save, R.drawable.ic_action_save, -// new OnClickListener() { -// @Override -// public void onClick(View v) { -// // Save -// -// } -// }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel, -// new OnClickListener() { -// @Override -// public void onClick(View v) { -// // Cancel -// -// } -// } -// ); - Uri dataUri = getIntent().getData(); if (dataUri == null) { Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index ac4390eac..b6a95a517 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -17,6 +17,8 @@ package org.sufficientlysecure.keychain.ui; +import android.app.ProgressDialog; +import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -42,11 +44,17 @@ import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResults; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsArrayAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -68,6 +76,7 @@ public class EditKeyFragment extends LoaderFragment implements private UserIdsAdapter mUserIdsAdapter; private SubkeysAdapter mKeysAdapter; + private UserIdsArrayAdapter mUserIdsAddedAdapter; private Uri mDataUri; @@ -180,6 +189,10 @@ public class EditKeyFragment extends LoaderFragment implements } }); + mUserIdsAddedAdapter = new UserIdsArrayAdapter(getActivity()); + mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); + mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); + mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0); mKeysList.setAdapter(mKeysAdapter); @@ -253,8 +266,6 @@ public class EditKeyFragment extends LoaderFragment implements String newPassphrase = data .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE); -// updatePassphraseButtonText(); -// somethingChanged(); mSaveKeyringParcel.newPassphrase = newPassphrase; } } @@ -263,14 +274,6 @@ public class EditKeyFragment extends LoaderFragment implements // Create a new Messenger for the communication back Messenger messenger = new Messenger(returnHandler); - // set title based on isPassphraseSet() -// int title; -// if (isPassphraseSet()) { -// title = R.string.title_change_passphrase; -// } else { -// title = R.string.title_set_passphrase; -// } - SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance( messenger, R.string.title_change_passphrase); @@ -321,9 +324,17 @@ public class EditKeyFragment extends LoaderFragment implements Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { - if (message.what == AddUserIdDialogFragment.MESSAGE_OK) { + switch (message.what) { + case AddUserIdDialogFragment.MESSAGE_OKAY: + Bundle data = message.getData(); + String userId = data.getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID); + if (userId != null) { + mSaveKeyringParcel.addUserIds.add(userId); + mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); + } } + getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); } }; @@ -341,9 +352,73 @@ public class EditKeyFragment extends LoaderFragment implements } private void save() { - getActivity().finish(); - // TODO + String passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), + mSaveKeyringParcel.mMasterKeyId); + if (passphrase == null) { + PassphraseDialogFragment.show(getActivity(), mSaveKeyringParcel.mMasterKeyId, + new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + saveFinal(); + } + } + } + ); + + } + } + private void saveFinal() { + // Message is received after importing is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( + getActivity(), + getString(R.string.progress_saving), + ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + if (returnData == null) { + return; + } + final OperationResults.SaveKeyringResult result = + returnData.getParcelable(KeychainIntentService.RESULT); + if (result == null) { + return; + } -} + // if good -> finish, return result to showkey and display there! + // if bad -> display here! + +// result.displayNotify(ImportKeysActivity.this); + +// getActivity().finish(); + } + } + }; + + // Send all information needed to service to import key in other thread + Intent intent = new Intent(getActivity(), KeychainIntentService.class); + intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); + + // fill values for this action + Bundle data = new Bundle(); + data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, mSaveKeyringParcel); + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(getActivity()); + + // start service with intent + getActivity().startService(intent); + } +}
\ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index e4ba6ebd0..51963e963 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -27,8 +27,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.Button; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -52,7 +51,7 @@ public class EncryptAsymmetricFragment extends Fragment { OnAsymmetricKeySelection mKeySelectionListener; // view - private BootstrapButton mSelectKeysButton; + private Button mSelectKeysButton; private CheckBox mSign; private TextView mMainUserId; private TextView mMainUserIdRest; @@ -99,7 +98,7 @@ public class EncryptAsymmetricFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSelectKeysButton = (BootstrapButton) view.findViewById(R.id.btn_selectEncryptKeys); + mSelectKeysButton = (Button) view.findViewById(R.id.btn_selectEncryptKeys); mSign = (CheckBox) view.findViewById(R.id.sign); mMainUserId = (TextView) view.findViewById(R.id.mainUserId); mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); @@ -204,7 +203,7 @@ public class EncryptAsymmetricFragment extends Fragment { userId = null; } if (userId != null && userId[0] != null) { - mMainUserId.setText(userId[0]); + mMainUserId.setText(String.format("%#16x", Long.parseLong(userId[0]))); } else { mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 4da76bdfb..2fabeb82c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -33,8 +33,8 @@ import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.Spinner; import android.widget.TextView; +import android.widget.ImageButton; -import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; @@ -66,7 +66,7 @@ public class EncryptFileFragment extends Fragment { private TextView mFilename = null; private CheckBox mDeleteAfter = null; private CheckBox mShareAfter = null; - private BootstrapButton mBrowse = null; + private ImageButton mBrowse = null; private View mEncryptFile; // model @@ -99,7 +99,7 @@ public class EncryptFileFragment extends Fragment { }); mFilename = (TextView) view.findViewById(R.id.filename); - mBrowse = (BootstrapButton) view.findViewById(R.id.btn_browse); + mBrowse = (ImageButton) view.findViewById(R.id.btn_browse); mBrowse.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Constants.KITKAT) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index f7455905d..3ff3b56bf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -36,11 +36,6 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import com.github.johnpersano.supertoasts.SuperCardToast; -import com.github.johnpersano.supertoasts.SuperToast; -import com.github.johnpersano.supertoasts.util.OnClickWrapper; -import com.github.johnpersano.supertoasts.util.Style; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.OtherHelper; @@ -54,6 +49,7 @@ import org.sufficientlysecure.keychain.service.OperationResults.ImportResult; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.util.ArrayList; import java.util.Locale; @@ -64,8 +60,12 @@ public class ImportKeysActivity extends ActionBarActivity { + "IMPORT_KEY_FROM_QR_CODE"; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEYSERVER"; + public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT = + Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN_RESULT"; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN"; + public static final String ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN = Constants.INTENT_PREFIX + + "IMPORT_KEY_FROM_FILE_AND_RETURN"; public static final String ACTION_IMPORT_KEY_FROM_KEYBASE = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEYBASE"; @@ -75,6 +75,8 @@ public class ImportKeysActivity extends ActionBarActivity { public static final String ACTION_IMPORT_KEY_FROM_NFC = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_NFC"; + public static final String EXTRA_RESULT = "result"; + // only used by ACTION_IMPORT_KEY public static final String EXTRA_KEY_BYTES = "key_bytes"; @@ -165,7 +167,8 @@ public class ImportKeysActivity extends ActionBarActivity { startListFragment(savedInstanceState, importData, null, null); } } else if (ACTION_IMPORT_KEY_FROM_KEYSERVER.equals(action) - || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(action)) { + || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(action) + || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(action)) { // only used for OpenPgpService if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) { @@ -224,7 +227,8 @@ public class ImportKeysActivity extends ActionBarActivity { ); return; } - } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { + } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action) + || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { // NOTE: this only displays the appropriate fragment, no actions are taken mSwitchToTab = TAB_FILE; @@ -373,11 +377,7 @@ public class ImportKeysActivity extends ActionBarActivity { private boolean isFingerprintValid(String fingerprint) { if (fingerprint == null || fingerprint.length() < 40) { - SuperCardToast toast = SuperCardToast.create(this, - getString(R.string.import_qr_code_too_short_fingerprint), - SuperToast.Duration.LONG); - toast.setBackground(SuperToast.Background.RED); - toast.show(); + Notify.showNotify(this, R.string.import_qr_code_too_short_fingerprint, Notify.Style.ERROR); return false; } else { return true; @@ -386,9 +386,6 @@ public class ImportKeysActivity extends ActionBarActivity { /** * Scroll ViewPager left and right - * - * @param event - * @return */ @Override public boolean onTouchEvent(MotionEvent event) { @@ -427,94 +424,34 @@ public class ImportKeysActivity extends ActionBarActivity { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { // get returned data bundle Bundle returnData = message.getData(); + if (returnData == null) { + return; + } final ImportResult result = - returnData.<ImportResult>getParcelable(KeychainIntentService.RESULT); - - int resultType = result.getResult(); - - String str; - int duration, color; - - // Not an overall failure - if ((resultType & ImportResult.RESULT_ERROR) == 0) { - String withWarnings; - - // Any warnings? - if ((resultType & ImportResult.RESULT_WITH_WARNINGS) > 0) { - duration = 0; - color = Style.ORANGE; - withWarnings = getResources().getString(R.string.import_with_warnings); - } else { - duration = SuperToast.Duration.LONG; - color = Style.GREEN; - withWarnings = ""; - } - - // New and updated keys - if (result.isOkBoth()) { - str = getResources().getQuantityString( - R.plurals.import_keys_added_and_updated_1, result.mNewKeys, result.mNewKeys); - str += getResources().getQuantityString( - R.plurals.import_keys_added_and_updated_2, result.mUpdatedKeys, result.mUpdatedKeys, withWarnings); - } else if (result.isOkUpdated()) { - str = getResources().getQuantityString( - R.plurals.import_keys_updated, result.mUpdatedKeys, result.mUpdatedKeys, withWarnings); - } else if (result.isOkNew()) { - str = getResources().getQuantityString( - R.plurals.import_keys_added, result.mNewKeys, result.mNewKeys, withWarnings); - } else { - duration = 0; - color = Style.RED; - str = "internal error"; - } - - } else { - duration = 0; - color = Style.RED; - if (result.isFailNothing()) { - str = getString(R.string.import_error_nothing); - } else { - str = getString(R.string.import_error); - } + returnData.getParcelable(KeychainIntentService.RESULT); + if (result == null) { + return; } - SuperCardToast toast = new SuperCardToast(ImportKeysActivity.this, - SuperToast.Type.BUTTON, Style.getStyle(color, SuperToast.Animations.POPUP)); - toast.setText(str); - toast.setDuration(duration); - toast.setIndeterminate(duration == 0); - toast.setSwipeToDismiss(true); - toast.setButtonIcon(R.drawable.ic_action_view_as_list, - getResources().getString(R.string.import_view_log)); - toast.setButtonTextColor(getResources().getColor(R.color.black)); - toast.setTextColor(getResources().getColor(R.color.black)); - toast.setOnClickWrapper(new OnClickWrapper("supercardtoast", - new SuperToast.OnClickListener() { - @Override - public void onClick(View view, Parcelable token) { - Intent intent = new Intent( - ImportKeysActivity.this, LogDisplayActivity.class); - intent.putExtra(LogDisplayFragment.EXTRA_RESULT, result); - startActivity(intent); - } - } - )); - toast.show(); - - /* - if (bad > 0) { - BadImportKeyDialogFragment badImportKeyDialogFragment = - BadImportKeyDialogFragment.newInstance(bad); - badImportKeyDialogFragment.show(getSupportFragmentManager(), "badKeyDialog"); + if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_RESULT, result); + ImportKeysActivity.this.setResult(RESULT_OK, intent); + ImportKeysActivity.this.finish(); + return; } - */ - - /* if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) { - ImportKeysActivity.this.setResult(Activity.RESULT_OK, mPendingIntentData); - finish(); + ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData); + ImportKeysActivity.this.finish(); + return; + } + if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { + ImportKeysActivity.this.setResult(RESULT_OK); + ImportKeysActivity.this.finish(); + return; } - */ + + result.displayNotify(ImportKeysActivity.this); } } }; @@ -600,11 +537,7 @@ public class ImportKeysActivity extends ActionBarActivity { startService(intent); } else { - SuperCardToast toast = SuperCardToast.create(this, - getString(R.string.error_nothing_import), - SuperToast.Duration.LONG); - toast.setBackground(SuperToast.Background.RED); - toast.show(); + Notify.showNotify(this, R.string.error_nothing_import, Notify.Style.ERROR); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 84fd513a0..9a39b6cc3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -35,6 +35,7 @@ import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.Keyserver; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListKeybaseLoader; @@ -79,6 +80,7 @@ public class ImportKeysListFragment extends ListFragment implements public ArrayList<ParcelableKeyRing> getSelectedData() { ArrayList<ParcelableKeyRing> result = new ArrayList<ParcelableKeyRing>(); for (ImportKeysListEntry entry : getSelectedEntries()) { + Log.d(Constants.TAG, "code" + Integer.toString(entry.hashCode())); result.add(mCachedKeyData.get(entry.hashCode())); } return result; @@ -207,7 +209,9 @@ public class ImportKeysListFragment extends ListFragment implements if (getLoaderManager().getLoader(LOADER_ID_KEYBASE) != null) { getLoaderManager().destroyLoader(LOADER_ID_KEYBASE); } - setListShown(true); + if (getView() != null) { + setListShown(true); + } } private void restartLoaders() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index de16142d6..7ce7a06aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -113,10 +113,10 @@ public class KeyListActivity extends DrawerActivity { } private void createKey() { - Intent intent = new Intent(this, EditKeyActivity.class); - intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); - intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); - intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view + Intent intent = new Intent(this, WizardActivity.class); +// intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); +// intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); +// intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view startActivityForResult(intent, 0); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 48ad13425..0940d5632 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -51,8 +51,8 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; +import android.widget.Button; -import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; @@ -85,8 +85,8 @@ public class KeyListFragment extends LoaderFragment private String mQuery; private SearchView mSearchView; // empty list layout - private BootstrapButton mButtonEmptyCreate; - private BootstrapButton mButtonEmptyImport; + private Button mButtonEmptyCreate; + private Button mButtonEmptyImport; /** @@ -101,7 +101,7 @@ public class KeyListFragment extends LoaderFragment mStickyList.setOnItemClickListener(this); // empty view - mButtonEmptyCreate = (BootstrapButton) view.findViewById(R.id.key_list_empty_button_create); + mButtonEmptyCreate = (Button) view.findViewById(R.id.key_list_empty_button_create); mButtonEmptyCreate.setOnClickListener(new OnClickListener() { @Override @@ -113,7 +113,7 @@ public class KeyListFragment extends LoaderFragment startActivityForResult(intent, 0); } }); - mButtonEmptyImport = (BootstrapButton) view.findViewById(R.id.key_list_empty_button_import); + mButtonEmptyImport = (Button) view.findViewById(R.id.key_list_empty_button_import); mButtonEmptyImport.setOnClickListener(new OnClickListener() { @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index e42d9d00b..67317de6e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -173,7 +173,14 @@ public class LogDisplayFragment extends ListFragment implements OnTouchListener ih = (ItemHolder) convertView.getTag(); } - ih.mText.setText(getResources().getString(entry.mType.getMsgId(), (Object[]) entry.mParameters)); + // special case: first parameter may be a quantity + if (entry.mParameters != null && entry.mParameters.length > 0 + && entry.mParameters[0] instanceof Integer) { + ih.mText.setText(getResources().getQuantityString(entry.mType.getMsgId(), + (Integer) entry.mParameters[0], entry.mParameters)); + } else { + ih.mText.setText(getResources().getString(entry.mType.getMsgId(), entry.mParameters)); + } ih.mText.setTextColor(entry.mLevel == LogLevel.DEBUG ? Color.GRAY : Color.BLACK); convertView.setPadding((entry.mIndent) * dipFactor, 0, 0, 0); switch (entry.mLevel) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java index b36270981..e156b8b9c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java @@ -30,10 +30,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.Button; import android.widget.TextView; -import com.beardedhen.androidbootstrap.BootstrapButton; - import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; @@ -45,7 +44,7 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan private TextView mKeyUserIdRest; private TextView mKeyMasterKeyIdHex; private TextView mNoKeySelected; - private BootstrapButton mSelectKeyButton; + private Button mSelectKeyButton; private Boolean mFilterCertify, mFilterSign; private Uri mReceivedUri = null; @@ -117,8 +116,7 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan mKeyUserId = (TextView) view.findViewById(R.id.select_secret_key_user_id); mKeyUserIdRest = (TextView) view.findViewById(R.id.select_secret_key_user_id_rest); mKeyMasterKeyIdHex = (TextView) view.findViewById(R.id.select_secret_key_master_key_hex); - mSelectKeyButton = (BootstrapButton) view - .findViewById(R.id.select_secret_key_select_key_button); + mSelectKeyButton = (Button) view.findViewById(R.id.select_secret_key_select_key_button); mFilterCertify = false; mFilterSign = false; mSelectKeyButton.setOnClickListener(new OnClickListener() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index d9be88d68..c7fffe263 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -152,7 +152,7 @@ public class ViewCertActivity extends ActionBarActivity sig.init(signerRing.getSubkey()); if (sig.verifySignature(signeeRing.getSubkey(), signeeUid)) { mStatus.setText(R.string.cert_verify_ok); - mStatus.setTextColor(getResources().getColor(R.color.bbutton_success)); + mStatus.setTextColor(getResources().getColor(R.color.result_green)); } else { mStatus.setText(R.string.cert_verify_failed); mStatus.setTextColor(getResources().getColor(R.color.alert)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 6dc6990e0..22a23e6a5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.OperationResults.ImportResult; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout.TabColorizer; import org.sufficientlysecure.keychain.util.Log; @@ -329,7 +330,7 @@ public class ViewKeyActivity extends ActionBarActivity implements String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); Intent queryIntent = new Intent(this, ImportKeysActivity.class); - queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN); + queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); startActivityForResult(queryIntent, REQUEST_CODE_LOOKUP_KEY); @@ -353,7 +354,10 @@ public class ViewKeyActivity extends ActionBarActivity implements switch (requestCode) { case REQUEST_CODE_LOOKUP_KEY: { if (resultCode == Activity.RESULT_OK) { - // TODO: reload key??? move this into fragment? + ImportResult result = data.getParcelableExtra(ImportKeysActivity.EXTRA_RESULT); + if (result != null) { + result.displayNotify(this); + } } break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java index eccd2a5e5..52b573f47 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -152,7 +152,11 @@ public class ViewKeyShareFragment extends LoaderFragment implements KeyRings.buildUnifiedKeyRingUri(dataUri), Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); String fingerprint = PgpKeyHelper.convertFingerprintToHex(data); - content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; + if(!toClipboard){ + content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; + } else { + content = fingerprint; + } } else { // get public keyring as ascii armored string Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java new file mode 100644 index 000000000..20b47ed01 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java @@ -0,0 +1,466 @@ +/* + * Copyright (C) 2014 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; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBarActivity; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RadioGroup; +import android.widget.TextView; + +import org.sufficientlysecure.htmltextview.HtmlTextView; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.regex.Matcher; + + +public class WizardActivity extends ActionBarActivity { + + private State mCurrentState; + + // values for mCurrentScreen + private enum State { + START, CREATE_KEY, IMPORT_KEY, K9 + } + + public static final int REQUEST_CODE_IMPORT = 0x00007703; + + Button mBackButton; + Button mNextButton; + StartFragment mStartFragment; + CreateKeyFragment mCreateKeyFragment; + K9Fragment mK9Fragment; + + private static final String K9_PACKAGE = "com.fsck.k9"; + // private static final String K9_MARKET_INTENT_URI_BASE = "market://details?id=%s"; +// private static final Intent K9_MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse( +// String.format(K9_MARKET_INTENT_URI_BASE, K9_PACKAGE))); + private static final Intent K9_MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/k9mail/k-9/releases/tag/4.904")); + + LinearLayout mProgressLayout; + View mProgressLine; + ProgressBar mProgressBar; + ImageView mProgressImage; + TextView mProgressText; + + /** + * Checks if text of given EditText is not empty. If it is empty an error is + * set and the EditText gets the focus. + * + * @param context + * @param editText + * @return true if EditText is not empty + */ + private static boolean isEditTextNotEmpty(Context context, EditText editText) { + boolean output = true; + if (editText.getText().toString().length() == 0) { + editText.setError("empty!"); + editText.requestFocus(); + output = false; + } else { + editText.setError(null); + } + + return output; + } + + public static class StartFragment extends Fragment { + public static StartFragment newInstance() { + StartFragment myFragment = new StartFragment(); + + Bundle args = new Bundle(); + myFragment.setArguments(args); + + return myFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.wizard_start_fragment, + container, false); + } + } + + public static class CreateKeyFragment extends Fragment { + public static CreateKeyFragment newInstance() { + CreateKeyFragment myFragment = new CreateKeyFragment(); + + Bundle args = new Bundle(); + myFragment.setArguments(args); + + return myFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.wizard_create_key_fragment, + container, false); + + final AutoCompleteTextView emailView = (AutoCompleteTextView) view.findViewById(R.id.email); + emailView.setThreshold(1); // Start working from first character + emailView.setAdapter( + new ArrayAdapter<String> + (getActivity(), android.R.layout.simple_dropdown_item_1line, + ContactHelper.getPossibleUserEmails(getActivity()) + ) + ); + emailView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void afterTextChanged(Editable editable) { + String email = editable.toString(); + if (email.length() > 0) { + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); + if (emailMatcher.matches()) { + emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_ok, 0); + } else { + emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_bad, 0); + } + } else { + // remove drawable if email is empty + emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + }); + final AutoCompleteTextView nameView = (AutoCompleteTextView) view.findViewById(R.id.name); + nameView.setThreshold(1); // Start working from first character + nameView.setAdapter( + new ArrayAdapter<String> + (getActivity(), android.R.layout.simple_dropdown_item_1line, + ContactHelper.getPossibleUserNames(getActivity()) + ) + ); + return view; + } + } + + public static class K9Fragment extends Fragment { + public static K9Fragment newInstance() { + K9Fragment myFragment = new K9Fragment(); + + Bundle args = new Bundle(); + myFragment.setArguments(args); + + return myFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.wizard_k9_fragment, + container, false); + + HtmlTextView text = (HtmlTextView) v + .findViewById(R.id.wizard_k9_text); + text.setHtmlFromString("Install K9. It's good for you! Here is a screenhot how to enable OK in K9: (TODO)", true); + + return v; + } + + } + + /** + * Loads new fragment + * + * @param fragment + */ + private void loadFragment(Fragment fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager + .beginTransaction(); + fragmentTransaction.replace(R.id.wizard_container, + fragment); + fragmentTransaction.commit(); + } + + /** + * Instantiate View and initialize fragments for this Activity + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.wizard_activity); + mBackButton = (Button) findViewById(R.id.wizard_back); + mNextButton = (Button) findViewById(R.id.wizard_next); + + // progress layout + mProgressLayout = (LinearLayout) findViewById(R.id.wizard_progress); + mProgressLine = findViewById(R.id.wizard_progress_line); + mProgressBar = (ProgressBar) findViewById(R.id.wizard_progress_progressbar); + mProgressImage = (ImageView) findViewById(R.id.wizard_progress_image); + mProgressText = (TextView) findViewById(R.id.wizard_progress_text); + + changeToState(State.START); + } + + private enum ProgressState { + WORKING, ENABLED, DISABLED, ERROR + } + + private void showProgress(ProgressState state, String text) { + switch (state) { + case WORKING: + mProgressBar.setVisibility(View.VISIBLE); + mProgressImage.setVisibility(View.GONE); + break; + case ENABLED: + mProgressBar.setVisibility(View.GONE); + mProgressImage.setVisibility(View.VISIBLE); +// mProgressImage.setImageDrawable(getResources().getDrawable( +// R.drawable.status_enabled)); + break; + case DISABLED: + mProgressBar.setVisibility(View.GONE); + mProgressImage.setVisibility(View.VISIBLE); +// mProgressImage.setImageDrawable(getResources().getDrawable( +// R.drawable.status_disabled)); + break; + case ERROR: + mProgressBar.setVisibility(View.GONE); + mProgressImage.setVisibility(View.VISIBLE); +// mProgressImage.setImageDrawable(getResources().getDrawable( +// R.drawable.status_fail)); + break; + + default: + break; + } + mProgressText.setText(text); + + mProgressLine.setVisibility(View.VISIBLE); + mProgressLayout.setVisibility(View.VISIBLE); + } + + private void hideProgress() { + mProgressLine.setVisibility(View.GONE); + mProgressLayout.setVisibility(View.GONE); + } + + public void nextOnClick(View view) { + // close keyboard + if (getCurrentFocus() != null) { + InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(getCurrentFocus() + .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + + switch (mCurrentState) { + case START: { + RadioGroup radioGroup = (RadioGroup) findViewById(R.id.wizard_start_radio_group); + int selectedId = radioGroup.getCheckedRadioButtonId(); + switch (selectedId) { + case R.id.wizard_start_new_key: { + changeToState(State.CREATE_KEY); + break; + } + case R.id.wizard_start_import: { + changeToState(State.IMPORT_KEY); + break; + } + case R.id.wizard_start_skip: { + finish(); + break; + } + } + + mBackButton.setText(R.string.btn_back); + break; + } + case CREATE_KEY: + EditText nameEdit = (EditText) findViewById(R.id.name); + EditText emailEdit = (EditText) findViewById(R.id.email); + EditText passphraseEdit = (EditText) findViewById(R.id.passphrase); + + if (isEditTextNotEmpty(this, nameEdit) + && isEditTextNotEmpty(this, emailEdit) + && isEditTextNotEmpty(this, passphraseEdit)) { + +// SaveKeyringParcel newKey = new SaveKeyringParcel(); +// newKey.addUserIds.add(nameEdit.getText().toString() + " <" +// + emailEdit.getText().toString() + ">"); + + + AsyncTask<String, Boolean, Boolean> generateTask = new AsyncTask<String, Boolean, Boolean>() { + + @Override + protected void onPreExecute() { + super.onPreExecute(); + + showProgress(ProgressState.WORKING, "generating key..."); + } + + @Override + protected Boolean doInBackground(String... params) { + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + + if (result) { + showProgress(ProgressState.ENABLED, "key generated successfully!"); + + changeToState(State.K9); + } else { + showProgress(ProgressState.ERROR, "error in key gen"); + } + } + + }; + + generateTask.execute(""); + } + break; + case K9: { + RadioGroup radioGroup = (RadioGroup) findViewById(R.id.wizard_k9_radio_group); + int selectedId = radioGroup.getCheckedRadioButtonId(); + switch (selectedId) { + case R.id.wizard_k9_install: { + try { + startActivity(K9_MARKET_INTENT); + } catch (ActivityNotFoundException e) { + Log.e(Constants.TAG, "Activity not found for: " + K9_MARKET_INTENT); + } + break; + } + case R.id.wizard_k9_skip: { + finish(); + break; + } + } + + finish(); + break; + } + default: + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode) { + case REQUEST_CODE_IMPORT: { + if (resultCode == Activity.RESULT_OK) { + // imported now... + changeToState(State.K9); + } else { + // back to start + changeToState(State.START); + } + break; + } + + default: { + super.onActivityResult(requestCode, resultCode, data); + + break; + } + } + } + + public void backOnClick(View view) { + switch (mCurrentState) { + case START: + finish(); + break; + case CREATE_KEY: + changeToState(State.START); + break; + case IMPORT_KEY: + changeToState(State.START); + break; + default: + changeToState(State.START); + break; + } + } + + private void changeToState(State state) { + switch (state) { + case START: { + mCurrentState = State.START; + mStartFragment = StartFragment.newInstance(); + loadFragment(mStartFragment); + mBackButton.setText(android.R.string.cancel); + mNextButton.setText(R.string.btn_next); + break; + } + case CREATE_KEY: { + mCurrentState = State.CREATE_KEY; + mCreateKeyFragment = CreateKeyFragment.newInstance(); + loadFragment(mCreateKeyFragment); + break; + } + case IMPORT_KEY: { + mCurrentState = State.IMPORT_KEY; + Intent intent = new Intent(this, ImportKeysActivity.class); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); + startActivityForResult(intent, REQUEST_CODE_IMPORT); + break; + } + case K9: { + mCurrentState = State.K9; + mBackButton.setEnabled(false); // don't go back to import/create key + mK9Fragment = K9Fragment.newInstance(); + loadFragment(mK9Fragment); + break; + } + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index a44d32e5b..7a55f9aaa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -85,6 +85,10 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> { public ArrayList<ImportKeysListEntry> getSelectedEntries() { ArrayList<ImportKeysListEntry> selectedData = new ArrayList<ImportKeysListEntry>(); + // Nothing to select, nvm. + if (mData == null) { + return selectedData; + } for (ImportKeysListEntry entry : mData) { if (entry.isSelected()) { selectedData.add(entry); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index 7a7acfe89..7fc78dc41 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -144,7 +144,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC vComment.setVisibility(View.GONE); } - // show small star icon for primary user ids boolean isPrimary = cursor.getInt(mIsPrimary) != 0; boolean isRevoked = cursor.getInt(mIsRevoked) > 0; @@ -185,6 +184,8 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC vName.setEnabled(true); vAddress.setEnabled(true); + // verified: has been verified + // isPrimary: show small star icon for primary user ids int verified = cursor.getInt(mVerifiedId); switch (verified) { case Certs.VERIFIED_SECRET: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java new file mode 100644 index 000000000..e6445c074 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2013-2014 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 android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +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.ImageView; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; + +import java.util.List; + +public class UserIdsArrayAdapter extends ArrayAdapter<String> { + protected LayoutInflater mInflater; + protected Activity mActivity; + + protected List<String> mData; + + static class ViewHolder { + public TextView vName; + public TextView vAddress; + public TextView vComment; + public ImageView vVerified; + public ImageView vHasChanges; + public CheckBox vCheckBox; + } + + public UserIdsArrayAdapter(Activity activity) { + super(activity, -1); + mActivity = activity; + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void setData(List<String> data) { + clear(); + if (data != null) { + this.mData = data; + + // add data to extended ArrayAdapter + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + addAll(data); + } else { + for (String entry : data) { + add(entry); + } + } + } + } + + public List<String> getData() { + return mData; + } + + @Override + public boolean hasStableIds() { + return true; + } + + public View getView(int position, View convertView, ViewGroup parent) { + String entry = mData.get(position); + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.view_key_userids_item, null); + holder.vName = (TextView) convertView.findViewById(R.id.userId); + holder.vAddress = (TextView) convertView.findViewById(R.id.address); + holder.vComment = (TextView) convertView.findViewById(R.id.comment); + holder.vVerified = (ImageView) convertView.findViewById(R.id.certified); + holder.vHasChanges = (ImageView) convertView.findViewById(R.id.has_changes); + holder.vCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + // user id + String[] splitUserId = KeyRing.splitUserId(entry); + if (splitUserId[0] != null) { + holder.vName.setText(splitUserId[0]); + } else { + holder.vName.setText(R.string.user_id_no_name); + } + if (splitUserId[1] != null) { + holder.vAddress.setText(splitUserId[1]); + holder.vAddress.setVisibility(View.VISIBLE); + } else { + holder.vAddress.setVisibility(View.GONE); + } + if (splitUserId[2] != null) { + holder.vComment.setText(splitUserId[2]); + holder.vComment.setVisibility(View.VISIBLE); + } else { + holder.vComment.setVisibility(View.GONE); + } + + holder.vCheckBox.setVisibility(View.GONE); + + holder.vVerified.setImageResource(R.drawable.key_certify_ok_depth0); + + // all items are "new" + holder.vHasChanges.setVisibility(View.VISIBLE); + + return convertView; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index db7c38e71..c27266e3f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -24,17 +24,32 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; -public class AddUserIdDialogFragment extends DialogFragment { +public class AddUserIdDialogFragment extends DialogFragment implements EditText.OnEditorActionListener { private static final String ARG_MESSENGER = "messenger"; - public static final int MESSAGE_OK = 1; + public static final int MESSAGE_OKAY = 1; + + public static final String MESSAGE_DATA_USER_ID = "user_id"; private Messenger mMessenger; + EditText mName; + EditText mAddress; + EditText mComment; + /** * Creates new instance of this dialog fragment */ @@ -55,34 +70,75 @@ public class AddUserIdDialogFragment extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { mMessenger = getArguments().getParcelable(ARG_MESSENGER); - CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity()); -// CharSequence[] array = {"change to primary user id", "revoke"}; -// -// builder.setTitle("select action!"); -// builder.setItems(array, new DialogInterface.OnClickListener() { -// -// @Override -// public void onClick(DialogInterface dialog, int which) { -// switch (which) { -// case 0: -// sendMessageToHandler(MESSAGE_CHANGE_PRIMARY_USER_ID, null); -// break; -// case 1: -// sendMessageToHandler(MESSAGE_REVOKE, null); -// break; -// default: -// break; -// } -// } -// }); -// builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() { -// @Override -// public void onClick(DialogInterface dialog, int id) { -// dismiss(); -// } -// }); - - return builder.show(); + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.add_user_id_dialog, null); + alert.setView(view); + alert.setTitle("Add Identity"); + + mName = (EditText) view.findViewById(R.id.name); + mAddress = (EditText) view.findViewById(R.id.address); + mComment = (EditText) view.findViewById(R.id.comment); + + alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + done(); + } + }); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + + + return alert.show(); + } + + @Override + public void onActivityCreated(Bundle arg0) { + super.onActivityCreated(arg0); + // Show soft keyboard automatically + mName.requestFocus(); + getDialog().getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + mComment.setOnEditorActionListener(this); + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (EditorInfo.IME_ACTION_DONE == actionId) { + done(); + return true; + } + return false; + } + + private void done() { + String name = mName.getText().toString(); + String email = mAddress.getText().toString(); + String comment = mComment.getText().toString(); + + String userId = null; + if (!TextUtils.isEmpty(name)) { + userId = name; + if (!TextUtils.isEmpty(comment)) { + userId += " (" + comment + ")"; + } + if (!TextUtils.isEmpty(email)) { + userId += " <" + email + ">"; + } + } + Bundle data = new Bundle(); + data.putString(MESSAGE_DATA_USER_ID, userId); + sendMessageToHandler(MESSAGE_OKAY, data); + + this.dismiss(); } /** @@ -105,4 +161,5 @@ public class AddUserIdDialogFragment extends DialogFragment { Log.w(Constants.TAG, "Messenger is null!", e); } } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java index c02c37055..15d50d7ed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java @@ -33,11 +33,8 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; +import android.widget.ImageButton; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; - -import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -63,7 +60,7 @@ public class FileDialogFragment extends DialogFragment { private Messenger mMessenger; private EditText mFilename; - private BootstrapButton mBrowse; + private ImageButton mBrowse; private CheckBox mCheckBox; private TextView mMessageTextView; @@ -120,7 +117,7 @@ public class FileDialogFragment extends DialogFragment { mFilename = (EditText) view.findViewById(R.id.input); mFilename.setText(mFile.getName()); - mBrowse = (BootstrapButton) view.findViewById(R.id.btn_browse); + mBrowse = (ImageButton) view.findViewById(R.id.btn_browse); mBrowse.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // only .asc or .gpg files diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java index 24641a9cc..a29c17d37 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java @@ -26,8 +26,7 @@ import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.LinearLayout; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.FontAwesomeText; +import android.widget.ImageButton; import org.sufficientlysecure.keychain.R; @@ -50,7 +49,7 @@ import org.sufficientlysecure.keychain.R; */ public class FoldableLinearLayout extends LinearLayout { - private FontAwesomeText mFoldableIcon; + private ImageButton mFoldableIcon; private boolean mFolded; private boolean mHasMigrated = false; private Integer mShortAnimationDuration = null; @@ -58,8 +57,6 @@ public class FoldableLinearLayout extends LinearLayout { private LinearLayout mFoldableContainer = null; private View mFoldableLayout = null; - private String mFoldedIconName; - private String mUnFoldedIconName; private String mFoldedLabel; private String mUnFoldedLabel; @@ -87,15 +84,11 @@ public class FoldableLinearLayout extends LinearLayout { if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FoldableLinearLayout, 0, 0); - mFoldedIconName = a.getString(R.styleable.FoldableLinearLayout_foldedIcon); - mUnFoldedIconName = a.getString(R.styleable.FoldableLinearLayout_unFoldedIcon); mFoldedLabel = a.getString(R.styleable.FoldableLinearLayout_foldedLabel); mUnFoldedLabel = a.getString(R.styleable.FoldableLinearLayout_unFoldedLabel); a.recycle(); } // If any attribute isn't found then set a default one - mFoldedIconName = (mFoldedIconName == null) ? "fa-chevron-right" : mFoldedIconName; - mUnFoldedIconName = (mUnFoldedIconName == null) ? "fa-chevron-down" : mUnFoldedIconName; mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.id.none) : mFoldedLabel; mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.id.none) : mUnFoldedLabel; } @@ -146,8 +139,8 @@ public class FoldableLinearLayout extends LinearLayout { } private void initialiseInnerViews() { - mFoldableIcon = (FontAwesomeText) mFoldableLayout.findViewById(R.id.foldableIcon); - mFoldableIcon.setIcon(mFoldedIconName); + mFoldableIcon = (ImageButton) mFoldableLayout.findViewById(R.id.foldableIcon); + mFoldableIcon.setImageResource(R.drawable.ic_action_expand); mFoldableTextView = (TextView) mFoldableLayout.findViewById(R.id.foldableText); mFoldableTextView.setText(mFoldedLabel); @@ -160,7 +153,7 @@ public class FoldableLinearLayout extends LinearLayout { public void onClick(View view) { mFolded = !mFolded; if (mFolded) { - mFoldableIcon.setIcon(mUnFoldedIconName); + mFoldableIcon.setImageResource(R.drawable.ic_action_collapse); mFoldableContainer.setVisibility(View.VISIBLE); AlphaAnimation animation = new AlphaAnimation(0f, 1f); animation.setDuration(mShortAnimationDuration); @@ -168,7 +161,7 @@ public class FoldableLinearLayout extends LinearLayout { mFoldableTextView.setText(mUnFoldedLabel); } else { - mFoldableIcon.setIcon(mFoldedIconName); + mFoldableIcon.setImageResource(R.drawable.ic_action_expand); AlphaAnimation animation = new AlphaAnimation(1f, 0f); animation.setDuration(mShortAnimationDuration); animation.setAnimationListener(new Animation.AnimationListener() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java index 40fe7665c..c23b4c3ff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java @@ -31,12 +31,12 @@ import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.DatePicker; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.Button; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; @@ -54,11 +54,11 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { private EditorListener mEditorListener = null; private boolean mIsMasterKey; - BootstrapButton mDeleteButton; + ImageButton mDeleteButton; TextView mAlgorithm; TextView mKeyId; TextView mCreationDate; - BootstrapButton mExpiryDateButton; + Button mExpiryDateButton; Calendar mCreatedDate; Calendar mExpiryDate; Calendar mOriginalExpiryDate = null; @@ -122,9 +122,9 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { mAlgorithm = (TextView) findViewById(R.id.algorithm); mKeyId = (TextView) findViewById(R.id.keyId); mCreationDate = (TextView) findViewById(R.id.creation); - mExpiryDateButton = (BootstrapButton) findViewById(R.id.expiry); + mExpiryDateButton = (Button) findViewById(R.id.expiry); - mDeleteButton = (BootstrapButton) findViewById(R.id.delete); + mDeleteButton = (ImageButton) findViewById(R.id.delete); mDeleteButton.setOnClickListener(this); mChkCertify = (CheckBox) findViewById(R.id.chkCertify); mChkCertify.setOnCheckedChangeListener(mCheckChanged); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java index dc4c13b1a..3fd01958a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java @@ -22,17 +22,16 @@ import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; -import com.beardedhen.androidbootstrap.BootstrapButton; - import org.sufficientlysecure.keychain.R; public class KeyServerEditor extends LinearLayout implements Editor, OnClickListener { private EditorListener mEditorListener = null; - BootstrapButton mDeleteButton; + ImageButton mDeleteButton; TextView mServer; public KeyServerEditor(Context context) { @@ -50,7 +49,7 @@ public class KeyServerEditor extends LinearLayout implements Editor, OnClickList mServer = (TextView) findViewById(R.id.server); - mDeleteButton = (BootstrapButton) findViewById(R.id.delete); + mDeleteButton = (ImageButton) findViewById(R.id.delete); mDeleteButton.setOnClickListener(this); super.onFinishInflate(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index b7336318f..4ecc96cee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -32,8 +32,7 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.ImageButton; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; @@ -52,7 +51,7 @@ import java.util.Vector; public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Editor { private LayoutInflater mInflater; - private BootstrapButton mPlusButton; + private ImageButton mPlusButton; private ViewGroup mEditors; private TextView mTitle; private int mType = 0; @@ -126,7 +125,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor setDrawingCacheEnabled(true); setAlwaysDrawnWithCacheEnabled(true); - mPlusButton = (BootstrapButton) findViewById(R.id.plusbutton); + mPlusButton = (ImageButton) findViewById(R.id.plusbutton); mPlusButton.setOnClickListener(this); mEditors = (ViewGroup) findViewById(R.id.editors); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java index 9781dd213..9b561f819 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java @@ -31,8 +31,7 @@ import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RadioButton; - -import com.beardedhen.androidbootstrap.BootstrapButton; +import android.widget.ImageButton; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ContactHelper; @@ -43,7 +42,7 @@ import java.util.regex.Matcher; public class UserIdEditor extends LinearLayout implements Editor, OnClickListener { private EditorListener mEditorListener = null; - private BootstrapButton mDeleteButton; + private ImageButton mDeleteButton; private RadioButton mIsMainUserId; private String mOriginalID; private EditText mName; @@ -103,7 +102,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene setDrawingCacheEnabled(true); setAlwaysDrawnWithCacheEnabled(true); - mDeleteButton = (BootstrapButton) findViewById(R.id.delete); + mDeleteButton = (ImageButton) findViewById(R.id.delete); mDeleteButton.setOnClickListener(this); mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId); mIsMainUserId.setOnClickListener(this); @@ -119,7 +118,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene mEmail.setAdapter( new ArrayAdapter<String> (this.getContext(), android.R.layout.simple_dropdown_item_1line, - ContactHelper.getMailAccounts(getContext()) + ContactHelper.getPossibleUserEmails(getContext()) )); mEmail.addTextChangedListener(new TextWatcher(){ @Override diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png Binary files differnew file mode 100644 index 000000000..7cc407315 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png Binary files differnew file mode 100644 index 000000000..e9d2dcb46 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png Binary files differnew file mode 100644 index 000000000..29f4de211 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_new_account.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_new_account.png Binary files differnew file mode 100644 index 000000000..790af372d --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_new_account.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_not_secure.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_not_secure.png Binary files differnew file mode 100644 index 000000000..5ee148080 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_not_secure.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_view_as_list.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_view_as_list.png Binary files differindex 86da228e9..e08afae85 100644 --- a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_view_as_list.png +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_view_as_list.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png Binary files differnew file mode 100644 index 000000000..2bf88c183 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png Binary files differnew file mode 100644 index 000000000..4ac28f270 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png Binary files differnew file mode 100644 index 000000000..bb46bb315 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_new_account.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_new_account.png Binary files differnew file mode 100644 index 000000000..69c801dcc --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_new_account.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_not_secure.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_not_secure.png Binary files differnew file mode 100644 index 000000000..dd5289ee4 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_not_secure.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_view_as_list.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_view_as_list.png Binary files differindex ccb4c7d7b..4fe0edfa3 100644 --- a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_view_as_list.png +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_view_as_list.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/minus.png b/OpenKeychain/src/main/res/drawable-mdpi/minus.png Binary files differnew file mode 100644 index 000000000..d59e4a3e1 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/minus.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/plus.png b/OpenKeychain/src/main/res/drawable-mdpi/plus.png Binary files differnew file mode 100644 index 000000000..88ee823af --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/plus.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png Binary files differnew file mode 100644 index 000000000..f1ec295d2 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png Binary files differnew file mode 100644 index 000000000..60ac6b066 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png Binary files differnew file mode 100644 index 000000000..76937f57a --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_new_account.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_new_account.png Binary files differnew file mode 100644 index 000000000..c6dfd0bcb --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_new_account.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_not_secure.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_not_secure.png Binary files differnew file mode 100644 index 000000000..312a230e7 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_not_secure.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_view_as_list.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_view_as_list.png Binary files differindex b9c93c8c2..a38638e4d 100644 --- a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_view_as_list.png +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_view_as_list.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/minus.png b/OpenKeychain/src/main/res/drawable-xhdpi/minus.png Binary files differnew file mode 100644 index 000000000..8a98ea967 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/minus.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/plus.png b/OpenKeychain/src/main/res/drawable-xhdpi/plus.png Binary files differnew file mode 100644 index 000000000..def608491 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/plus.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png Binary files differnew file mode 100644 index 000000000..da24654eb --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png Binary files differnew file mode 100644 index 000000000..76ec594dc --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png Binary files differnew file mode 100644 index 000000000..22003198b --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_new_account.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_new_account.png Binary files differnew file mode 100644 index 000000000..38589ba0e --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_new_account.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_not_secure.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_not_secure.png Binary files differnew file mode 100644 index 000000000..4aa9dc85c --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_not_secure.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_view_as_list.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_view_as_list.png Binary files differindex 460041640..b00a85f6d 100644 --- a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_view_as_list.png +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_view_as_list.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/minus.png b/OpenKeychain/src/main/res/drawable-xxhdpi/minus.png Binary files differnew file mode 100644 index 000000000..c46bf00de --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/minus.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/plus.png b/OpenKeychain/src/main/res/drawable-xxhdpi/plus.png Binary files differnew file mode 100644 index 000000000..e1f6e841f --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/plus.png diff --git a/OpenKeychain/src/main/res/drawable/button_edgy.xml b/OpenKeychain/src/main/res/drawable/button_edgy.xml new file mode 100644 index 000000000..fdb94d40e --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/button_edgy.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <solid android:color="#ebebeb" /> + <stroke android:color="#cccccc" android:width="1.5dip" /> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <solid android:color="#ebebeb"/> + <stroke android:color="#cccccc" android:width="1.5dip" /> + </shape> + </item> + <item > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <solid android:color="#ffffff" /> + <stroke android:color="#cccccc" android:width="1.5dip" /> + </shape> + </item> +</selector>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/drawable/button_no_style.xml b/OpenKeychain/src/main/res/drawable/button_no_style.xml new file mode 100644 index 000000000..e9571c2b0 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/button_no_style.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + +</selector>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/drawable/button_rounded.xml b/OpenKeychain/src/main/res/drawable/button_rounded.xml new file mode 100644 index 000000000..f547b8cdb --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/button_rounded.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <stroke android:color="#cccccc" android:width="1.5dip" /> + <stroke android:color="#ebebeb" /> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <stroke android:color="#cccccc" android:width="1.5dip" /> + <solid android:color="#ebebeb"/> + </shape> + </item> + <item > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <stroke android:color="#cccccc" android:width="1.5dip" /> + <solid android:color="#ffffff" /> + </shape> + </item> +</selector>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/drawable/button_rounded_green.xml b/OpenKeychain/src/main/res/drawable/button_rounded_green.xml new file mode 100644 index 000000000..fc12fdf05 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/button_rounded_green.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <solid android:color="#47a447" /> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <solid android:color="#47a447"/> + </shape> + </item> + <item > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <solid android:color="#5cb85c" /> + </shape> + </item> +</selector>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/drawable/button_rounded_red.xml b/OpenKeychain/src/main/res/drawable/button_rounded_red.xml new file mode 100644 index 000000000..330e83939 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/button_rounded_red.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <solid android:color="#d2322d" /> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <solid android:color="#d2322d"/> + </shape> + </item> + <item > + <shape android:shape="rectangle" > + <padding + android:bottom="6dip" + android:left="6dip" + android:right="6dip" + android:top="6dip" /> + <corners android:radius="6dip" /> + <solid android:color="#d9534f" /> + </shape> + </item> +</selector>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml b/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml new file mode 100644 index 000000000..502ca1c70 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:stretchColumns="1"> + + <TableRow android:layout_marginBottom="5dip"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:padding="4dp" + android:text="Name" /> + + <EditText + android:id="@+id/name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:imeOptions="actionNext" + android:padding="4dp" /> + </TableRow> + + <TableRow android:layout_marginBottom="10dip"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:padding="4dp" + android:text="Email" /> + + <EditText + android:id="@+id/address" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:imeOptions="actionNext" + android:padding="4dp" /> + </TableRow> + + <TableRow android:layout_marginBottom="10dip"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:padding="4dp" + android:text="Comment" /> + + <EditText + android:id="@+id/comment" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:imeOptions="actionDone" + android:padding="4dp" /> + </TableRow> + +</TableLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_account_settings_fragment.xml b/OpenKeychain/src/main/res/layout/api_account_settings_fragment.xml index 32843eb29..7bb861547 100644 --- a/OpenKeychain/src/main/res/layout/api_account_settings_fragment.xml +++ b/OpenKeychain/src/main/res/layout/api_account_settings_fragment.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" @@ -43,7 +42,7 @@ android:layout_height="wrap_content" tools:layout="@layout/select_secret_key_layout_fragment" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/api_account_settings_create_key" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -52,9 +51,9 @@ android:layout_marginRight="4dp" android:layout_marginTop="4dp" android:text="@string/api_settings_create_key" - bootstrapbutton:bb_icon_left="fa-key" - bootstrapbutton:bb_size="default" - bootstrapbutton:bb_type="default" /> + android:background="@drawable/button_edgy" + android:drawableLeft="@drawable/ic_action_accounts" + android:textSize="14dip"/> <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout android:layout_width="match_parent" diff --git a/OpenKeychain/src/main/res/layout/decrypt_content.xml b/OpenKeychain/src/main/res/layout/decrypt_content.xml index 866857143..ff75f20ee 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_content.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_content.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - <include layout="@layout/notification_area"/> + <include layout="@layout/notify_area"/> <android.support.v4.view.ViewPager android:id="@+id/decrypt_pager" diff --git a/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml index d1db1c782..098aaaea1 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> @@ -43,15 +42,14 @@ android:minLines="2" android:scrollbars="vertical" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/decrypt_file_browse" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" - bootstrapbutton:bb_icon_left="fa-folder-open" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="default" - bootstrapbutton:bb_type="default" /> + android:src="@drawable/ic_action_collection" + android:background="@drawable/button_rounded" + android:layout_gravity="center_vertical"/> </LinearLayout> <CheckBox diff --git a/OpenKeychain/src/main/res/layout/decrypt_result_include.xml b/OpenKeychain/src/main/res/layout/decrypt_result_include.xml index 3bc78d325..05877656b 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_result_include.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_result_include.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:id="@+id/result" android:orientation="vertical" android:layout_width="match_parent" @@ -83,16 +82,15 @@ android:layout_toRightOf="@+id/result_signature_image" android:textColor="@color/white" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/lookup_key" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_lookup_key" - bootstrapbutton:bb_icon_left="fa-download" - bootstrapbutton:bb_type="info" - bootstrapbutton:bb_size="small" + android:drawableRight="@drawable/ic_action_download" android:layout_alignParentRight="true" - android:layout_centerVertical="true" /> + android:layout_centerVertical="true" + android:background="@drawable/button_edgy"/> </RelativeLayout> diff --git a/OpenKeychain/src/main/res/layout/drawer_list_item.xml b/OpenKeychain/src/main/res/layout/drawer_list_item.xml index 72f4fec50..4719483da 100644 --- a/OpenKeychain/src/main/res/layout/drawer_list_item.xml +++ b/OpenKeychain/src/main/res/layout/drawer_list_item.xml @@ -3,17 +3,15 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - <com.beardedhen.androidbootstrap.FontAwesomeText + <ImageView android:id="@+id/drawer_item_icon" + android:gravity="center_vertical" android:layout_width="30dp" android:layout_height="wrap_content" - android:gravity="center_vertical" - android:textSize="24sp" android:layout_marginLeft="8dp" - fontawesometext:fa_icon="fa-github" - android:layout_centerVertical="true" + android:layout_alignParentStart="true" android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" /> + android:layout_centerVertical="true" /> <TextView android:id="@+id/drawer_item_text" @@ -28,6 +26,6 @@ android:textAppearance="@android:style/TextAppearance.Medium" android:textColor="#111" android:layout_alignParentTop="true" - android:layout_toRightOf="@+id/drawer_item_icon" /> + android:layout_toRightOf="@id/drawer_item_icon"/> </RelativeLayout> diff --git a/OpenKeychain/src/main/res/layout/edit_key_activity.xml b/OpenKeychain/src/main/res/layout/edit_key_activity.xml index 1ce5c096f..b6c5a1c9a 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_activity.xml @@ -26,14 +26,14 @@ android:layout_height="wrap_content" android:text="@string/label_no_passphrase" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/edit_key_btn_change_passphrase" android:layout_width="match_parent" android:layout_height="60dp" android:padding="4dp" android:text="@string/btn_set_passphrase" - bootstrapbutton:bb_icon_left="fa-pencil" - bootstrapbutton:bb_type="default" /> + android:drawableLeft="@drawable/ic_action_edit" + android:background="@drawable/button_edgy" /> <LinearLayout android:id="@+id/edit_key_container" diff --git a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml index f652269e5..7f94cb3cd 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml @@ -45,6 +45,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + <org.sufficientlysecure.keychain.ui.widget.FixedListView android:id="@+id/edit_key_user_ids_added" android:layout_width="match_parent" @@ -82,6 +87,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + <org.sufficientlysecure.keychain.ui.widget.FixedListView android:id="@+id/edit_key_keys_added" android:layout_width="match_parent" diff --git a/OpenKeychain/src/main/res/layout/edit_key_key_item.xml b/OpenKeychain/src/main/res/layout/edit_key_key_item.xml index 090115d62..81fb643ab 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_key_item.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_key_item.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <org.sufficientlysecure.keychain.ui.widget.KeyEditor xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > @@ -80,13 +79,12 @@ android:paddingRight="10dip" android:text="@string/label_expiry" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/expiry" android:layout_width="match_parent" android:layout_height="40dp" android:text="@string/none" - bootstrapbutton:bb_size="small" - bootstrapbutton:bb_type="default" /> + android:background="@drawable/button_edgy" /> </TableRow> <TableRow @@ -155,15 +153,13 @@ </TableRow> </TableLayout> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" - bootstrapbutton:bb_icon_left="fa-minus" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="small" - bootstrapbutton:bb_type="danger" /> + android:src="@drawable/minus" + android:background="@drawable/button_rounded_red"/> </LinearLayout> <View diff --git a/OpenKeychain/src/main/res/layout/edit_key_section.xml b/OpenKeychain/src/main/res/layout/edit_key_section.xml index 9f10ff8c1..6cfe18bd6 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_section.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_section.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <org.sufficientlysecure.keychain.ui.widget.SectionView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > @@ -23,15 +22,13 @@ android:singleLine="true" android:text="Section Name" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/plusbutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" - bootstrapbutton:bb_icon_left="fa-plus" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="small" - bootstrapbutton:bb_type="success" /> + android:src="@drawable/plus" + android:background="@drawable/button_rounded_green"/> </LinearLayout> <LinearLayout diff --git a/OpenKeychain/src/main/res/layout/edit_key_user_id_item.xml b/OpenKeychain/src/main/res/layout/edit_key_user_id_item.xml index a8d1dc674..3454d3668 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_user_id_item.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_user_id_item.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <org.sufficientlysecure.keychain.ui.widget.UserIdEditor xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > @@ -76,18 +75,16 @@ </TableRow> </TableLayout> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:layout_margin="10dp" + android:layout_margin="10dip" android:layout_marginLeft="4dip" android:layout_marginRight="6dip" - bootstrapbutton:bb_icon_left="fa-minus" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="small" - bootstrapbutton:bb_type="danger" /> + android:src="@drawable/minus" + android:background="@drawable/button_rounded_red" /> </LinearLayout> <View diff --git a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml index fa1b03889..cde92b477 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" @@ -65,15 +64,14 @@ android:text="@string/label_select_public_keys" android:textAppearance="?android:attr/textAppearanceMedium" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/btn_selectEncryptKeys" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="4dp" android:text="@string/select_keys_button_default" - bootstrapbutton:bb_icon_left="fa-user" - bootstrapbutton:bb_size="default" - bootstrapbutton:bb_type="default" /> + android:background="@drawable/button_edgy" + android:drawableLeft="@drawable/ic_action_person" /> </LinearLayout> </LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml index c8aaf77b8..4142b3de6 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml @@ -31,15 +31,14 @@ android:minLines="2" android:scrollbars="vertical" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/btn_browse" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" - bootstrapbutton:bb_icon_left="fa-folder-open" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="default" - bootstrapbutton:bb_type="default" /> + android:layout_gravity="center_vertical" + android:src="@drawable/ic_action_collection" + android:background="@drawable/button_rounded"/> </LinearLayout> <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout diff --git a/OpenKeychain/src/main/res/layout/file_dialog.xml b/OpenKeychain/src/main/res/layout/file_dialog.xml index 83d697001..dcf711679 100644 --- a/OpenKeychain/src/main/res/layout/file_dialog.xml +++ b/OpenKeychain/src/main/res/layout/file_dialog.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" @@ -31,17 +30,15 @@ android:minLines="2" android:scrollbars="vertical" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/btn_browse" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="4dp" android:contentDescription="@string/filemanager_title_open" - bootstrapbutton:bb_icon_left="fa-folder-open" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="default" - bootstrapbutton:bb_type="default" /> + android:background="@drawable/button_rounded" + android:src="@drawable/ic_action_collection"/> </LinearLayout> <CheckBox diff --git a/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml b/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml index 2b863d52b..3d2fb688b 100644 --- a/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml +++ b/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:fontawesometext="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -12,23 +11,21 @@ android:orientation="horizontal" android:clickable="true"> - <com.beardedhen.androidbootstrap.FontAwesomeText + <ImageButton android:id="@+id/foldableIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_gravity="center_vertical" android:layout_marginRight="10dp" - android:textSize="12sp" - android:paddingTop="@dimen/padding_medium" - android:paddingBottom="@dimen/padding_medium" - fontawesometext:fa_icon="fa-chevron-right"/> + android:src="@drawable/ic_action_expand" + android:background="@drawable/button_no_style"/> <TextView android:id="@+id/foldableText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/none" - android:paddingTop="@dimen/padding_medium" - android:paddingBottom="@dimen/padding_medium" + android:layout_gravity="center_vertical" android:textColor="@color/emphasis"/> </LinearLayout> diff --git a/OpenKeychain/src/main/res/layout/import_keys_activity.xml b/OpenKeychain/src/main/res/layout/import_keys_activity.xml index b076debfe..81aa6d792 100644 --- a/OpenKeychain/src/main/res/layout/import_keys_activity.xml +++ b/OpenKeychain/src/main/res/layout/import_keys_activity.xml @@ -4,11 +4,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - <LinearLayout - android:id="@+id/card_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" /> + <include layout="@layout/notify_area"/> <org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout android:id="@+id/import_sliding_tab_layout" diff --git a/OpenKeychain/src/main/res/layout/key_list_fragment.xml b/OpenKeychain/src/main/res/layout/key_list_fragment.xml index c02854668..32b77baac 100644 --- a/OpenKeychain/src/main/res/layout/key_list_fragment.xml +++ b/OpenKeychain/src/main/res/layout/key_list_fragment.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> @@ -49,14 +48,15 @@ android:text="@string/key_list_empty_text2" android:textAppearance="?android:attr/textAppearanceSmall" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/key_list_empty_button_create" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" + android:textSize="14sp" android:text="@string/key_list_empty_button_create" - bootstrapbutton:bb_icon_left="fa-plus" - bootstrapbutton:bb_type="default" /> + android:drawableLeft="@drawable/ic_action_new_account" + android:background="@drawable/button_edgy"/> <TextView android:layout_width="wrap_content" @@ -66,14 +66,15 @@ android:text="@string/key_list_empty_text3" android:textAppearance="?android:attr/textAppearanceSmall" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/key_list_empty_button_import" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" + android:textSize="14sp" android:text="@string/key_list_empty_button_import" - bootstrapbutton:bb_icon_left="fa-download" - bootstrapbutton:bb_type="default" /> + android:drawableLeft="@drawable/ic_action_download" + android:background="@drawable/button_edgy" /> </LinearLayout> </FrameLayout> diff --git a/OpenKeychain/src/main/res/layout/key_server_editor.xml b/OpenKeychain/src/main/res/layout/key_server_editor.xml index 950978a0e..b07fdc50c 100644 --- a/OpenKeychain/src/main/res/layout/key_server_editor.xml +++ b/OpenKeychain/src/main/res/layout/key_server_editor.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <org.sufficientlysecure.keychain.ui.widget.KeyServerEditor xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > @@ -18,17 +17,15 @@ android:layout_weight="1" android:inputType="textUri" /> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="10dp" android:layout_marginRight="3dip" - bootstrapbutton:bb_icon_left="fa-minus" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="small" - bootstrapbutton:bb_type="danger" /> + android:background="@drawable/button_rounded_red" + android:src="@drawable/minus" /> </LinearLayout> <View diff --git a/OpenKeychain/src/main/res/layout/key_server_preference.xml b/OpenKeychain/src/main/res/layout/key_server_preference.xml index b8897a7b3..baf7111af 100644 --- a/OpenKeychain/src/main/res/layout/key_server_preference.xml +++ b/OpenKeychain/src/main/res/layout/key_server_preference.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > @@ -42,7 +41,7 @@ android:textAppearance="?android:attr/textAppearanceSmall" /> </RelativeLayout> - <com.beardedhen.androidbootstrap.BootstrapButton + <ImageButton android:id="@+id/add" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -50,10 +49,8 @@ android:layout_margin="10dp" android:layout_marginLeft="4dip" android:layout_marginRight="6dip" - bootstrapbutton:bb_icon_left="fa-plus" - bootstrapbutton:bb_roundedCorners="true" - bootstrapbutton:bb_size="small" - bootstrapbutton:bb_type="success" /> + android:src="@drawable/plus" + android:background="@drawable/button_rounded_green"/> </LinearLayout> <View diff --git a/OpenKeychain/src/main/res/layout/notification_area.xml b/OpenKeychain/src/main/res/layout/notify_area.xml index d1ba265a5..d1ba265a5 100644 --- a/OpenKeychain/src/main/res/layout/notification_area.xml +++ b/OpenKeychain/src/main/res/layout/notify_area.xml diff --git a/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml b/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml index cc2ab0cac..63eeb8eaf 100644 --- a/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml +++ b/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml @@ -1,11 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> - <com.beardedhen.androidbootstrap.BootstrapButton + <Button android:id="@+id/select_secret_key_select_key_button" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -14,9 +13,9 @@ android:layout_marginRight="4dp" android:layout_marginTop="4dp" android:text="@string/api_settings_select_key" - bootstrapbutton:bb_icon_left="fa-key" - bootstrapbutton:bb_size="default" - bootstrapbutton:bb_type="default" /> + android:drawableLeft="@drawable/ic_action_accounts" + android:background="@drawable/button_edgy" + android:textSize="14dp"/> <LinearLayout android:layout_width="match_parent" diff --git a/OpenKeychain/src/main/res/layout/view_key_activity.xml b/OpenKeychain/src/main/res/layout/view_key_activity.xml index 5aa1cd167..481b1ddf5 100644 --- a/OpenKeychain/src/main/res/layout/view_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/view_key_activity.xml @@ -4,6 +4,12 @@ android:layout_height="match_parent" android:orientation="vertical"> + <LinearLayout + android:id="@+id/card_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" /> + <TextView android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/OpenKeychain/src/main/res/layout/wizard_activity.xml b/OpenKeychain/src/main/res/layout/wizard_activity.xml new file mode 100644 index 000000000..299d07a76 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/wizard_activity.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:id="@+id/wizard_buttons" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:orientation="horizontal"> + + <Button + android:id="@+id/wizard_back" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:onClick="backOnClick" + android:text="cancel" + style="@style/SelectableItem" /> + + <View + android:layout_width="1dip" + android:layout_height="match_parent" + android:layout_marginBottom="4dip" + android:layout_marginTop="4dip" + android:background="?android:attr/listDivider" /> + + <Button + android:id="@+id/wizard_next" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:onClick="nextOnClick" + android:text="next" + style="@style/SelectableItem" /> + </LinearLayout> + + <View + android:id="@+id/wizard_progress_line" + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_above="@+id/wizard_buttons" + android:layout_marginLeft="4dip" + android:layout_marginRight="4dip" + android:background="?android:attr/listDivider" + android:visibility="gone" /> + + <LinearLayout + android:id="@+id/wizard_progress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_above="@+id/wizard_progress_line" + android:visibility="gone"> + + <ProgressBar + android:id="@+id/wizard_progress_progressbar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <ImageView + android:id="@+id/wizard_progress_image" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/icon_light_refresh" /> + + <TextView + android:id="@+id/wizard_progress_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:text="asd" + android:textAppearance="?android:attr/textAppearanceMedium" /> + </LinearLayout> + + <View + android:id="@+id/wizard_line2" + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_above="@+id/wizard_progress" + android:layout_marginLeft="4dip" + android:layout_marginRight="4dip" + android:background="?android:attr/listDivider" /> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_above="@+id/wizard_line2"> + + <LinearLayout + android:id="@+id/wizard_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp" /> + </ScrollView> + +</RelativeLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/wizard_create_key_fragment.xml b/OpenKeychain/src/main/res/layout/wizard_create_key_fragment.xml new file mode 100644 index 000000000..258ea7223 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/wizard_create_key_fragment.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="4dp" + android:text="Enter Full Name, Email and Passphrase!" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <AutoCompleteTextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPersonName" + android:hint="Name" + android:ems="10" + android:id="@+id/name" /> + + <AutoCompleteTextView + android:id="@+id/email" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="bla@example.com" + android:layout_weight="1" + android:ems="10" + android:inputType="textEmailAddress" /> + + <EditText + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:hint="passphrase" + android:ems="10" + android:id="@+id/passphrase" + android:layout_gravity="center_horizontal" /> + + +</LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/wizard_k9_fragment.xml b/OpenKeychain/src/main/res/layout/wizard_k9_fragment.xml new file mode 100644 index 000000000..342adc37e --- /dev/null +++ b/OpenKeychain/src/main/res/layout/wizard_k9_fragment.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <org.sufficientlysecure.htmltextview.HtmlTextView + android:id="@+id/wizard_k9_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="4dp" + android:text="Text..." + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <RadioGroup + android:id="@+id/wizard_k9_radio_group" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <RadioButton + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:checked="true" + android:textAppearance="?android:attr/textAppearanceMedium" + style="@style/SelectableItem" + android:text="install K9" + android:id="@+id/wizard_k9_install" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + + <RadioButton + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:textAppearance="?android:attr/textAppearanceMedium" + style="@style/SelectableItem" + android:text="skip install" + android:id="@+id/wizard_k9_skip" /> + </RadioGroup> + +</LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/wizard_start_fragment.xml b/OpenKeychain/src/main/res/layout/wizard_start_fragment.xml new file mode 100644 index 000000000..9e1403f74 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/wizard_start_fragment.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="4dp" + android:text="Welcome to OpenKeychain" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <TextView + style="@style/SectionHeader" + android:layout_width="wrap_content" + android:layout_height="0dp" + android:layout_marginTop="14dp" + android:text="What you wanna do today?" + android:layout_weight="1" /> + + <RadioGroup + android:id="@+id/wizard_start_radio_group" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <RadioButton + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:checked="true" + android:textAppearance="?android:attr/textAppearanceMedium" + style="@style/SelectableItem" + android:text="new key" + android:id="@+id/wizard_start_new_key" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + + <RadioButton + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:textAppearance="?android:attr/textAppearanceMedium" + style="@style/SelectableItem" + android:text="import existing key" + android:id="@+id/wizard_start_import" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + + <RadioButton + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:textAppearance="?android:attr/textAppearanceMedium" + style="@style/SelectableItem" + android:text="skip wizard" + android:id="@+id/wizard_start_skip" /> + </RadioGroup> + +</LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/raw/help_faq.html b/OpenKeychain/src/main/res/raw/help_faq.html index e6757d0da..6f8763f36 100644 --- a/OpenKeychain/src/main/res/raw/help_faq.html +++ b/OpenKeychain/src/main/res/raw/help_faq.html @@ -12,5 +12,13 @@ And don't add newlines before or after p tags because of transifex --> <h2>A wrong primary user id is shown when searching on a Keyserver</h2> <p>Unfortunately, this is a bug in the SKS Keyserver software. Its machine-readable output returns the user ids in an arbitrary order. Read the <a href="https://bitbucket.org/skskeyserver/sks-keyserver/issue/28/primary-uid-in-machine-readable-index">related bug report</a> for more information.</p> +<h2>How do I activate OpenKeychain in K9-Mail?</h2> +<p>To use OpenKeychain with K9-Mail, you want to follow these steps:</p> +<ol> + <li>Open K9-Mail and long-tap on the account you want to use OpenKeychain with.</li> + <li>Select "Account settings" and scroll to the very bottom and click "Cryptography".</li> + <li>Click on "OpenPGP Provider" and select OpenKeychain from the list.</li> +</ol> +<p>Thats it.</p> </body> </html> diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 5600aa06e..25cdfb541 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -9,8 +9,9 @@ <string name="title_authentication">Passphrase</string> <string name="title_create_key">Create Key</string> <string name="title_edit_key">Edit Key</string> + <string name="title_wizard">Welcome to OpenKeychain</string> <string name="title_preferences">Preferences</string> - <string name="title_api_registered_apps">Registered Applications</string> + <string name="title_api_registered_apps">Apps</string> <string name="title_key_server_preference">Keyserver Preference</string> <string name="title_change_passphrase">Change Passphrase</string> <string name="title_set_passphrase">Set Passphrase</string> @@ -388,19 +389,19 @@ <!-- Import result toast --> <plurals name="import_keys_added_and_updated_1"> - <item quantity="one">Successfully added %1$d key</item> - <item quantity="other">Successfully added %1$d keys</item> + <item quantity="one">Successfully imported key</item> + <item quantity="other">Successfully imported %1$d keys</item> </plurals> <plurals name="import_keys_added_and_updated_2"> - <item quantity="one"> and updated %1$d key%2$s.</item> + <item quantity="one"> and updated key%2$s.</item> <item quantity="other"> and updated %1$d keys%2$s.</item> </plurals> <plurals name="import_keys_added"> - <item quantity="one">Successfully added %1$d key%2$s.</item> - <item quantity="other">Successfully added %1$d keys%2$s.</item> + <item quantity="one">Successfully imported key%2$s.</item> + <item quantity="other">Successfully imported %1$d keys%2$s.</item> </plurals> <plurals name="import_keys_updated"> - <item quantity="one">Successfully updated %1$d key%2$s.</item> + <item quantity="one">Successfully updated key%2$s.</item> <item quantity="other">Successfully updated %1$d keys%2$s.</item> </plurals> <string name="import_view_log">View Log</string> @@ -477,7 +478,7 @@ <string name="nav_encrypt">Sign and Encrypt</string> <string name="nav_decrypt">Decrypt and Verify</string> <string name="nav_import">Import Keys</string> - <string name="nav_apps">Registered Apps</string> + <string name="nav_apps">Apps</string> <string name="drawer_open">Open navigation drawer</string> <string name="drawer_close">Close navigation drawer</string> <string name="edit">Edit</string> @@ -542,8 +543,15 @@ <string name="msg_ip_uid_cert_bad">Encountered bad certificate!</string> <string name="msg_ip_uid_cert_error">Error processing certificate!</string> <string name="msg_ip_uid_cert_good">User id is certified by %1$s (%2$s)</string> - <string name="msg_ip_uid_certs_unknown">Ignoring %s certificates from unknown pubkeys</string> - <string name="msg_ip_uid_classifying">Classifying user ids, using %s trusted signatures</string> + <plurals name="msg_ip_uid_certs_unknown"> + <item quantity="one">Ignoring one certificate issued by an unknown public key</item> + <item quantity="other">Ignoring %s certificates issued by unknown public keys</item> + </plurals> + <plurals name="msg_ip_uid_classifying"> + <item quantity="zero">Classifying user ids (no trusted keys available)</item> + <item quantity="one">Classifying user ids (using one trusted key)</item> + <item quantity="other">Classifying user ids (using %s trusted keys)</item> + </plurals> <string name="msg_ip_uid_reorder">Re-ordering user ids</string> <string name="msg_ip_uid_processing">Processing user id %s</string> <string name="msg_ip_uid_revoked">User id is revoked</string> @@ -588,9 +596,15 @@ <string name="msg_kc_sub_revoke_bad">Removing bad subkey revocation certificate</string> <string name="msg_kc_sub_revoke_dup">Removing redundant subkey revocation certificate</string> <string name="msg_kc_success">Keyring canonicalization successful, no changes</string> - <string name="msg_kc_success_bad">Keyring canonicalization successful, removed %s erroneous certificates</string> + <plurals name="msg_kc_success_bad"> + <item quantity="one">Keyring canonicalization successful, removed one erroneous certificate</item> + <item quantity="other">Keyring canonicalization successful, removed %d erroneous certificates</item> + </plurals> <string name="msg_kc_success_bad_and_red">Keyring canonicalization successful, removed %1$s erroneous and %2$s redundant certificates</string> - <string name="msg_kc_success_redundant">Keyring canonicalization successful, removed %s redundant certificates</string> + <plurals name="msg_kc_success_redundant"> + <item quantity="one">Keyring canonicalization successful, removed one redundant certificate</item> + <item quantity="other">Keyring canonicalization successful, removed %d redundant certificates</item> + </plurals> <string name="msg_kc_uid_bad_err">Removing bad self certificate for user id %s</string> <string name="msg_kc_uid_bad_local">Removing user id certificate with "local" flag</string> <string name="msg_kc_uid_bad_time">Removing user id with future timestamp</string> diff --git a/OpenKeychain/src/test/java/tests/ProviderHelperKeyringTest.java b/OpenKeychain/src/test/java/tests/ProviderHelperKeyringTest.java index 265e01170..3d48c2f97 100644 --- a/OpenKeychain/src/test/java/tests/ProviderHelperKeyringTest.java +++ b/OpenKeychain/src/test/java/tests/ProviderHelperKeyringTest.java @@ -1,5 +1,10 @@ package tests; +import java.util.Collections; +import java.util.Arrays; +import java.util.Collection; +import java.util.ArrayList; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -14,7 +19,68 @@ public class ProviderHelperKeyringTest { @Test public void testSavePublicKeyring() throws Exception { - Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring()); + Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(Collections.singleton( + "/public-key-for-sample.blob" + ))); + } + + @Test + public void testSavePublicKeyringRsa() throws Exception { + Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(prependResourcePath(Arrays.asList( + "000001-006.public_key", + "000002-013.user_id", + "000003-002.sig", + "000004-012.ring_trust", + "000005-002.sig", + "000006-012.ring_trust", + "000007-002.sig", + "000008-012.ring_trust", + "000009-002.sig", + "000010-012.ring_trust", + "000011-002.sig", + "000012-012.ring_trust", + "000013-014.public_subkey", + "000014-002.sig", + "000015-012.ring_trust" + )))); } + @Test + public void testSavePublicKeyringDsa() throws Exception { + Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(prependResourcePath(Arrays.asList( + "000016-006.public_key", + "000017-002.sig", + "000018-012.ring_trust", + "000019-013.user_id", + "000020-002.sig", + "000021-012.ring_trust", + "000022-002.sig", + "000023-012.ring_trust", + "000024-014.public_subkey", + "000025-002.sig", + "000026-012.ring_trust" + )))); + } + + @Test + public void testSavePublicKeyringDsa2() throws Exception { + Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(prependResourcePath(Arrays.asList( + "000027-006.public_key", + "000028-002.sig", + "000029-012.ring_trust", + "000030-013.user_id", + "000031-002.sig", + "000032-012.ring_trust", + "000033-002.sig", + "000034-012.ring_trust" + )))); + } + + private static Collection<String> prependResourcePath(Collection<String> files) { + Collection<String> prependedFiles = new ArrayList<String>(); + for (String file: files) { + prependedFiles.add("/extern/OpenPGP-Haskell/tests/data/" + file); + } + return prependedFiles; + } } diff --git a/OpenKeychain/src/test/resources/extern/OpenPGP-Haskell b/OpenKeychain/src/test/resources/extern/OpenPGP-Haskell new file mode 160000 +Subproject eba7e4fdce3de6622b4ec3862b405b0acd01637 |