set svn:eol-style to LF for all code/resource files

This commit is contained in:
Thialfihar
2010-07-16 20:13:12 +00:00
parent ec10329664
commit f5efd73d33
37 changed files with 7339 additions and 7339 deletions

View File

@@ -1,25 +1,25 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
public interface Editor {
public interface EditorListener {
public void onDeleted(Editor editor);
}
public void setEditorListener(EditorListener listener);
}
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
public interface Editor {
public interface EditorListener {
public void onDeleted(Editor editor);
}
public void setEditorListener(EditorListener listener);
}

View File

@@ -1,242 +1,242 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.utils.Choice;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private PGPSecretKey mKey;
private EditorListener mEditorListener = null;
private boolean mIsMasterKey;
ImageButton mDeleteButton;
TextView mAlgorithm;
TextView mKeyId;
Spinner mUsage;
TextView mCreationDate;
Button mExpiryDateButton;
GregorianCalendar mExpiryDate;
private DatePickerDialog.OnDateSetListener mExpiryDateSetListener =
new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
GregorianCalendar date = new GregorianCalendar(year, monthOfYear, dayOfMonth);
setExpiryDate(date);
}
};
public KeyEditor(Context context) {
super(context);
}
public KeyEditor(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mAlgorithm = (TextView) findViewById(R.id.algorithm);
mKeyId = (TextView) findViewById(R.id.keyId);
mCreationDate = (TextView) findViewById(R.id.creation);
mExpiryDateButton = (Button) findViewById(R.id.expiry);
mUsage = (Spinner) findViewById(R.id.usage);
Choice choices[] = {
new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.choice_signOnly)),
new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.choice_encryptOnly)),
new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.choice_signAndEncrypt)),
};
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mUsage.setAdapter(adapter);
mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
setExpiryDate(null);
mExpiryDateButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GregorianCalendar date = mExpiryDate;
if (date == null) {
date = new GregorianCalendar();
}
DatePickerDialog dialog =
new DatePickerDialog(getContext(), mExpiryDateSetListener,
date.get(Calendar.YEAR),
date.get(Calendar.MONTH),
date.get(Calendar.DAY_OF_MONTH));
dialog.setCancelable(true);
dialog.setButton(Dialog.BUTTON_NEGATIVE,
getContext().getString(R.string.btn_noDate),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
setExpiryDate(null);
}
});
dialog.show();
}
});
super.onFinishInflate();
}
public void setValue(PGPSecretKey key, boolean isMasterKey) {
mKey = key;
mIsMasterKey = isMasterKey;
if (mIsMasterKey) {
mDeleteButton.setVisibility(View.INVISIBLE);
}
mAlgorithm.setText(Apg.getAlgorithmInfo(key));
String keyId1Str = Long.toHexString((key.getKeyID() >> 32) & 0xffffffffL);
while (keyId1Str.length() < 8) {
keyId1Str = "0" + keyId1Str;
}
String keyId2Str = Long.toHexString(key.getKeyID() & 0xffffffffL);
while (keyId2Str.length() < 8) {
keyId2Str = "0" + keyId2Str;
}
mKeyId.setText(keyId1Str + " " + keyId2Str);
Vector<Choice> choices = new Vector<Choice>();
boolean isElGamalKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT);
if (!isElGamalKey) {
choices.add(new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.choice_signOnly)));
}
if (!mIsMasterKey) {
choices.add(new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.choice_encryptOnly)));
}
if (!isElGamalKey) {
choices.add(new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.choice_signAndEncrypt)));
}
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mUsage.setAdapter(adapter);
int selectId = 0;
if (Apg.isEncryptionKey(key)) {
if (Apg.isSigningKey(key)) {
selectId = Id.choice.usage.sign_and_encrypt;
} else {
selectId = Id.choice.usage.encrypt_only;
}
} else {
selectId = Id.choice.usage.sign_only;
}
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == selectId) {
mUsage.setSelection(i);
break;
}
}
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(Apg.getCreationDate(key));
mCreationDate.setText(DateFormat.getDateInstance().format(cal.getTime()));
cal = new GregorianCalendar();
Date date = Apg.getExpiryDate(key);
if (date == null) {
setExpiryDate(null);
} else {
cal.setTime(Apg.getExpiryDate(key));
setExpiryDate(cal);
}
}
public PGPSecretKey getValue() {
return mKey;
}
@Override
public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) {
parent.removeView(this);
if (mEditorListener != null) {
mEditorListener.onDeleted(this);
}
}
}
@Override
public void setEditorListener(EditorListener listener) {
mEditorListener = listener;
}
private void setExpiryDate(GregorianCalendar date) {
mExpiryDate = date;
if (date == null) {
mExpiryDateButton.setText(R.string.none);
} else {
mExpiryDateButton.setText(DateFormat.getDateInstance().format(date.getTime()));
}
}
public GregorianCalendar getExpiryDate() {
return mExpiryDate;
}
public int getUsage() {
return ((Choice) mUsage.getSelectedItem()).getId();
}
}
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.utils.Choice;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private PGPSecretKey mKey;
private EditorListener mEditorListener = null;
private boolean mIsMasterKey;
ImageButton mDeleteButton;
TextView mAlgorithm;
TextView mKeyId;
Spinner mUsage;
TextView mCreationDate;
Button mExpiryDateButton;
GregorianCalendar mExpiryDate;
private DatePickerDialog.OnDateSetListener mExpiryDateSetListener =
new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
GregorianCalendar date = new GregorianCalendar(year, monthOfYear, dayOfMonth);
setExpiryDate(date);
}
};
public KeyEditor(Context context) {
super(context);
}
public KeyEditor(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mAlgorithm = (TextView) findViewById(R.id.algorithm);
mKeyId = (TextView) findViewById(R.id.keyId);
mCreationDate = (TextView) findViewById(R.id.creation);
mExpiryDateButton = (Button) findViewById(R.id.expiry);
mUsage = (Spinner) findViewById(R.id.usage);
Choice choices[] = {
new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.choice_signOnly)),
new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.choice_encryptOnly)),
new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.choice_signAndEncrypt)),
};
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mUsage.setAdapter(adapter);
mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
setExpiryDate(null);
mExpiryDateButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GregorianCalendar date = mExpiryDate;
if (date == null) {
date = new GregorianCalendar();
}
DatePickerDialog dialog =
new DatePickerDialog(getContext(), mExpiryDateSetListener,
date.get(Calendar.YEAR),
date.get(Calendar.MONTH),
date.get(Calendar.DAY_OF_MONTH));
dialog.setCancelable(true);
dialog.setButton(Dialog.BUTTON_NEGATIVE,
getContext().getString(R.string.btn_noDate),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
setExpiryDate(null);
}
});
dialog.show();
}
});
super.onFinishInflate();
}
public void setValue(PGPSecretKey key, boolean isMasterKey) {
mKey = key;
mIsMasterKey = isMasterKey;
if (mIsMasterKey) {
mDeleteButton.setVisibility(View.INVISIBLE);
}
mAlgorithm.setText(Apg.getAlgorithmInfo(key));
String keyId1Str = Long.toHexString((key.getKeyID() >> 32) & 0xffffffffL);
while (keyId1Str.length() < 8) {
keyId1Str = "0" + keyId1Str;
}
String keyId2Str = Long.toHexString(key.getKeyID() & 0xffffffffL);
while (keyId2Str.length() < 8) {
keyId2Str = "0" + keyId2Str;
}
mKeyId.setText(keyId1Str + " " + keyId2Str);
Vector<Choice> choices = new Vector<Choice>();
boolean isElGamalKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT);
if (!isElGamalKey) {
choices.add(new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.choice_signOnly)));
}
if (!mIsMasterKey) {
choices.add(new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.choice_encryptOnly)));
}
if (!isElGamalKey) {
choices.add(new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.choice_signAndEncrypt)));
}
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mUsage.setAdapter(adapter);
int selectId = 0;
if (Apg.isEncryptionKey(key)) {
if (Apg.isSigningKey(key)) {
selectId = Id.choice.usage.sign_and_encrypt;
} else {
selectId = Id.choice.usage.encrypt_only;
}
} else {
selectId = Id.choice.usage.sign_only;
}
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == selectId) {
mUsage.setSelection(i);
break;
}
}
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(Apg.getCreationDate(key));
mCreationDate.setText(DateFormat.getDateInstance().format(cal.getTime()));
cal = new GregorianCalendar();
Date date = Apg.getExpiryDate(key);
if (date == null) {
setExpiryDate(null);
} else {
cal.setTime(Apg.getExpiryDate(key));
setExpiryDate(cal);
}
}
public PGPSecretKey getValue() {
return mKey;
}
@Override
public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) {
parent.removeView(this);
if (mEditorListener != null) {
mEditorListener.onDeleted(this);
}
}
}
@Override
public void setEditorListener(EditorListener listener) {
mEditorListener = listener;
}
private void setExpiryDate(GregorianCalendar date) {
mExpiryDate = date;
if (date == null) {
mExpiryDateButton.setText(R.string.none);
} else {
mExpiryDateButton.setText(DateFormat.getDateInstance().format(date.getTime()));
}
}
public GregorianCalendar getExpiryDate() {
return mExpiryDate;
}
public int getUsage() {
return ((Choice) mUsage.getSelectedItem()).getId();
}
}

