diff options
| author | mar-v-in <github@rvin.mooo.com> | 2014-06-24 11:35:59 +0200 | 
|---|---|---|
| committer | mar-v-in <github@rvin.mooo.com> | 2014-06-24 11:35:59 +0200 | 
| commit | 38823b73a31ae0fb82d7e385c141f1170127c4dd (patch) | |
| tree | fec3fd3ac257d1755388d021dbf0d48133dee40e | |
| parent | 9e7e0be82cafc6dc98bbc31099ce0efc36a789a0 (diff) | |
| parent | c865de4002a9751928969ef30a3a5a6f943249cc (diff) | |
| download | open-keychain-38823b73a31ae0fb82d7e385c141f1170127c4dd.tar.gz open-keychain-38823b73a31ae0fb82d7e385c141f1170127c4dd.tar.bz2 open-keychain-38823b73a31ae0fb82d7e385c141f1170127c4dd.zip | |
Merge branch 'master' into improve-file-more
21 files changed, 587 insertions, 86 deletions
| diff --git a/.gitmodules b/.gitmodules index 6b1646b89..f18a8731b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,9 +28,9 @@  [submodule "extern/SuperToasts"]  	path = extern/SuperToasts  	url = https://github.com/open-keychain/SuperToasts.git -[submodule "extern/dnsjava"] -	path = extern/dnsjava -	url = https://github.com/open-keychain/dnsjava.git  [submodule "extern/KeybaseLib"]  	path = extern/KeybaseLib  	url = https://github.com/timbray/KeybaseLib.git +[submodule "extern/minidns"] +	path = extern/minidns +	url = https://github.com/open-keychain/minidns.git diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index ff6f603f4..fd0c4c6ba 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -19,7 +19,7 @@ dependencies {      compile project(':extern:spongycastle:prov')      compile project(':extern:AppMsg:library')      compile project(':extern:SuperToasts:supertoasts') -    compile project(':extern:dnsjava') +    compile project(':extern:minidns')      compile project(':extern:KeybaseLib:Lib') @@ -29,7 +29,6 @@ dependencies {      testCompile 'com.squareup:fest-android:1.0.8'      testCompile 'com.google.android:android:4.1.1.4'      // compile dependencies are automatically also included in testCompile -  }  android { @@ -79,6 +78,11 @@ android {          htmlReport true          htmlOutput file("lint-report.html")      } +     +    // Disable preDexing, causes com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000) on some systems +    dexOptions { +        preDexLibraries = false +    }  }  // NOTE: This disables Lint! diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java index 80f52f914..5d281d5b0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java @@ -57,11 +57,13 @@ public class EmailKeyHelper {              }          } -        // Most users don't have the SRV record, so ask a default server as well -        String[] servers = Preferences.getPreferences(context).getKeyServers(); -        if (servers != null && servers.length != 0) { -            HkpKeyserver hkp = new HkpKeyserver(servers[0]); -            keys.addAll(getEmailKeys(mail, hkp)); +        if (keys.isEmpty()) { +            // Most users don't have the SRV record, so ask a default server as well +            String[] servers = Preferences.getPreferences(context).getKeyServers(); +            if (servers != null && servers.length != 0) { +                HkpKeyserver hkp = new HkpKeyserver(servers[0]); +                keys.addAll(getEmailKeys(mail, hkp)); +            }          }          return new ArrayList<ImportKeysListEntry>(keys);      } 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 2ec9e1c07..e49085a0e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -18,6 +18,10 @@  package org.sufficientlysecure.keychain.keyimport; +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; @@ -33,10 +37,6 @@ import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.pgp.PgpHelper;  import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;  import org.sufficientlysecure.keychain.util.Log; -import org.xbill.DNS.Lookup; -import org.xbill.DNS.Record; -import org.xbill.DNS.SRVRecord; -import org.xbill.DNS.Type;  import java.io.IOException;  import java.io.InputStream; @@ -316,6 +316,12 @@ public class HkpKeyserver extends Keyserver {              while (uidMatcher.find()) {                  String tmp = uidMatcher.group(1).trim();                  if (tmp.contains("%")) { +                    if(tmp.contains("%%")) { +                        // This is a fix for issue #683 +                        // The server encodes a percent sign as %%, so it is swapped out with its +                        // urlencoded counterpart to prevent errors +                        tmp = tmp.replace("%%", "%25"); +                    }                      try {                          // converts Strings like "Universit%C3%A4t" to a proper encoding form "Universität".                          tmp = (URLDecoder.decode(tmp, "UTF8")); @@ -396,19 +402,20 @@ public class HkpKeyserver extends Keyserver {       */      public static HkpKeyserver resolve(String domain) {          try { -            Record[] records = new Lookup("_hkp._tcp." + domain, Type.SRV).run(); +            Record[] records = new Client().query(new Question("_hkp._tcp." + domain, Record.TYPE.SRV)).getAnswers();              if (records.length > 0) {                  Arrays.sort(records, new Comparator<Record>() {                      @Override                      public int compare(Record lhs, Record rhs) { -                        if (!(lhs instanceof SRVRecord)) return 1; -                        if (!(rhs instanceof SRVRecord)) return -1; -                        return ((SRVRecord) lhs).getPriority() - ((SRVRecord) rhs).getPriority(); +                        if (lhs.getPayload().getType() != Record.TYPE.SRV) return 1; +                        if (rhs.getPayload().getType() != Record.TYPE.SRV) return -1; +                        return ((SRV) lhs.getPayload()).getPriority() - ((SRV) rhs.getPayload()).getPriority();                      }                  });                  Record record = records[0]; // This is our best choice -                if (record instanceof SRVRecord) { -                    return new HkpKeyserver(((SRVRecord) record).getTarget().toString(), (short) ((SRVRecord) record).getPort()); +                if (record.getPayload().getType() == Record.TYPE.SRV) { +                    return new HkpKeyserver(((SRV) record.getPayload()).getName(), +                            (short) ((SRV) record.getPayload()).getPort());                  }              }          } catch (Exception ignored) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java index 29ab06264..0ca6f07fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java @@ -42,6 +42,9 @@ public class KeybaseKeyserver extends Keyserver {              // cut off "0x" if a user is searching for a key id              query = query.substring(2);          } +        if (query.isEmpty()) { +            throw new QueryTooShortException(); +        }          mQuery = query;          try { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 47a6cab1d..020b808b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -41,6 +41,11 @@ public class SaveKeyringParcel implements Parcelable {      public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) {          mMasterKeyId = masterKeyId;          mFingerprint = fingerprint; +        addUserIds = new ArrayList<String>(); +        addSubKeys = new ArrayList<SubkeyAdd>(); +        changeSubKeys = new ArrayList<SubkeyChange>(); +        revokeUserIds = new ArrayList<String>(); +        revokeSubKeys = new ArrayList<Long>();      }      // performance gain for using Parcelable here would probably be negligible, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 6c74818a5..7ac229b91 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -53,7 +53,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;  import org.sufficientlysecure.keychain.service.KeychainIntentService;  import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;  import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;  import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;  import org.sufficientlysecure.keychain.util.Log; @@ -75,7 +75,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements      private long mMasterKeyId = 0;      private ListView mUserIds; -    private ViewKeyUserIdsAdapter mUserIdsAdapter; +    private UserIdsAdapter mUserIdsAdapter;      private static final int LOADER_ID_KEYRING = 0;      private static final int LOADER_ID_USER_IDS = 1; @@ -143,13 +143,12 @@ public class CertifyKeyActivity extends ActionBarActivity implements          mUserIds = (ListView) findViewById(R.id.view_key_user_ids); -        mUserIdsAdapter = new ViewKeyUserIdsAdapter(this, null, 0, true); +        mUserIdsAdapter = new UserIdsAdapter(this, null, 0, true);          mUserIds.setAdapter(mUserIdsAdapter);          mUserIds.setOnItemClickListener(mUserIdsAdapter);          getSupportLoaderManager().initLoader(LOADER_ID_KEYRING, null, this);          getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); -      }      static final String USER_IDS_SELECTION = UserIds.IS_REVOKED + " = 0"; @@ -175,7 +174,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements              case LOADER_ID_USER_IDS: {                  Uri uri = UserIds.buildUserIdsUri(mDataUri);                  return new CursorLoader(this, uri, -                        ViewKeyUserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_SELECTION, null, null); +                        UserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_SELECTION, null, null);              }          }          return null; 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 9231ce142..ac4390eac 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -20,6 +20,9 @@ package org.sufficientlysecure.keychain.ui;  import android.database.Cursor;  import android.net.Uri;  import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger;  import android.support.v4.app.LoaderManager;  import android.support.v4.content.CursorLoader;  import android.support.v4.content.Loader; @@ -28,15 +31,23 @@ import android.view.LayoutInflater;  import android.view.View;  import android.view.View.OnClickListener;  import android.view.ViewGroup; +import android.widget.AdapterView;  import android.widget.ListView; +import android.widget.Toast;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;  import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing;  import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter; -import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +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.dialog.AddUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;  import org.sufficientlysecure.keychain.util.Log;  public class EditKeyFragment extends LoaderFragment implements @@ -44,17 +55,24 @@ public class EditKeyFragment extends LoaderFragment implements      public static final String ARG_DATA_URI = "uri"; -    private ListView mUserIds; -    private ListView mKeys; +    private ListView mUserIdsList; +    private ListView mKeysList; +    private ListView mUserIdsAddedList; +    private ListView mKeysAddedList; +    private View mChangePassphrase; +    private View mAddUserId; +    private View mAddKey;      private static final int LOADER_ID_USER_IDS = 0;      private static final int LOADER_ID_KEYS = 1; -    private ViewKeyUserIdsAdapter mUserIdsAdapter; -    private ViewKeyKeysAdapter mKeysAdapter; +    private UserIdsAdapter mUserIdsAdapter; +    private SubkeysAdapter mKeysAdapter;      private Uri mDataUri; +    private SaveKeyringParcel mSaveKeyringParcel; +      /**       * Creates new instance of this fragment       */ @@ -74,9 +92,13 @@ public class EditKeyFragment extends LoaderFragment implements          View root = super.onCreateView(inflater, superContainer, savedInstanceState);          View view = inflater.inflate(R.layout.edit_key_fragment, getContainer()); -        mUserIds = (ListView) view.findViewById(R.id.edit_key_user_ids); -        mKeys = (ListView) view.findViewById(R.id.edit_key_keys); -//        mActionEdit = view.findViewById(R.id.view_key_action_edit); +        mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids); +        mKeysList = (ListView) view.findViewById(R.id.edit_key_keys); +        mUserIdsAddedList = (ListView) view.findViewById(R.id.edit_key_user_ids_added); +        mKeysAddedList = (ListView) view.findViewById(R.id.edit_key_keys_added); +        mChangePassphrase = view.findViewById(R.id.edit_key_action_change_passphrase); +        mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id); +        mAddKey = view.findViewById(R.id.edit_key_action_add_key);          return root;      } @@ -85,7 +107,6 @@ public class EditKeyFragment extends LoaderFragment implements      public void onActivityCreated(Bundle savedInstanceState) {          super.onActivityCreated(savedInstanceState); -          // Inflate a "Done"/"Cancel" custom action bar view          ActionBarHelper.setTwoButtonView(((ActionBarActivity) getActivity()).getSupportActionBar(),                  R.string.btn_save, R.drawable.ic_action_save, @@ -115,23 +136,52 @@ public class EditKeyFragment extends LoaderFragment implements          loadData(dataUri);      } +      private void loadData(Uri dataUri) {          mDataUri = dataUri;          Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); -//        mActionEncrypt.setOnClickListener(new View.OnClickListener() { -//            @Override -//            public void onClick(View v) { -//                encrypt(mDataUri); -//            } -//        }); +        try { +            Uri secretUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); +            WrappedSecretKeyRing keyRing = +                    new ProviderHelper(getActivity()).getWrappedSecretKeyRing(secretUri); + +            mSaveKeyringParcel = new SaveKeyringParcel(keyRing.getMasterKeyId(), +                    keyRing.getUncachedKeyRing().getFingerprint()); +        } catch (ProviderHelper.NotFoundException e) { +            Log.e(Constants.TAG, "Keyring not found: " + e.getMessage(), e); +            Toast.makeText(getActivity(), R.string.error_no_secret_key_found, Toast.LENGTH_SHORT).show(); +            getActivity().finish(); +        } + +        mChangePassphrase.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                changePassphrase(); +            } +        }); +        mAddUserId.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                addUserId(); +            } +        }); -        mUserIdsAdapter = new ViewKeyUserIdsAdapter(getActivity(), null, 0); -        mUserIds.setAdapter(mUserIdsAdapter); -        mKeysAdapter = new ViewKeyKeysAdapter(getActivity(), null, 0); -        mKeys.setAdapter(mKeysAdapter); +        mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, mSaveKeyringParcel); +        mUserIdsList.setAdapter(mUserIdsAdapter); + +        mUserIdsList.setOnItemClickListener(new AdapterView.OnItemClickListener() { +            @Override +            public void onItemClick(AdapterView<?> parent, View view, int position, long id) { +                String userId = mUserIdsAdapter.getUserId(position); +                editUserId(userId); +            } +        }); + +        mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0); +        mKeysList.setAdapter(mKeysAdapter);          // Prepare the loaders. Either re-connect with an existing ones,          // or start new ones. @@ -146,13 +196,13 @@ public class EditKeyFragment extends LoaderFragment implements              case LOADER_ID_USER_IDS: {                  Uri baseUri = KeychainContract.UserIds.buildUserIdsUri(mDataUri);                  return new CursorLoader(getActivity(), baseUri, -                        ViewKeyUserIdsAdapter.USER_IDS_PROJECTION, null, null, null); +                        UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);              }              case LOADER_ID_KEYS: {                  Uri baseUri = KeychainContract.Keys.buildKeysUri(mDataUri);                  return new CursorLoader(getActivity(), baseUri, -                        ViewKeyKeysAdapter.KEYS_PROJECTION, null, null, null); +                        SubkeysAdapter.KEYS_PROJECTION, null, null, null);              }              default: @@ -191,6 +241,105 @@ public class EditKeyFragment extends LoaderFragment implements          }      } +    private void changePassphrase() { +        // Message is received after passphrase is cached +        Handler returnHandler = new Handler() { +            @Override +            public void handleMessage(Message message) { +                if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) { +                    Bundle data = message.getData(); + +                    // set new returned passphrase! +                    String newPassphrase = data +                            .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE); + +//                    updatePassphraseButtonText(); +//                    somethingChanged(); +                    mSaveKeyringParcel.newPassphrase = newPassphrase; +                } +            } +        }; + +        // 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); + +        setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog"); +    } + +    private void editUserId(final String userId) { +        Handler returnHandler = new Handler() { +            @Override +            public void handleMessage(Message message) { +                switch (message.what) { +                    case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID: +                        // toggle +                        if (mSaveKeyringParcel.changePrimaryUserId != null +                                && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) { +                            mSaveKeyringParcel.changePrimaryUserId = null; +                        } else { +                            mSaveKeyringParcel.changePrimaryUserId = userId; +                        } +                        break; +                    case EditUserIdDialogFragment.MESSAGE_REVOKE: +                        // toggle +                        if (mSaveKeyringParcel.revokeUserIds.contains(userId)) { +                            mSaveKeyringParcel.revokeUserIds.remove(userId); +                        } else { +                            mSaveKeyringParcel.revokeUserIds.add(userId); +                        } +                        break; +                } +                getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); +            } +        }; + +        // Create a new Messenger for the communication back +        final Messenger messenger = new Messenger(returnHandler); + +        DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { +            public void run() { +                EditUserIdDialogFragment dialogFragment = +                        EditUserIdDialogFragment.newInstance(messenger); + +                dialogFragment.show(getActivity().getSupportFragmentManager(), "editUserIdDialog"); +            } +        }); +    } + +    private void addUserId() { +        Handler returnHandler = new Handler() { +            @Override +            public void handleMessage(Message message) { +                if (message.what == AddUserIdDialogFragment.MESSAGE_OK) { + +                } +            } +        }; + +        // Create a new Messenger for the communication back +        final Messenger messenger = new Messenger(returnHandler); + +        DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { +            public void run() { +                AddUserIdDialogFragment dialogFragment = +                        AddUserIdDialogFragment.newInstance(messenger); + +                dialogFragment.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); +            } +        }); +    } +      private void save() {          getActivity().finish();          // TODO diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java index e01a0140c..4be572b4e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java @@ -31,7 +31,7 @@ import android.widget.ListView;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter; +import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;  import org.sufficientlysecure.keychain.util.Log; @@ -42,7 +42,7 @@ public class ViewKeyKeysFragment extends LoaderFragment implements      private ListView mKeys; -    private ViewKeyKeysAdapter mKeysAdapter; +    private SubkeysAdapter mKeysAdapter;      private Uri mDataUri; @@ -75,7 +75,7 @@ public class ViewKeyKeysFragment extends LoaderFragment implements          Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); -        mKeysAdapter = new ViewKeyKeysAdapter(getActivity(), null, 0); +        mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0);          mKeys.setAdapter(mKeysAdapter);          // Prepare the loaders. Either re-connect with an existing ones, @@ -87,7 +87,7 @@ public class ViewKeyKeysFragment extends LoaderFragment implements          setContentShown(false);          Uri baseUri = Keys.buildKeysUri(mDataUri);          return new CursorLoader(getActivity(), baseUri, -                ViewKeyKeysAdapter.KEYS_PROJECTION, null, null, null); +                SubkeysAdapter.KEYS_PROJECTION, null, null, null);      }      public void onLoadFinished(Loader<Cursor> loader, Cursor data) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index bd29f3820..dd48f193c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -38,7 +38,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;  import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;  import org.sufficientlysecure.keychain.util.Log;  import java.util.Date; @@ -63,7 +63,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements      // conservative attitude      private boolean mHasEncrypt = true; -    private ViewKeyUserIdsAdapter mUserIdsAdapter; +    private UserIdsAdapter mUserIdsAdapter;      private Uri mDataUri; @@ -124,7 +124,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements              }          }); -        mUserIdsAdapter = new ViewKeyUserIdsAdapter(getActivity(), null, 0); +        mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);          mUserIds.setAdapter(mUserIdsAdapter);          // Prepare the loaders. Either re-connect with an existing ones, @@ -154,7 +154,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements              case LOADER_ID_USER_IDS: {                  Uri baseUri = UserIds.buildUserIdsUri(mDataUri);                  return new CursorLoader(getActivity(), baseUri, -                        ViewKeyUserIdsAdapter.USER_IDS_PROJECTION, null, null, null); +                        UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);              }              default: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index dae287bbc..6d8455589 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -35,7 +35,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;  import java.util.Date; -public class ViewKeyKeysAdapter extends CursorAdapter { +public class SubkeysAdapter extends CursorAdapter {      private LayoutInflater mInflater;      private int mIndexKeyId; @@ -69,7 +69,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter {              Keys.FINGERPRINT      }; -    public ViewKeyKeysAdapter(Context context, Cursor c, int flags) { +    public SubkeysAdapter(Context context, Cursor c, int flags) {          super(context, c, flags);          mInflater = LayoutInflater.from(context); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index 763752edc..7a7acfe89 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -34,10 +34,11 @@ import org.sufficientlysecure.keychain.helper.OtherHelper;  import org.sufficientlysecure.keychain.pgp.KeyRing;  import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;  import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel;  import java.util.ArrayList; -public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.OnItemClickListener { +public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemClickListener {      private LayoutInflater mInflater;      private int mIndexUserId, mIndexRank; @@ -45,6 +46,8 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.      private final ArrayList<Boolean> mCheckStates; +    private SaveKeyringParcel mSaveKeyringParcel; +      public static final String[] USER_IDS_PROJECTION = new String[]{              UserIds._ID,              UserIds.USER_ID, @@ -54,18 +57,27 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.              UserIds.IS_REVOKED      }; -    public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) { +    public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes, +                          SaveKeyringParcel saveKeyringParcel) {          super(context, c, flags); -          mInflater = LayoutInflater.from(context);          mCheckStates = showCheckBoxes ? new ArrayList<Boolean>() : null; +        mSaveKeyringParcel = saveKeyringParcel;          initIndex(c);      } -    public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags) { -        this(context, c, flags, false); +    public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) { +        this(context, c, flags, showCheckBoxes, null); +    } + +    public UserIdsAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) { +        this(context, c, flags, false, saveKeyringParcel); +    } + +    public UserIdsAdapter(Context context, Cursor c, int flags) { +        this(context, c, flags, false, null);      }      @Override @@ -110,21 +122,23 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.          TextView vAddress = (TextView) view.findViewById(R.id.address);          TextView vComment = (TextView) view.findViewById(R.id.comment);          ImageView vVerified = (ImageView) view.findViewById(R.id.certified); +        ImageView vHasChanges = (ImageView) view.findViewById(R.id.has_changes); -        String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId)); -        if (userId[0] != null) { -            vName.setText(userId[0]); +        String userId = cursor.getString(mIndexUserId); +        String[] splitUserId = KeyRing.splitUserId(userId); +        if (splitUserId[0] != null) { +            vName.setText(splitUserId[0]);          } else {              vName.setText(R.string.user_id_no_name);          } -        if (userId[1] != null) { -            vAddress.setText(userId[1]); +        if (splitUserId[1] != null) { +            vAddress.setText(splitUserId[1]);              vAddress.setVisibility(View.VISIBLE);          } else {              vAddress.setVisibility(View.GONE);          } -        if (userId[2] != null) { -            vComment.setText(userId[2]); +        if (splitUserId[2] != null) { +            vComment.setText(splitUserId[2]);              vComment.setVisibility(View.VISIBLE);          } else {              vComment.setVisibility(View.GONE); @@ -132,9 +146,33 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.          // show small star icon for primary user ids          boolean isPrimary = cursor.getInt(mIsPrimary) != 0; +        boolean isRevoked = cursor.getInt(mIsRevoked) > 0; + +        // for edit key +        if (mSaveKeyringParcel != null) { +            boolean changeUserId = (mSaveKeyringParcel.changePrimaryUserId != null +                    && mSaveKeyringParcel.changePrimaryUserId.equals(userId)); +            boolean revoke = (mSaveKeyringParcel.revokeUserIds.contains(userId)); -        if (cursor.getInt(mIsRevoked) > 0) { +            if (changeUserId) { +                isPrimary = !isPrimary; +            } +            if (revoke) { +                if (!isRevoked) { +                    isRevoked = true; +                } +            } +            if (changeUserId || revoke) { +                vHasChanges.setVisibility(View.VISIBLE); +            } else { +                vHasChanges.setVisibility(View.GONE); +            } +        } else { +            vHasChanges.setVisibility(View.GONE); +        } + +        if (isRevoked) {              // set revocation icon (can this even be primary?)              vVerified.setImageResource(R.drawable.key_certify_revoke); @@ -181,7 +219,6 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.              }          });          vCheckBox.setClickable(false); -      }      public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { @@ -202,6 +239,11 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.          return result;      } +    public String getUserId(int position) { +        mCursor.moveToPosition(position); +        return mCursor.getString(mIndexUserId); +    } +      @Override      public View newView(Context context, Cursor cursor, ViewGroup parent) {          View view = mInflater.inflate(R.layout.view_key_userids_item, null); @@ -213,7 +255,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.      // Disable selection of items for lists without checkboxes, http://stackoverflow.com/a/4075045      @Override      public boolean areAllItemsEnabled() { -        if (mCheckStates == null) { +        if (mCheckStates == null && mSaveKeyringParcel == null) {              return false;          } else {              return super.areAllItemsEnabled(); @@ -223,7 +265,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.      // Disable selection of items for lists without checkboxes, http://stackoverflow.com/a/4075045      @Override      public boolean isEnabled(int position) { -        if (mCheckStates == null) { +        if (mCheckStates == null && mSaveKeyringParcel == null) {              return false;          } else {              return super.isEnabled(position); 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 new file mode 100644 index 000000000..db7c38e71 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -0,0 +1,108 @@ +/* + * 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.dialog; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.v4.app.DialogFragment; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +public class AddUserIdDialogFragment extends DialogFragment { +    private static final String ARG_MESSENGER = "messenger"; + +    public static final int MESSAGE_OK = 1; + +    private Messenger mMessenger; + +    /** +     * Creates new instance of this dialog fragment +     */ +    public static AddUserIdDialogFragment newInstance(Messenger messenger) { +        AddUserIdDialogFragment frag = new AddUserIdDialogFragment(); +        Bundle args = new Bundle(); +        args.putParcelable(ARG_MESSENGER, messenger); + +        frag.setArguments(args); + +        return frag; +    } + +    /** +     * Creates dialog +     */ +    @Override +    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(); +    } + +    /** +     * Send message back to handler which is initialized in a activity +     * +     * @param what Message integer you want to send +     */ +    private void sendMessageToHandler(Integer what, Bundle data) { +        Message msg = Message.obtain(); +        msg.what = what; +        if (data != null) { +            msg.setData(data); +        } + +        try { +            mMessenger.send(msg); +        } catch (RemoteException e) { +            Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); +        } catch (NullPointerException e) { +            Log.w(Constants.TAG, "Messenger is null!", e); +        } +    } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java new file mode 100644 index 000000000..f0ca73f0d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java @@ -0,0 +1,109 @@ +/* + * 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.dialog; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.v4.app.DialogFragment; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +public class EditUserIdDialogFragment extends DialogFragment { +    private static final String ARG_MESSENGER = "messenger"; + +    public static final int MESSAGE_CHANGE_PRIMARY_USER_ID = 1; +    public static final int MESSAGE_REVOKE = 2; + +    private Messenger mMessenger; + +    /** +     * Creates new instance of this dialog fragment +     */ +    public static EditUserIdDialogFragment newInstance(Messenger messenger) { +        EditUserIdDialogFragment frag = new EditUserIdDialogFragment(); +        Bundle args = new Bundle(); +        args.putParcelable(ARG_MESSENGER, messenger); + +        frag.setArguments(args); + +        return frag; +    } + +    /** +     * Creates dialog +     */ +    @Override +    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(); +    } + +    /** +     * Send message back to handler which is initialized in a activity +     * +     * @param what Message integer you want to send +     */ +    private void sendMessageToHandler(Integer what, Bundle data) { +        Message msg = Message.obtain(); +        msg.what = what; +        if (data != null) { +            msg.setData(data); +        } + +        try { +            mMessenger.send(msg); +        } catch (RemoteException e) { +            Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); +        } catch (NullPointerException e) { +            Log.w(Constants.TAG, "Messenger is null!", e); +        } +    } +} diff --git a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml index dbc0c3941..f652269e5 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml @@ -13,7 +13,29 @@              style="@style/SectionHeader"              android:layout_width="wrap_content"              android:layout_height="0dp" -            android:layout_marginBottom="4dp" +            android:layout_marginTop="8dp" +            android:text="Passphrase" +            android:layout_weight="1" /> + +        <TextView +            android:id="@+id/edit_key_action_change_passphrase" +            android:paddingLeft="8dp" +            android:paddingRight="8dp" +            android:textAppearance="?android:attr/textAppearanceMedium" +            android:layout_width="match_parent" +            android:layout_height="match_parent" +            android:text="change passphrase" +            android:minHeight="?android:attr/listPreferredItemHeight" +            android:drawableRight="@drawable/ic_action_edit" +            android:drawablePadding="8dp" +            android:gravity="center_vertical" +            android:clickable="true" +            style="@style/SelectableItem" /> + +        <TextView +            style="@style/SectionHeader" +            android:layout_width="wrap_content" +            android:layout_height="0dp"              android:layout_marginTop="8dp"              android:text="@string/section_user_ids"              android:layout_weight="1" /> @@ -21,23 +43,69 @@          <org.sufficientlysecure.keychain.ui.widget.FixedListView              android:id="@+id/edit_key_user_ids"              android:layout_width="match_parent" -            android:layout_height="0dp" -            android:layout_marginBottom="4dp" -            android:layout_weight="1" /> +            android:layout_height="wrap_content" /> + +        <org.sufficientlysecure.keychain.ui.widget.FixedListView +            android:id="@+id/edit_key_user_ids_added" +            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" /> + +        <TextView +            android:id="@+id/edit_key_action_add_user_id" +            android:paddingLeft="8dp" +            android:paddingRight="8dp" +            android:textAppearance="?android:attr/textAppearanceMedium" +            android:layout_width="match_parent" +            android:layout_height="match_parent" +            android:text="add identity" +            android:minHeight="?android:attr/listPreferredItemHeight" +            android:drawableRight="@drawable/ic_action_add_person" +            android:drawablePadding="8dp" +            android:gravity="center_vertical" +            android:clickable="true" +            style="@style/SelectableItem" />          <TextView              style="@style/SectionHeader"              android:layout_width="wrap_content"              android:layout_height="wrap_content" -            android:layout_marginBottom="4dp"              android:layout_marginTop="8dp"              android:text="@string/section_keys" />          <org.sufficientlysecure.keychain.ui.widget.FixedListView              android:id="@+id/edit_key_keys"              android:layout_width="match_parent" -            android:layout_height="wrap_content" -            android:layout_marginBottom="8dp" /> +            android:layout_height="wrap_content" /> + +        <org.sufficientlysecure.keychain.ui.widget.FixedListView +            android:id="@+id/edit_key_keys_added" +            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" /> + +        <TextView +            android:id="@+id/edit_key_action_add_key" +            android:paddingLeft="8dp" +            android:paddingRight="8dp" +            android:textAppearance="?android:attr/textAppearanceMedium" +            android:layout_width="match_parent" +            android:layout_height="match_parent" +            android:text="add key" +            android:minHeight="?android:attr/listPreferredItemHeight" +            android:drawableRight="@drawable/ic_action_add_person" +            android:drawablePadding="8dp" +            android:gravity="center_vertical" +            android:clickable="true" +            style="@style/SelectableItem" />      </LinearLayout> diff --git a/OpenKeychain/src/main/res/layout/import_keys_activity.xml b/OpenKeychain/src/main/res/layout/import_keys_activity.xml index fc9d21e23..b076debfe 100644 --- a/OpenKeychain/src/main/res/layout/import_keys_activity.xml +++ b/OpenKeychain/src/main/res/layout/import_keys_activity.xml @@ -1,7 +1,5 @@  <?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" -    android:id="@+id/content_frame" -    android:layout_marginLeft="@dimen/drawer_content_padding"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical"> diff --git a/OpenKeychain/src/main/res/layout/view_key_userids_item.xml b/OpenKeychain/src/main/res/layout/view_key_userids_item.xml index 03e619aff..f812127a9 100644 --- a/OpenKeychain/src/main/res/layout/view_key_userids_item.xml +++ b/OpenKeychain/src/main/res/layout/view_key_userids_item.xml @@ -6,10 +6,17 @@      android:orientation="horizontal"      android:singleLine="true"> -    <CheckBox +    <ImageView +        android:id="@+id/has_changes"          android:layout_width="wrap_content"          android:layout_height="match_parent" +        android:minWidth="10dp" +        android:background="@color/emphasis" /> + +    <CheckBox          android:id="@+id/checkBox" +        android:layout_width="wrap_content" +        android:layout_height="match_parent"          android:clickable="false"          android:focusable="false" /> diff --git a/build.gradle b/build.gradle index e0da6b52f..fa6c7278e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript {      dependencies {          // NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information          classpath 'com.android.tools.build:gradle:0.11.1' -	    classpath 'org.robolectric:robolectric-gradle-plugin:0.11.0' +        classpath 'org.robolectric:robolectric-gradle-plugin:0.11.0'      }  } diff --git a/extern/dnsjava b/extern/dnsjava deleted file mode 160000 -Subproject 71c8a9e56b19b34907e7e2e810ca15b57e3edc2 diff --git a/extern/minidns b/extern/minidns new file mode 160000 +Subproject dcf62a8ac59d84072e66e71ec8a5d137784e760 diff --git a/settings.gradle b/settings.gradle index 24eb03490..4776ae5ee 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,5 +12,5 @@ include ':extern:spongycastle:pkix'  include ':extern:spongycastle:prov'  include ':extern:AppMsg:library'  include ':extern:SuperToasts:supertoasts' -include ':extern:dnsjava' +include ':extern:minidns'  include ':extern:KeybaseLib:Lib' | 
