diff options
Diffstat (limited to 'OpenKeychain')
7 files changed, 308 insertions, 227 deletions
| 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 3b55e6231..abc377b7e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -20,19 +20,23 @@ package org.sufficientlysecure.keychain.service;  import android.os.Parcel;  import android.os.Parcelable; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; +  import java.io.Serializable;  import java.util.ArrayList; -/** This class is a a transferable representation for a collection of changes +/** + * This class is a a transferable representation for a collection of changes   * to be done on a keyring. - * + * <p/>   * This class should include all types of operations supported in the backend. - * + * <p/>   * All changes are done in a differential manner. Besides the two key   * identification attributes, all attributes may be null, which indicates no   * change to the keyring. This is also the reason why boxed values are used   * instead of primitives in the subclasses. - * + * <p/>   * Application of operations in the backend should be fail-fast, which means an   * error in any included operation (for example revocation of a non-existent   * subkey) will cause the operation as a whole to fail. @@ -82,12 +86,23 @@ public class SaveKeyringParcel implements Parcelable {          public int mKeysize;          public int mFlags;          public Long mExpiry; +          public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) {              mAlgorithm = algorithm;              mKeysize = keysize;              mFlags = flags;              mExpiry = expiry;          } + +        @Override +        public String toString() { +            String out = "mAlgorithm: " + mAlgorithm + ", "; +            out += "mKeysize: " + mKeysize + ", "; +            out += "mFlags: " + mFlags; +            out += "mExpiry: " + mExpiry; + +            return out; +        }      }      public static class SubkeyChange implements Serializable { @@ -95,11 +110,46 @@ public class SaveKeyringParcel implements Parcelable {          public Integer mFlags;          // this is a long unix timestamp, in seconds (NOT MILLISECONDS!)          public Long mExpiry; + +        public SubkeyChange(long keyId) { +            mKeyId = keyId; +        } +          public SubkeyChange(long keyId, Integer flags, Long expiry) {              mKeyId = keyId;              mFlags = flags;              mExpiry = expiry;          } + +        @Override +        public String toString() { +            String out = "mKeyId: " + mKeyId + ", "; +            out += "mFlags: " + mFlags + ", "; +            out += "mExpiry: " + mExpiry; + +            return out; +        } +    } + +    public SubkeyChange getSubkeyChange(long keyId) { +        for (SubkeyChange subkeyChange : mChangeSubKeys) { +            if (subkeyChange.mKeyId == keyId) { +                return subkeyChange; +            } +        } +        return null; +    } + +    public SubkeyChange getOrCreateSubkeyChange(long keyId) { +        SubkeyChange foundSubkeyChange = getSubkeyChange(keyId); +        if (foundSubkeyChange != null) { +            return foundSubkeyChange; +        } else { +            // else, create a new one +            SubkeyChange newSubkeyChange = new SubkeyChange(keyId); +            mChangeSubKeys.add(newSubkeyChange); +            return newSubkeyChange; +        }      }      public SaveKeyringParcel(Parcel source) { @@ -121,7 +171,7 @@ public class SaveKeyringParcel implements Parcelable {      @Override      public void writeToParcel(Parcel destination, int flags) {          destination.writeInt(mMasterKeyId == null ? 0 : 1); -        if(mMasterKeyId != null) { +        if (mMasterKeyId != null) {              destination.writeLong(mMasterKeyId);          }          destination.writeByteArray(mFingerprint); @@ -153,4 +203,16 @@ public class SaveKeyringParcel implements Parcelable {          return 0;      } +    @Override +    public String toString() { +        String out = "mMasterKeyId: " + mMasterKeyId + "\n"; +        out += "mNewPassphrase: " + mNewPassphrase + "\n"; +        out += "mAddSubKeys: " + mAddSubKeys + "\n"; +        out += "mChangeSubKeys: " + mChangeSubKeys + "\n"; +        out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n"; +        out += "mRevokeUserIds: " + mRevokeUserIds + "\n"; +        out += "mRevokeSubKeys: " + mRevokeSubKeys; + +        return out; +    }  } 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 7460b73b4..6b062af59 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -45,7 +45,6 @@ import org.sufficientlysecure.keychain.helper.ActionBarHelper;  import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;  import org.sufficientlysecure.keychain.pgp.KeyRing;  import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;  import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.provider.ProviderHelper;  import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -60,15 +59,13 @@ import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;  import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter;  import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment;  import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.ChangeExpiryDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment;  import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment;  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; -import java.util.Date; -  public class EditKeyFragment extends LoaderFragment implements          LoaderManager.LoaderCallbacks<Cursor> { @@ -96,8 +93,8 @@ public class EditKeyFragment extends LoaderFragment implements      private Uri mDataUri;      private SaveKeyringParcel mSaveKeyringParcel; -    private String mPrimaryUserId; +    private String mPrimaryUserId;      private String mCurrentPassphrase;      /** @@ -399,23 +396,17 @@ public class EditKeyFragment extends LoaderFragment implements      private void editSubkeyExpiry(final int position) {          final long keyId = mSubkeysAdapter.getKeyId(position); -        final Date creationDate = new Date(mSubkeysAdapter.getCreationDate(position)); -        final Date expiryDate = new Date(mSubkeysAdapter.getExpiryDate(position)); +        final long creationDate = mSubkeysAdapter.getCreationDate(position); +        final long expiryDate = mSubkeysAdapter.getExpiryDate(position);          Handler returnHandler = new Handler() {              @Override              public void handleMessage(Message message) {                  switch (message.what) { -                    case ChangeExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: -//                        SaveKeyringParcel.SubkeyChange subkeyChange = new SaveKeyringParcel.SubkeyChange(); - -//                        mSaveKeyringParcel.mChangeSubKeys.add() -//                        if (mSaveKeyringParcel.changePrimaryUserId != null -//                                && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) { -//                            mSaveKeyringParcel.changePrimaryUserId = null; -//                        } else { -//                            mSaveKeyringParcel.changePrimaryUserId = userId; -//                        } +                    case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: +                        long expiry = message.getData().getLong(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); +                        Log.d(Constants.TAG, "new expiry: " + expiry); +                        mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry;                          break;                  }                  getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); @@ -427,8 +418,8 @@ public class EditKeyFragment extends LoaderFragment implements          DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {              public void run() { -                ChangeExpiryDialogFragment dialogFragment = -                        ChangeExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); +                EditSubkeyExpiryDialogFragment dialogFragment = +                        EditSubkeyExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate);                  dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog");              } @@ -501,9 +492,7 @@ public class EditKeyFragment extends LoaderFragment implements      }      private void save(String passphrase) { -        Log.d(Constants.TAG, "mSaveKeyringParcel.mAddUserIds: " + mSaveKeyringParcel.mAddUserIds); -        Log.d(Constants.TAG, "mSaveKeyringParcel.mNewPassphrase: " + mSaveKeyringParcel.mNewPassphrase); -        Log.d(Constants.TAG, "mSaveKeyringParcel.mRevokeUserIds: " + mSaveKeyringParcel.mRevokeUserIds); +        Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());          // Message is received after importing is done in KeychainIntentService          KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 25b3c0fc5..dd972866c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -161,6 +161,11 @@ public class SubkeysAdapter extends CursorAdapter {          boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; +        Date expiryDate = null; +        if (!cursor.isNull(INDEX_EXPIRY)) { +            expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); +        } +          // for edit key          if (mSaveKeyringParcel != null) {              boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)); @@ -171,24 +176,21 @@ public class SubkeysAdapter extends CursorAdapter {                  }              } +            SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId); +            if (subkeyChange != null) { +                // 0 is "no expiry" +                if (subkeyChange.mExpiry != null && subkeyChange.mExpiry != 0) { +                    expiryDate = new Date(subkeyChange.mExpiry * 1000); +                } +            } +              vEditImage.setVisibility(View.VISIBLE);          } else {              vEditImage.setVisibility(View.GONE);          } -        if (isRevoked) { -            vRevokedIcon.setVisibility(View.VISIBLE); -        } else { -            vKeyId.setTextColor(mDefaultTextColor); -            vKeyDetails.setTextColor(mDefaultTextColor); -            vKeyExpiry.setTextColor(mDefaultTextColor); - -            vRevokedIcon.setVisibility(View.GONE); -        } -          boolean isExpired; -        if (!cursor.isNull(INDEX_EXPIRY)) { -            Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); +        if (expiryDate != null) {              isExpired = expiryDate.before(new Date());              vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " @@ -199,6 +201,16 @@ public class SubkeysAdapter extends CursorAdapter {              vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none));          } +        if (isRevoked) { +            vRevokedIcon.setVisibility(View.VISIBLE); +        } else { +            vKeyId.setTextColor(mDefaultTextColor); +            vKeyDetails.setTextColor(mDefaultTextColor); +            vKeyExpiry.setTextColor(mDefaultTextColor); + +            vRevokedIcon.setVisibility(View.GONE); +        } +          // if key is expired or revoked, strike through text          boolean isInvalid = isRevoked || isExpired;          if (isInvalid) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java deleted file mode 100644 index d5354a9f6..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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.DatePickerDialog; -import android.app.Dialog; -import android.content.Context; -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 android.text.format.DateUtils; -import android.widget.DatePicker; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -public class ChangeExpiryDialogFragment extends DialogFragment { -    private static final String ARG_MESSENGER = "messenger"; -    private static final String ARG_CREATION_DATE = "creation_date"; -    private static final String ARG_EXPIRY_DATE = "expiry_date"; - -    public static final int MESSAGE_NEW_EXPIRY_DATE = 1; -    public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; - -    private Messenger mMessenger; -    private Calendar mCreationCal; -    private Calendar mExpiryCal; - -    private int mDatePickerResultCount = 0; -    private DatePickerDialog.OnDateSetListener mExpiryDateSetListener = -            new DatePickerDialog.OnDateSetListener() { -                public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { -                    // Note: Ignore results after the first one - android sends multiples. -                    if (mDatePickerResultCount++ == 0) { -                        Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); -                        selectedCal.set(year, monthOfYear, dayOfMonth); -                        if (mExpiryCal != null) { -                            long numDays = (selectedCal.getTimeInMillis() / 86400000) -                                    - (mExpiryCal.getTimeInMillis() / 86400000); -                            if (numDays > 0) { -                                Bundle data = new Bundle(); -                                data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime()); -                                sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); -                            } -                        } else { -                            Bundle data = new Bundle(); -                            data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime()); -                            sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); -                        } -                    } -                } -            }; - -    public class ExpiryDatePickerDialog extends DatePickerDialog { - -        public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack, -                                      int year, int monthOfYear, int dayOfMonth) { -            super(context, callBack, year, monthOfYear, dayOfMonth); -        } - -        // set permanent title -        public void setTitle(CharSequence title) { -            super.setTitle(getContext().getString(R.string.expiry_date_dialog_title)); -        } -    } - -    /** -     * Creates new instance of this dialog fragment -     */ -    public static ChangeExpiryDialogFragment newInstance(Messenger messenger, -                                                         Date creationDate, Date expiryDate) { -        ChangeExpiryDialogFragment frag = new ChangeExpiryDialogFragment(); -        Bundle args = new Bundle(); -        args.putParcelable(ARG_MESSENGER, messenger); -        args.putSerializable(ARG_CREATION_DATE, creationDate); -        args.putSerializable(ARG_EXPIRY_DATE, expiryDate); - -        frag.setArguments(args); - -        return frag; -    } - -    /** -     * Creates dialog -     */ -    @Override -    public Dialog onCreateDialog(Bundle savedInstanceState) { -        mMessenger = getArguments().getParcelable(ARG_MESSENGER); -        Date creationDate = (Date) getArguments().getSerializable(ARG_CREATION_DATE); -        Date expiryDate = (Date) getArguments().getSerializable(ARG_EXPIRY_DATE); - -        mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); -        mCreationCal.setTime(creationDate); -        mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); -        mExpiryCal.setTime(expiryDate); - -        /* -         * Using custom DatePickerDialog which overrides the setTitle because -         * the DatePickerDialog title is buggy (unix warparound bug). -         * See: https://code.google.com/p/android/issues/detail?id=49066 -         */ -        DatePickerDialog dialog = new ExpiryDatePickerDialog(getActivity(), -                mExpiryDateSetListener, mExpiryCal.get(Calendar.YEAR), mExpiryCal.get(Calendar.MONTH), -                mExpiryCal.get(Calendar.DAY_OF_MONTH)); -        mDatePickerResultCount = 0; -        dialog.setCancelable(true); -        dialog.setButton(Dialog.BUTTON_NEGATIVE, -                getActivity().getString(R.string.btn_no_date), -                new DialogInterface.OnClickListener() { -                    public void onClick(DialogInterface dialog, int which) { -                        // Note: Ignore results after the first one - android sends multiples. -                        if (mDatePickerResultCount++ == 0) { -                            // none expiry dates corresponds to a null message -                            Bundle data = new Bundle(); -                            data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, null); -                            sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); -                        } -                    } -                } -        ); - -        // setCalendarViewShown() is supported from API 11 onwards. -        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { -            // Hide calendarView in tablets because of the unix warparound bug. -            dialog.getDatePicker().setCalendarViewShown(false); -        } -        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { -            // will crash with IllegalArgumentException if we set a min date -            // that is not before expiry -            if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { -                dialog.getDatePicker().setMinDate(mCreationCal.getTime().getTime() -                        + DateUtils.DAY_IN_MILLIS); -            } else { -                // When created date isn't available -                dialog.getDatePicker().setMinDate(mExpiryCal.getTime().getTime() -                        + DateUtils.DAY_IN_MILLIS); -            } -        } - -        return dialog; -    } - -    /** -     * 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/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java new file mode 100644 index 000000000..1712b922f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -0,0 +1,189 @@ +/* + * 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.Activity; +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 android.text.format.DateUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.DatePicker; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +public class EditSubkeyExpiryDialogFragment extends DialogFragment { +    private static final String ARG_MESSENGER = "messenger"; +    private static final String ARG_CREATION_DATE = "creation_date"; +    private static final String ARG_EXPIRY_DATE = "expiry_date"; + +    public static final int MESSAGE_NEW_EXPIRY_DATE = 1; +    public static final int MESSAGE_CANCEL = 2; +    public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; + +    private Messenger mMessenger; +    private Calendar mCreationCal; +    private Calendar mExpiryCal; + +    private DatePicker mDatePicker; + +    /** +     * Creates new instance of this dialog fragment +     */ +    public static EditSubkeyExpiryDialogFragment newInstance(Messenger messenger, +                                                             long creationDate, long expiryDate) { +        EditSubkeyExpiryDialogFragment frag = new EditSubkeyExpiryDialogFragment(); +        Bundle args = new Bundle(); +        args.putParcelable(ARG_MESSENGER, messenger); +        args.putLong(ARG_CREATION_DATE, creationDate); +        args.putLong(ARG_EXPIRY_DATE, expiryDate); + +        frag.setArguments(args); + +        return frag; +    } + +    /** +     * Creates dialog +     */ +    @Override +    public Dialog onCreateDialog(Bundle savedInstanceState) { +        final Activity activity = getActivity(); +        mMessenger = getArguments().getParcelable(ARG_MESSENGER); +        Date creationDate = new Date(getArguments().getLong(ARG_CREATION_DATE) * 1000); +        Date expiryDate = new Date(getArguments().getLong(ARG_EXPIRY_DATE) * 1000); + +        mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); +        mCreationCal.setTime(creationDate); +        mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); +        mExpiryCal.setTime(expiryDate); + +        Log.d(Constants.TAG, "onCreateDialog"); + +        // Explicitly not using DatePickerDialog here! +        // DatePickerDialog is difficult to customize and has many problems (see old git versions) +        CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); + +        alert.setTitle(R.string.expiry_date_dialog_title); + +        LayoutInflater inflater = activity.getLayoutInflater(); +        View view = inflater.inflate(R.layout.expiry_dialog, null); +        alert.setView(view); + +        mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); + +        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { +            // will crash with IllegalArgumentException if we set a min date +            // that is not before expiry +            if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { +                mDatePicker.setMinDate(mCreationCal.getTime().getTime() +                        + DateUtils.DAY_IN_MILLIS); +            } else { +                // When created date isn't available +                mDatePicker.setMinDate(mExpiryCal.getTime().getTime() +                        + DateUtils.DAY_IN_MILLIS); +            } +        } + +        alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { +            @Override +            public void onClick(DialogInterface dialog, int id) { +                dismiss(); + +                Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); +                //noinspection ResourceType +                selectedCal.set(mDatePicker.getYear(), mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); + +                if (mExpiryCal != null) { +                    long numDays = (selectedCal.getTimeInMillis() / 86400000) +                            - (mExpiryCal.getTimeInMillis() / 86400000); +                    if (numDays > 0) { +                        Bundle data = new Bundle(); +                        data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); +                        sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); +                    } +                } else { +                    Bundle data = new Bundle(); +                    data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); +                    sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); +                } +            } +        }); + +        alert.setNeutralButton(R.string.btn_no_date, new DialogInterface.OnClickListener() { +            @Override +            public void onClick(DialogInterface dialog, int id) { +                dismiss(); + +                // "no expiry" corresponds to a 0 +                Bundle data = new Bundle(); +                data.putLong(MESSAGE_DATA_EXPIRY_DATE, 0); +                sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); +            } +        }); + +        alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { +            @Override +            public void onClick(DialogInterface dialog, int id) { +                dismiss(); +            } +        }); + +        return alert.show(); +    } + +    @Override +    public void onCancel(DialogInterface dialog) { +        super.onCancel(dialog); + +        dismiss(); +        sendMessageToHandler(MESSAGE_CANCEL, null); +    } + +    /** +     * 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/expiry_dialog.xml b/OpenKeychain/src/main/res/layout/expiry_dialog.xml new file mode 100644 index 000000000..14fff0b3f --- /dev/null +++ b/OpenKeychain/src/main/res/layout/expiry_dialog.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +    android:orientation="vertical" +    android:layout_width="match_parent" +    android:layout_height="match_parent"> + +    <DatePicker xmlns:android="http://schemas.android.com/apk/res/android" +        android:id="@+id/datePicker" +        android:layout_gravity="center_horizontal" +        android:layout_width="wrap_content" +        android:layout_height="wrap_content" +        android:spinnersShown="true" +        android:calendarViewShown="false" /> +    <!-- Hide calendarView in tablets because of the unix warparound bug. --> + +</LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index ed5dca813..18031e25b 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -51,7 +51,7 @@      <string name="btn_save">Save</string>      <string name="btn_do_not_save">Cancel</string>      <string name="btn_delete">Delete</string> -    <string name="btn_no_date">None</string> +    <string name="btn_no_date">No Expiry</string>      <string name="btn_okay">Okay</string>      <string name="btn_export_to_server">Upload To Keyserver</string>      <string name="btn_next">Next</string> | 