View File

@@ -1,337 +1,337 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.utils.Choice;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Runnable {
private LayoutInflater mInflater;
private View mAdd;
private ViewGroup mEditors;
private TextView mTitle;
private int mType = 0;
private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize;
volatile private PGPSecretKey mNewKey;
private ProgressDialog mProgressDialog;
private Thread mRunningThread = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
if (data != null) {
boolean closeProgressDialog = data.getBoolean("closeProgressDialog");
if (closeProgressDialog) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) {
Toast.makeText(getContext(),
getContext().getString(R.string.errorMessage, error),
Toast.LENGTH_SHORT).show();
}
boolean gotNewKey = data.getBoolean("gotNewKey");
if (gotNewKey) {
KeyEditor view =
(KeyEditor) mInflater.inflate(R.layout.edit_key_key_item,
mEditors, false);
view.setEditorListener(SectionView.this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(mNewKey, isMasterKey);
mEditors.addView(view);
SectionView.this.updateEditorsVisible();
}
}
}
};
public SectionView(Context context) {
super(context);
}
public SectionView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ViewGroup getEditors() {
return mEditors;
}
public void setType(int type) {
mType = type;
switch (type) {
case Id.type.user_id: {
mTitle.setText(R.string.section_userIds);
break;
}
case Id.type.key: {
mTitle.setText(R.string.section_keys);
break;
}
default: {
break;
}
}
}
/** {@inheritDoc} */
@Override
protected void onFinishInflate() {
mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mAdd = findViewById(R.id.header);
mAdd.setOnClickListener(this);
mEditors = (ViewGroup) findViewById(R.id.editors);
mTitle = (TextView) findViewById(R.id.title);
updateEditorsVisible();
super.onFinishInflate();
}
/** {@inheritDoc} */
public void onDeleted(Editor editor) {
this.updateEditorsVisible();
}
protected void updateEditorsVisible() {
final boolean hasChildren = mEditors.getChildCount() > 0;
mEditors.setVisibility(hasChildren ? View.VISIBLE : View.GONE);
}
/** {@inheritDoc} */
public void onClick(View v) {
switch (mType) {
case Id.type.user_id: {
UserIdEditor view =
(UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item,
mEditors, false);
view.setEditorListener(this);
if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true);
}
mEditors.addView(view);
break;
}
case Id.type.key: {
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
View view = mInflater.inflate(R.layout.create_key, null);
dialog.setView(view);
dialog.setTitle(R.string.title_createKey);
dialog.setMessage(R.string.keyCreationElGamalInfo);
boolean wouldBeMasterKey = (mEditors.getChildCount() == 0);
final Spinner algorithm = (Spinner) view.findViewById(R.id.algorithm);
Vector<Choice> choices = new Vector<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa,
getResources().getString(R.string.dsa)));
if (!wouldBeMasterKey) {
choices.add(new Choice(Id.choice.algorithm.elgamal,
getResources().getString(R.string.elgamal)));
}
choices.add(new Choice(Id.choice.algorithm.rsa,
getResources().getString(R.string.rsa)));
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item,
choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
algorithm.setAdapter(adapter);
// make RSA the default
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
algorithm.setSelection(i);
break;
}
}
final EditText keySize = (EditText) view.findViewById(R.id.size);
dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface di, int id) {
di.dismiss();
try {
mNewKeySize = Integer.parseInt("" + keySize.getText());
} catch (NumberFormatException e) {
mNewKeySize = 0;
}
mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
createKey();
}
});
dialog.setCancelable(true);
dialog.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface di, int id) {
di.dismiss();
}
});
dialog.create().show();
break;
}
default: {
break;
}
}
this.updateEditorsVisible();
}
public void setUserIds(Vector<String> list) {
if (mType != Id.type.user_id) {
return;
}
mEditors.removeAllViews();
for (String userId : list) {
UserIdEditor view =
(UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, mEditors, false);
view.setEditorListener(this);
view.setValue(userId);
if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true);
}
mEditors.addView(view);
}
this.updateEditorsVisible();
}
public void setKeys(Vector<PGPSecretKey> list) {
if (mType != Id.type.key) {
return;
}
mEditors.removeAllViews();
for (PGPSecretKey key : list) {
KeyEditor view =
(KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, mEditors, false);
view.setEditorListener(this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(key, isMasterKey);
mEditors.addView(view);
}
this.updateEditorsVisible();
}
private void createKey() {
mProgressDialog = new ProgressDialog(getContext());
mProgressDialog.setMessage(getContext().getString(R.string.progress_generating));
mProgressDialog.setCancelable(false);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.show();
mRunningThread = new Thread(this);
mRunningThread.start();
}
public void run() {
String error = null;
try {
PGPSecretKey masterKey = null;
String passPhrase;
if (mEditors.getChildCount() > 0) {
masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID());
} else {
passPhrase = "";
}
mNewKey = Apg.createKey(getContext(),
mNewKeyAlgorithmChoice.getId(),
mNewKeySize, passPhrase,
masterKey);
} catch (NoSuchProviderException e) {
error = "" + e;
} catch (NoSuchAlgorithmException e) {
error = "" + e;
} catch (PGPException e) {
error = "" + e;
} catch (InvalidParameterException e) {
error = "" + e;
} catch (InvalidAlgorithmParameterException e) {
error = "" + e;
} catch (Apg.GeneralException e) {
error = "" + e;
}
Message message = new Message();
Bundle data = new Bundle();
data.putBoolean("closeProgressDialog", true);
if (error != null) {
data.putString(Apg.EXTRA_ERROR, error);
} else {
data.putBoolean("gotNewKey", true);
}
message.setData(data);
mHandler.sendMessage(message);
}
}
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.utils.Choice;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Runnable {
private LayoutInflater mInflater;
private View mAdd;
private ViewGroup mEditors;
private TextView mTitle;
private int mType = 0;
private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize;
volatile private PGPSecretKey mNewKey;
private ProgressDialog mProgressDialog;
private Thread mRunningThread = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
if (data != null) {
boolean closeProgressDialog = data.getBoolean("closeProgressDialog");
if (closeProgressDialog) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) {
Toast.makeText(getContext(),
getContext().getString(R.string.errorMessage, error),
Toast.LENGTH_SHORT).show();
}
boolean gotNewKey = data.getBoolean("gotNewKey");
if (gotNewKey) {
KeyEditor view =
(KeyEditor) mInflater.inflate(R.layout.edit_key_key_item,
mEditors, false);
view.setEditorListener(SectionView.this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(mNewKey, isMasterKey);
mEditors.addView(view);
SectionView.this.updateEditorsVisible();
}
}
}
};
public SectionView(Context context) {
super(context);
}
public SectionView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ViewGroup getEditors() {
return mEditors;
}
public void setType(int type) {
mType = type;
switch (type) {
case Id.type.user_id: {
mTitle.setText(R.string.section_userIds);
break;
}
case Id.type.key: {
mTitle.setText(R.string.section_keys);
break;
}
default: {
break;
}
}
}
/** {@inheritDoc} */
@Override
protected void onFinishInflate() {
mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mAdd = findViewById(R.id.header);
mAdd.setOnClickListener(this);
mEditors = (ViewGroup) findViewById(R.id.editors);
mTitle = (TextView) findViewById(R.id.title);
updateEditorsVisible();
super.onFinishInflate();
}
/** {@inheritDoc} */
public void onDeleted(Editor editor) {
this.updateEditorsVisible();
}
protected void updateEditorsVisible() {
final boolean hasChildren = mEditors.getChildCount() > 0;
mEditors.setVisibility(hasChildren ? View.VISIBLE : View.GONE);
}
/** {@inheritDoc} */
public void onClick(View v) {
switch (mType) {
case Id.type.user_id: {
UserIdEditor view =
(UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item,
mEditors, false);
view.setEditorListener(this);
if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true);
}
mEditors.addView(view);
break;
}
case Id.type.key: {
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
View view = mInflater.inflate(R.layout.create_key, null);
dialog.setView(view);
dialog.setTitle(R.string.title_createKey);
dialog.setMessage(R.string.keyCreationElGamalInfo);
boolean wouldBeMasterKey = (mEditors.getChildCount() == 0);
final Spinner algorithm = (Spinner) view.findViewById(R.id.algorithm);
Vector<Choice> choices = new Vector<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa,
getResources().getString(R.string.dsa)));
if (!wouldBeMasterKey) {
choices.add(new Choice(Id.choice.algorithm.elgamal,
getResources().getString(R.string.elgamal)));
}
choices.add(new Choice(Id.choice.algorithm.rsa,
getResources().getString(R.string.rsa)));
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item,
choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
algorithm.setAdapter(adapter);
// make RSA the default
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
algorithm.setSelection(i);
break;
}
}
final EditText keySize = (EditText) view.findViewById(R.id.size);
dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface di, int id) {
di.dismiss();
try {
mNewKeySize = Integer.parseInt("" + keySize.getText());
} catch (NumberFormatException e) {
mNewKeySize = 0;
}
mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
createKey();
}
});
dialog.setCancelable(true);
dialog.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface di, int id) {
di.dismiss();
}
});
dialog.create().show();
break;
}
default: {
break;
}
}
this.updateEditorsVisible();
}
public void setUserIds(Vector<String> list) {
if (mType != Id.type.user_id) {
return;
}
mEditors.removeAllViews();
for (String userId : list) {
UserIdEditor view =
(UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, mEditors, false);
view.setEditorListener(this);
view.setValue(userId);
if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true);
}
mEditors.addView(view);
}
this.updateEditorsVisible();
}
public void setKeys(Vector<PGPSecretKey> list) {
if (mType != Id.type.key) {
return;
}
mEditors.removeAllViews();
for (PGPSecretKey key : list) {
KeyEditor view =
(KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, mEditors, false);
view.setEditorListener(this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(key, isMasterKey);
mEditors.addView(view);
}
this.updateEditorsVisible();
}
private void createKey() {
mProgressDialog = new ProgressDialog(getContext());
mProgressDialog.setMessage(getContext().getString(R.string.progress_generating));
mProgressDialog.setCancelable(false);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.show();
mRunningThread = new Thread(this);
mRunningThread.start();
}
public void run() {
String error = null;
try {
PGPSecretKey masterKey = null;
String passPhrase;
if (mEditors.getChildCount() > 0) {
masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID());
} else {
passPhrase = "";
}
mNewKey = Apg.createKey(getContext(),
mNewKeyAlgorithmChoice.getId(),
mNewKeySize, passPhrase,
masterKey);
} catch (NoSuchProviderException e) {
error = "" + e;
} catch (NoSuchAlgorithmException e) {
error = "" + e;
} catch (PGPException e) {
error = "" + e;
} catch (InvalidParameterException e) {
error = "" + e;
} catch (InvalidAlgorithmParameterException e) {
error = "" + e;
} catch (Apg.GeneralException e) {
error = "" + e;
}
Message message = new Message();
Bundle data = new Bundle();
data.putBoolean("closeProgressDialog", true);
if (error != null) {
data.putString(Apg.EXTRA_ERROR, error);
} else {
data.putBoolean("gotNewKey", true);
}
message.setData(data);
mHandler.sendMessage(message);
}
}

View File

@@ -1,194 +1,194 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.thialfihar.android.apg.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
private ImageButton mDeleteButton;
private RadioButton mIsMainUserId;
private EditText mName;
private EditText mEmail;
private EditText mComment;
private static final Pattern EMAIL_PATTERN =
Pattern.compile("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+[.]([a-zA-Z])+([a-zA-Z])+",
Pattern.CASE_INSENSITIVE);
public static class NoNameException extends Exception {
static final long serialVersionUID = 0xf812773343L;
public NoNameException(String message) {
super(message);
}
}
public static class NoEmailException extends Exception {
static final long serialVersionUID = 0xf812773344L;
public NoEmailException(String message) {
super(message);
}
}
public static class InvalidEmailException extends Exception {
static final long serialVersionUID = 0xf812773345L;
public InvalidEmailException(String message) {
super(message);
}
}
public UserIdEditor(Context context) {
super(context);
}
public UserIdEditor(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId);
mIsMainUserId.setOnClickListener(this);
mName = (EditText) findViewById(R.id.name);
mEmail = (EditText) findViewById(R.id.email);
mComment = (EditText) findViewById(R.id.comment);
super.onFinishInflate();
}
public void setValue(String userId) {
mName.setText("");
mComment.setText("");
mEmail.setText("");
Pattern withComment = Pattern.compile("^(.*) [(](.*)[)] <(.*)>$");
Matcher matcher = withComment.matcher(userId);
if (matcher.matches()) {
mName.setText(matcher.group(1));
mComment.setText(matcher.group(2));
mEmail.setText(matcher.group(3));
return;
}
Pattern withoutComment = Pattern.compile("^(.*) <(.*)>$");
matcher = withoutComment.matcher(userId);
if (matcher.matches()) {
mName.setText(matcher.group(1));
mEmail.setText(matcher.group(2));
return;
}
}
public String getValue() throws NoNameException, NoEmailException, InvalidEmailException {
String name = ("" + mName.getText()).trim();
String email = ("" + mEmail.getText()).trim();
String comment = ("" + mComment.getText()).trim();
if (email.length() > 0) {
Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
if (!emailMatcher.matches()) {
throw new InvalidEmailException(
getContext().getString(R.string.error_invalidEmail, email));
}
}
String userId = name;
if (comment.length() > 0) {
userId += " (" + comment + ")";
}
if (email.length() > 0) {
userId += " <" + email + ">";
}
if (userId.equals("")) {
// ok, empty one...
return userId;
}
// otherwise make sure that name and email exist
if (name.equals("")) {
throw new NoNameException("need a name");
}
if (email.equals("")) {
throw new NoEmailException("need an email");
}
return userId;
}
@Override
public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) {
boolean wasMainUserId = mIsMainUserId.isChecked();
parent.removeView(this);
if (mEditorListener != null) {
mEditorListener.onDeleted(this);
}
if (wasMainUserId && parent.getChildCount() > 0) {
UserIdEditor editor = (UserIdEditor) parent.getChildAt(0);
editor.setIsMainUserId(true);
}
} else if (v == mIsMainUserId) {
for (int i = 0; i < parent.getChildCount(); ++i) {
UserIdEditor editor = (UserIdEditor) parent.getChildAt(i);
if (editor == this) {
editor.setIsMainUserId(true);
} else {
editor.setIsMainUserId(false);
}
}
}
}
public void setIsMainUserId(boolean value) {
mIsMainUserId.setChecked(value);
}
public boolean isMainUserId() {
return mIsMainUserId.isChecked();
}
@Override
public void setEditorListener(EditorListener listener) {
mEditorListener = listener;
}
}
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.thialfihar.android.apg.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
private ImageButton mDeleteButton;
private RadioButton mIsMainUserId;
private EditText mName;
private EditText mEmail;
private EditText mComment;
private static final Pattern EMAIL_PATTERN =
Pattern.compile("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+[.]([a-zA-Z])+([a-zA-Z])+",
Pattern.CASE_INSENSITIVE);
public static class NoNameException extends Exception {
static final long serialVersionUID = 0xf812773343L;
public NoNameException(String message) {
super(message);
}
}
public static class NoEmailException extends Exception {
static final long serialVersionUID = 0xf812773344L;
public NoEmailException(String message) {
super(message);
}
}
public static class InvalidEmailException extends Exception {
static final long serialVersionUID = 0xf812773345L;
public InvalidEmailException(String message) {
super(message);
}
}
public UserIdEditor(Context context) {
super(context);
}
public UserIdEditor(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId);
mIsMainUserId.setOnClickListener(this);
mName = (EditText) findViewById(R.id.name);
mEmail = (EditText) findViewById(R.id.email);
mComment = (EditText) findViewById(R.id.comment);
super.onFinishInflate();
}
public void setValue(String userId) {
mName.setText("");
mComment.setText("");
mEmail.setText("");
Pattern withComment = Pattern.compile("^(.*) [(](.*)[)] <(.*)>$");
Matcher matcher = withComment.matcher(userId);
if (matcher.matches()) {
mName.setText(matcher.group(1));
mComment.setText(matcher.group(2));
mEmail.setText(matcher.group(3));
return;
}
Pattern withoutComment = Pattern.compile("^(.*) <(.*)>$");
matcher = withoutComment.matcher(userId);
if (matcher.matches()) {
mName.setText(matcher.group(1));
mEmail.setText(matcher.group(2));
return;
}
}
public String getValue() throws NoNameException, NoEmailException, InvalidEmailException {
String name = ("" + mName.getText()).trim();
String email = ("" + mEmail.getText()).trim();
String comment = ("" + mComment.getText()).trim();
if (email.length() > 0) {
Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
if (!emailMatcher.matches()) {
throw new InvalidEmailException(
getContext().getString(R.string.error_invalidEmail, email));
}
}
String userId = name;
if (comment.length() > 0) {
userId += " (" + comment + ")";
}
if (email.length() > 0) {
userId += " <" + email + ">";
}
if (userId.equals("")) {
// ok, empty one...
return userId;
}
// otherwise make sure that name and email exist
if (name.equals("")) {
throw new NoNameException("need a name");
}
if (email.equals("")) {
throw new NoEmailException("need an email");
}
return userId;
}
@Override
public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) {
boolean wasMainUserId = mIsMainUserId.isChecked();
parent.removeView(this);
if (mEditorListener != null) {
mEditorListener.onDeleted(this);
}
if (wasMainUserId && parent.getChildCount() > 0) {
UserIdEditor editor = (UserIdEditor) parent.getChildAt(0);
editor.setIsMainUserId(true);
}
} else if (v == mIsMainUserId) {
for (int i = 0; i < parent.getChildCount(); ++i) {
UserIdEditor editor = (UserIdEditor) parent.getChildAt(i);
if (editor == this) {
editor.setIsMainUserId(true);
} else {
editor.setIsMainUserId(false);
}
}
}
}
public void setIsMainUserId(boolean value) {
mIsMainUserId.setChecked(value);
}
public boolean isMainUserId() {
return mIsMainUserId.isChecked();
}
@Override
public void setEditorListener(EditorListener listener) {
mEditorListener = listener;
}
}