major restructuring, moving dialog, message, menu, option menu, task, type IDs into Id in a similar structure as the generated R, also introducing a BaseActivity class that almost all activities derive from, which generates some common dialogs, handles the progress update, thread management, and thread communication

also adding first draft of encrypt file activity, not very functional yet
This commit is contained in:
Thialfihar 2010-04-19 02:12:13 +00:00
parent 09741b0286
commit d5c5a2c43b
44 changed files with 2367 additions and 1754 deletions

8
.classpath Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/BouncyCastlePort"/>
<classpathentry kind="output" path="bin"/>
</classpath>

33
.project Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>APG 0.9.x</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -14,72 +14,99 @@
limitations under the License. limitations under the License.
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest
package="org.thialfihar.android.apg" xmlns:android="http://schemas.android.com/apk/res/android"
android:versionName="0.9.0" android:versionCode="5"> package="org.thialfihar.android.apg"
<application android:icon="@drawable/icon" android:label="@string/app_name"> android:versionName="0.9.0" android:versionCode="5">
<activity android:name=".MainActivity"
android:label="@string/app_name" <application
android:configChanges="keyboardHidden|orientation|keyboard"> android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|keyboard">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".PublicKeyListActivity" <activity
android:label="@string/title_managePublicKeys" android:name=".PublicKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_managePublicKeys"
</activity> android:configChanges="keyboardHidden|orientation|keyboard" />
<activity android:name=".SecretKeyListActivity" <activity
android:label="@string/title_manageSecretKeys" android:name=".SecretKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_manageSecretKeys"
</activity> android:configChanges="keyboardHidden|orientation|keyboard"/>
<activity android:name=".EditKeyActivity" <activity
android:label="@string/title_editKey" android:name=".EditKeyActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_editKey"
</activity> android:configChanges="keyboardHidden|orientation|keyboard"/>
<activity android:name=".SelectPublicKeyListActivity" <activity
android:label="@string/title_selectRecipients" android:name=".SelectPublicKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_selectRecipients"
</activity> android:configChanges="keyboardHidden|orientation|keyboard"/>
<activity android:name=".SelectSecretKeyListActivity" <activity
android:label="@string/title_selectSignature" android:name=".SelectSecretKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_selectSignature"
</activity> android:configChanges="keyboardHidden|orientation|keyboard"/>
<activity
android:name=".EncryptMessageActivity"
android:label="@string/title_encryptMessage"
android:configChanges="keyboardHidden|orientation|keyboard">
<activity android:name=".EncryptMessageActivity"
android:label="@string/title_encryptMessage"
android:configChanges="keyboardHidden|orientation|keyboard">
<intent-filter> <intent-filter>
<action android:name="org.thialfihar.android.apg.intent.ENCRYPT" /> <action android:name="org.thialfihar.android.apg.intent.ENCRYPT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".DecryptMessageActivity" <activity
android:label="@string/title_decryptMessage" android:name=".EncryptFileActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_encryptFile"
android:configChanges="keyboardHidden|orientation|keyboard">
<intent-filter>
<action android:name="org.thialfihar.android.apg.intent.ENCRYPT_FILE" />
</intent-filter>
</activity>
<activity
android:name=".DecryptMessageActivity"
android:label="@string/title_decryptMessage"
android:configChanges="keyboardHidden|orientation|keyboard">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/*"/> <data android:mimeType="text/*"/>
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="org.thialfihar.android.apg.intent.DECRYPT" /> <action android:name="org.thialfihar.android.apg.intent.DECRYPT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".MailListActivity" <activity
android:label="@string/title_mailInbox" android:name=".MailListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"> android:label="@string/title_mailInbox"
</activity> android:configChanges="keyboardHidden|orientation|keyboard"/>
<provider android:name="org.thialfihar.android.apg.provider.DataProvider" <provider
android:authorities="org.thialfihar.android.apg.provider" /> android:name="org.thialfihar.android.apg.provider.DataProvider"
android:authorities="org.thialfihar.android.apg.provider" />
</application> </application>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="5" /> <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="5" />

BIN
bin/APG 0.9.x.apk Normal file

Binary file not shown.

BIN
bin/classes.dex Normal file

Binary file not shown.

BIN
bin/resources.ap_ Normal file

Binary file not shown.

View File

@ -24,12 +24,12 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"> android:layout_height="?android:attr/listPreferredItemHeight">
<TextView <TextView
android:id="@+id/account_name" android:id="@+id/account_name"
android:text="someone@gmail.com" android:text="someone@gmail.com"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/> android:layout_gravity="center_vertical"/>
</LinearLayout> </LinearLayout>

View File

@ -18,35 +18,47 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
<TableLayout <TableLayout
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:stretchColumns="1" android:stretchColumns="1"
android:layout_marginRight="?android:attr/scrollbarSize" android:layout_marginRight="?android:attr/scrollbarSize"
android:paddingLeft="6dip"> android:paddingLeft="6dip">
<TableRow> <TableRow>
<TextView android:id="@+id/label_algorithm" <TextView android:id="@+id/label_algorithm"
android:text="Algorithm" android:text="Algorithm"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:paddingRight="10dip"/> android:paddingRight="10dip"/>
<Spinner <Spinner
android:id="@+id/algorithm" android:id="@+id/algorithm"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TextView android:id="@+id/label_size" <TextView android:id="@+id/label_size"
android:text="Key Size" android:text="Key Size"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:paddingRight="10dip"/> android:paddingRight="10dip"/>
<EditText android:id="@+id/size" <EditText android:id="@+id/size"
android:text="1024" android:text="1024"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:gravity="right" android:numeric="integer"/> android:layout_width="fill_parent"
android:gravity="right"
android:numeric="integer"/>
</TableRow> </TableRow>
</TableLayout> </TableLayout>
</ScrollView> </ScrollView>

View File

@ -21,77 +21,79 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:fillViewport="true"> android:fillViewport="true">
<EditText <EditText
android:id="@+id/message" android:id="@+id/message"
android:inputType="text|textCapSentences|textMultiLine|textLongMessage" android:inputType="text|textCapSentences|textMultiLine|textLongMessage"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dip" android:layout_height="0dip"
android:layout_weight="1" android:layout_weight="1"
android:gravity="top"/> android:gravity="top"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:paddingLeft="5dip" android:paddingLeft="5dip"
android:paddingRight="5dip"> android:paddingRight="5dip">
<LinearLayout <LinearLayout
android:id="@+id/layout_signature" android:id="@+id/layout_signature"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_weight="2"> android:layout_weight="2">
<RelativeLayout <RelativeLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content"> android:layout_width="wrap_content">
<ImageView
android:id="@+id/ic_signature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/signed_large"/>
<ImageView <ImageView
android:id="@+id/ic_signature_status" android:id="@+id/ic_signature"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/overlay_error"/> android:src="@drawable/signed_large"/>
</RelativeLayout> <ImageView
android:id="@+id/ic_signature_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/overlay_error"/>
<LinearLayout </RelativeLayout>
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingLeft="5dip">
<TextView <LinearLayout
android:id="@+id/main_user_id" android:orientation="vertical"
android:text="Main User Id" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:paddingLeft="5dip">
android:layout_height="wrap_content"
android:layout_gravity="left"/>
<TextView <TextView
android:id="@+id/main_user_id_rest" android:id="@+id/main_user_id"
android:text="Main User Id Rest" android:text="Main User Id"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="left"/> android:layout_height="wrap_content"
android:layout_gravity="left"/>
<TextView
android:id="@+id/main_user_id_rest"
android:text="Main User Id Rest"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/btn_decrypt"
android:text="@string/btn_decrypt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout>
<Button
android:id="@+id/btn_decrypt"
android:text="@string/btn_decrypt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>

View File

@ -22,19 +22,21 @@
android:paddingTop="5dip" android:paddingTop="5dip"
android:fillViewport="true"> android:fillViewport="true">
<ScrollView <ScrollView
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dip" android:layout_height="0dip"
android:layout_weight="1"> android:layout_weight="1">
<LinearLayout
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_marginRight="?android:attr/scrollbarSize"/>
</ScrollView>
<LinearLayout <LinearLayout
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_marginRight="?android:attr/scrollbarSize"/>
</ScrollView>
<LinearLayout
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
@ -53,6 +55,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="@string/btn_doNotSave"/> android:text="@string/btn_doNotSave"/>
</LinearLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -15,99 +15,129 @@
--> -->
<org.thialfihar.android.apg.ui.widget.KeyEditor <org.thialfihar.android.apg.ui.widget.KeyEditor
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="5dip"> android:paddingLeft="5dip">
<View <View
android:id="@+id/separator" android:id="@+id/separator"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="1dip" android:layout_height="1dip"
android:background="?android:attr/listDivider"/> android:background="?android:attr/listDivider"/>
<LinearLayout <LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_marginLeft="16dip"
android:stretchColumns="1">
<TableRow>
<TextView android:id="@+id/label_key_id" android:text="Key ID"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<TextView
android:id="@+id/key_id"
android:text="00000000 00000000"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"
android:typeface="monospace"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/label_algorithm"
android:text="Algorithm"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<TextView android:id="@+id/algorithm"
android:text="Name"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/label_creation"
android:text="Creation"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<TextView
android:id="@+id/creation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/label_expiry"
android:text="Expiry"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<Button
android:id="@+id/expiry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</TableRow>
<TableRow>
<TextView android:id="@+id/label_usage"
android:text="Usage"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<Spinner
android:id="@+id/usage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</TableRow>
</TableLayout>
<ImageButton
android:id="@+id/edit_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/MinusButton" android:layout_width="fill_parent"
android:layout_gravity="center_vertical"/> android:orientation="horizontal">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_marginLeft="16dip"
android:stretchColumns="1">
<TableRow>
<TextView
android:id="@+id/label_key_id"
android:text="Key ID"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<TextView
android:id="@+id/key_id"
android:text="00000000 00000000"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"
android:typeface="monospace"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/label_algorithm"
android:text="Algorithm"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<TextView
android:id="@+id/algorithm"
android:text="Name"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/label_creation"
android:text="Creation"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<TextView
android:id="@+id/creation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/label_expiry"
android:text="Expiry"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<Button
android:id="@+id/expiry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/label_usage"
android:text="Usage"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"/>
<Spinner
android:id="@+id/usage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</TableRow>
</TableLayout>
<ImageButton
android:id="@+id/edit_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MinusButton"
android:layout_gravity="center_vertical"/>
</LinearLayout>
</LinearLayout>
</org.thialfihar.android.apg.ui.widget.KeyEditor> </org.thialfihar.android.apg.ui.widget.KeyEditor>

View File

@ -15,7 +15,7 @@
--> -->
<org.thialfihar.android.apg.ui.widget.SectionView <org.thialfihar.android.apg.ui.widget.SectionView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">

View File

@ -15,82 +15,99 @@
--> -->
<org.thialfihar.android.apg.ui.widget.UserIdEditor <org.thialfihar.android.apg.ui.widget.UserIdEditor
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="5dip"> android:paddingLeft="5dip">
<View <View
android:id="@+id/separator" android:id="@+id/separator"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="1dip" android:layout_height="1dip"
android:background="?android:attr/listDivider"/> android:background="?android:attr/listDivider"/>
<RadioButton <RadioButton
android:id="@+id/is_main_user_id" android:text="Main User ID" android:id="@+id/is_main_user_id"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="Main User ID"
android:layout_marginLeft="20dip"/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_marginLeft="16dip">
<TableRow>
<TextView
android:id="@+id/name_label"
android:text="Name"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
<EditText
android:id="@+id/name"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/email_label"
android:text="Email"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
<EditText
android:id="@+id/email"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/comment_label"
android:text="Comment"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
<EditText
android:id="@+id/comment"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
</TableLayout>
<ImageButton
android:id="@+id/edit_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/MinusButton" android:layout_width="wrap_content"
android:layout_gravity="center_vertical"/> android:layout_marginLeft="20dip"/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_marginLeft="16dip">
<TableRow>
<TextView
android:id="@+id/name_label"
android:text="Name"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
<EditText
android:id="@+id/name"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/email_label"
android:text="Email"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
<EditText
android:id="@+id/email"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow>
<TextView
android:id="@+id/comment_label"
android:text="Comment"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dip"/>
<EditText
android:id="@+id/comment"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
</TableLayout>
<ImageButton
android:id="@+id/edit_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MinusButton"
android:layout_gravity="center_vertical"/>
</LinearLayout>
</LinearLayout>
</org.thialfihar.android.apg.ui.widget.UserIdEditor> </org.thialfihar.android.apg.ui.widget.UserIdEditor>

166
res/layout/encrypt_file.xml Normal file
View File

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingTop="5dip">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="5dip"
android:paddingRight="5dip">
<TextView
android:id="@+id/label_filename"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:text="@string/label_file"/>
<EditText
android:id="@+id/filename"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<ImageButton
android:id="@+id/btn_browse"
android:src="@drawable/ic_launcher_folder_small"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
</LinearLayout>
<TabHost
android:id="@+id/tab_host"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="0dip">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="65dip"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="65dip">
<LinearLayout
android:id="@+id/tab_asymmetric"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="3dip"
android:orientation="horizontal">
<CheckBox
android:text="@string/sign"
android:id="@+id/sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<LinearLayout
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_gravity="center_vertical"
android:paddingRight="5dip">
<TextView
android:id="@+id/main_user_id"
android:text="Main User Id"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"/>
<TextView
android:id="@+id/main_user_id_rest"
android:text="Main User Id Rest"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"/>
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/separator"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider"/>
<TextView
android:id="@+id/label_encrypt_keys"
android:text="@string/label_encrypt_keys"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ListView
android:id="@+id/public_key_list"
android:choiceMode="multipleChoice"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/tab_symmetric"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
</TabHost>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@android:style/ButtonBar">
<Button
android:id="@+id/btn_encrypt"
android:text="@string/btn_encrypt"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View File

@ -21,75 +21,73 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:fillViewport="true"> android:fillViewport="true">
<EditText <EditText
android:id="@+id/message" android:id="@+id/message"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dip" android:layout_height="0dip"
android:layout_weight="1" android:layout_weight="1"
android:gravity="top" android:gravity="top"
android:inputType="text|textCapSentences|textMultiLine|textLongMessage"> android:inputType="text|textCapSentences|textMultiLine|textLongMessage"/>
</EditText>
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:paddingBottom="3dip"> android:layout_width="fill_parent"
android:paddingBottom="3dip">
<CheckBox <CheckBox
android:text="@string/sign" android:text="@string/sign"
android:id="@+id/sign" android:id="@+id/sign"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/> android:layout_gravity="center_vertical"/>
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:paddingRight="5dip"> android:paddingRight="5dip">
<TextView <TextView
android:id="@+id/main_user_id" android:id="@+id/main_user_id"
android:text="Main User Id" android:text="Main User Id"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="right"> android:layout_gravity="right"/>
</TextView>
<TextView <TextView
android:id="@+id/main_user_id_rest" android:id="@+id/main_user_id_rest"
android:text="Main User Id Rest" android:text="Main User Id Rest"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="right"> android:layout_height="wrap_content"
</TextView> android:layout_gravity="right"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@android:style/ButtonBar">
<Button
android:text="@string/btn_selectEncryptKeys"
android:id="@+id/btn_selectEncryptKeys"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_send"
android:text="@string/btn_send"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@android:style/ButtonBar">
<Button
android:text="@string/btn_selectEncryptKeys"
android:id="@+id/btn_selectEncryptKeys"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_send"
android:text="@string/btn_send"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View File

@ -15,21 +15,23 @@
--> -->
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="5dip" android:orientation="horizontal"
android:paddingRight="5dip" android:paddingLeft="5dip"
> android:paddingRight="5dip">
<EditText <EditText
android:id="@+id/input" android:id="@+id/input"
android:layout_width="wrap_content" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"/>
/>
<ImageButton <ImageButton
android:id="@+id/btn_browse" android:id="@+id/btn_browse"
android:src="@drawable/ic_launcher_folder_small"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_folder_small" android:layout_width="wrap_content"/> android:layout_width="wrap_content"/>
</LinearLayout> </LinearLayout>

28
res/layout/key_list.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<ExpandableListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</ScrollView>

View File

@ -19,54 +19,62 @@
android:singleLine="true" android:singleLine="true"
android:paddingLeft="10dip" android:paddingLeft="10dip"
android:layout_marginRight="?android:attr/scrollbarSize" android:layout_marginRight="?android:attr/scrollbarSize"
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_width="fill_parent"> android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent">
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingRight="3dip"> android:paddingRight="3dip">
<ImageView <ImageView
android:id="@+id/ic_master_key" android:id="@+id/ic_master_key"
android:src="@drawable/key_small" android:src="@drawable/key_small"
android:paddingRight="6dip" android:paddingRight="6dip"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_vertical"/> android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<TextView <TextView
android:id="@+id/key_id" android:id="@+id/key_id"
android:text="Key ID" android:text="Key ID"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:paddingRight="5dip" android:typeface="monospace"/> android:layout_height="wrap_content"
android:paddingRight="5dip"
android:typeface="monospace"/>
<TextView <TextView
android:id="@+id/key_details" android:id="@+id/key_details"
android:text="(RSA, 1024bit)" android:text="(RSA, 1024bit)"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<LinearLayout
android:gravity="right"
android:orientation="horizontal"
android:paddingBottom="2dip"
android:paddingTop="2dip"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical">
<LinearLayout <ImageView
android:gravity="right" android:id="@+id/ic_encrypt_key"
android:orientation="horizontal" android:src="@drawable/encrypted_small"
android:layout_width="fill_parent" android:paddingBottom="2dip" android:paddingTop="2dip" android:layout_height="fill_parent" android:layout_gravity="center_vertical"> android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView <ImageView
android:id="@+id/ic_encrypt_key" android:id="@+id/ic_sign_key"
android:src="@drawable/encrypted_small" android:src="@drawable/signed_small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<ImageView </LinearLayout>
android:id="@+id/ic_sign_key"
android:src="@drawable/signed_small" </LinearLayout>
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -22,49 +22,51 @@
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingRight="3dip"> android:paddingRight="3dip">
<TextView <TextView
android:id="@+id/key_id" android:id="@+id/key_id"
android:text="Key ID" android:text="Key ID"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:paddingRight="5dip" android:typeface="monospace"/> android:layout_height="wrap_content"
android:paddingRight="5dip"
android:typeface="monospace"/>
<TextView <TextView
android:id="@+id/key_details" android:id="@+id/key_details"
android:text="(RSA, 1024bit)" android:text="(RSA, 1024bit)"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<LinearLayout
android:gravity="right"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="2dip"
android:paddingTop="2dip"
android:layout_gravity="center_vertical">
<LinearLayout <ImageView
android:gravity="right" android:id="@+id/ic_encrypt_key"
android:orientation="horizontal" android:src="@drawable/encrypted_small"
android:layout_width="fill_parent" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:layout_height="wrap_content"/>
android:paddingBottom="2dip"
android:paddingTop="2dip"
android:layout_gravity="center_vertical">
<ImageView <ImageView
android:id="@+id/ic_encrypt_key" android:id="@+id/ic_sign_key"
android:src="@drawable/encrypted_small" android:src="@drawable/signed_small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<ImageView </LinearLayout>
android:id="@+id/ic_sign_key"
android:src="@drawable/signed_small" </LinearLayout>
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -22,12 +22,12 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"> android:layout_height="?android:attr/listPreferredItemHeight">
<TextView <TextView
android:id="@+id/user_id" android:id="@+id/user_id"
android:text="User ID" android:text="User ID"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingRight="3dip"/> android:paddingRight="3dip"/>
</LinearLayout> </LinearLayout>

View File

@ -21,32 +21,33 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"> android:layout_height="?android:attr/listPreferredItemHeight">
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:paddingLeft="36dip"> android:layout_height="wrap_content"
android:paddingLeft="36dip">
<TextView <TextView
android:id="@+id/main_user_id" android:id="@+id/main_user_id"
android:text="Main User ID" android:text="Main User ID"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView <TextView
android:id="@+id/main_user_id_rest" android:id="@+id/main_user_id_rest"
android:text="&lt;user@somewhere.com&gt;" android:text="&lt;user@somewhere.com&gt;"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -24,34 +24,34 @@
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
<ImageView <ImageView
android:id="@+id/ic_status" android:id="@+id/ic_status"
android:src="@drawable/encrypted" android:src="@drawable/encrypted"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/> android:layout_gravity="center_vertical"/>
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="5dip" android:paddingLeft="5dip"
android:layout_weight="1" android:layout_weight="1"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <TextView
android:id="@+id/subject" android:id="@+id/subject"
android:text="Subject" android:text="Subject"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView <TextView
android:id="@+id/email_address" android:id="@+id/email_address"
android:text="user@somewhere.com" android:text="user@somewhere.com"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -22,41 +22,68 @@
android:paddingTop="5dip" android:paddingTop="5dip"
android:fillViewport="true"> android:fillViewport="true">
<ScrollView <ScrollView
android:layout_marginTop="10dip" android:layout_marginTop="10dip"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dip" android:layout_height="0dip"
android:layout_weight="1" android:layout_weight="1"
android:fillViewport="true"> android:fillViewport="true">
<ListView <ListView
android:id="@+id/account_list" android:id="@+id/account_list"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent"> android:layout_height="fill_parent"/>
</ListView>
</ScrollView> </ScrollView>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@android:style/ButtonBar"> style="@android:style/ButtonBar">
<Button <LinearLayout
android:id="@+id/btn_encryptMessage" android:orientation="horizontal"
android:text="@string/btn_encryptMessage" android:layout_width="fill_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content">
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button <Button
android:id="@+id/btn_decryptMessage" android:id="@+id/btn_encryptMessage"
android:text="@string/btn_decryptMessage" android:text="@string/btn_encryptMessage"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout> <Button
android:id="@+id/btn_decryptMessage"
android:text="@string/btn_decryptMessage"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_encryptFile"
android:text="@string/btn_encryptFile"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_decryptFile"
android:text="@string/btn_decryptFile"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -21,34 +21,33 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:fillViewport="true"> android:fillViewport="true">
<ListView <ListView
android:id="@+id/list" android:id="@+id/list"
android:choiceMode="multipleChoice" android:choiceMode="multipleChoice"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dip" android:layout_height="0dip"
android:layout_weight="1"> android:layout_weight="1"/>
</ListView>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@android:style/ButtonBar"> style="@android:style/ButtonBar">
<Button <Button
android:text="@android:string/ok" android:text="@android:string/ok"
android:id="@+id/btn_ok" android:id="@+id/btn_ok"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"/> android:layout_weight="1"/>
<Button <Button
android:text="@android:string/cancel" android:text="@android:string/cancel"
android:id="@+id/btn_cancel" android:id="@+id/btn_cancel"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"/> android:layout_weight="1"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -22,75 +22,76 @@
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
<CheckBox <CheckBox
android:id="@+id/selected" android:id="@+id/selected"
android:focusable="false" android:focusable="false"
android:focusableInTouchMode="false" android:focusableInTouchMode="false"
android:clickable="false" android:clickable="false"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="5dip" android:paddingLeft="5dip"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"> android:layout_weight="1">
<TextView <TextView
android:id="@+id/main_user_id" android:id="@+id/main_user_id"
android:text="Main User ID" android:text="Main User ID"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView <TextView
android:id="@+id/main_user_id_rest" android:id="@+id/main_user_id_rest"
android:text="&lt;user@somewhere.com&gt;" android:text="&lt;user@somewhere.com&gt;"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout </LinearLayout>
android:id="@+id/right_column"
android:orientation="vertical"
android:minWidth="90dip"
android:paddingLeft="3dip"
android:gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView <LinearLayout
android:id="@+id/key_id" android:id="@+id/right_column"
android:text="BBBBBBBB" android:orientation="vertical"
android:textAppearance="?android:attr/textAppearanceMedium" android:minWidth="90dip"
android:typeface="monospace" android:paddingLeft="3dip"
android:layout_width="wrap_content" android:gravity="right"
android:layout_height="fill_parent"/> android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView <TextView
android:id="@+id/creation" android:id="@+id/key_id"
android:textAppearance="?android:attr/textAppearanceSmall" android:text="BBBBBBBB"
android:text="31.12.2009" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:typeface="monospace"
android:layout_height="wrap_content"/> android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView <TextView
android:id="@+id/expiry" android:id="@+id/creation"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="31.12.2010" android:text="31.12.2009"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView <TextView
android:id="@+id/status" android:id="@+id/expiry"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="expired" android:text="31.12.2010"
android:textStyle="italic" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
android:layout_height="wrap_content"/>
<TextView
</LinearLayout> android:id="@+id/status"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="expired"
android:textStyle="italic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -21,10 +21,9 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:fillViewport="true"> android:fillViewport="true">
<ListView <ListView
android:id="@+id/list" android:id="@+id/list"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent"> android:layout_height="fill_parent"/>
</ListView>
</LinearLayout> </LinearLayout>

View File

@ -22,67 +22,68 @@
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="5dip" android:paddingLeft="5dip"
android:paddingRight="5dip" android:paddingRight="5dip"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"> android:layout_weight="1">
<TextView <TextView
android:id="@+id/main_user_id" android:id="@+id/main_user_id"
android:text="Main User ID" android:text="Main User ID"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView <TextView
android:id="@+id/main_user_id_rest" android:id="@+id/main_user_id_rest"
android:text="&lt;user@somewhere.com&gt;" android:text="&lt;user@somewhere.com&gt;"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout </LinearLayout>
android:orientation="vertical"
android:minWidth="90dip"
android:paddingLeft="3dip"
android:gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView <LinearLayout
android:id="@+id/key_id" android:orientation="vertical"
android:text="BBBBBBBB" android:minWidth="90dip"
android:textAppearance="?android:attr/textAppearanceMedium" android:paddingLeft="3dip"
android:typeface="monospace" android:gravity="right"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="fill_parent"/> android:layout_height="wrap_content">
<TextView <TextView
android:id="@+id/creation" android:id="@+id/key_id"
android:textAppearance="?android:attr/textAppearanceSmall" android:text="BBBBBBBB"
android:text="31.12.2009" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:typeface="monospace"
android:layout_height="wrap_content"/> android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView <TextView
android:id="@+id/expiry" android:id="@+id/creation"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="31.12.2010" android:text="31.12.2009"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<TextView <TextView
android:id="@+id/status" android:id="@+id/expiry"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="expired" android:text="31.12.2010"
android:textStyle="italic" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
android:layout_height="wrap_content"/>
<TextView
</LinearLayout> android:id="@+id/status"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="expired"
android:textStyle="italic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -23,6 +23,8 @@
<string name="title_selectSignature">Select Signature</string> <string name="title_selectSignature">Select Signature</string>
<string name="title_encryptMessage">Encrypt Message</string> <string name="title_encryptMessage">Encrypt Message</string>
<string name="title_decryptMessage">Decrypt Message</string> <string name="title_decryptMessage">Decrypt Message</string>
<string name="title_encryptFile">Encrypt File</string>
<string name="title_decryptFile">Decrypt File</string>
<string name="title_authentification">Authentification</string> <string name="title_authentification">Authentification</string>
<string name="title_createKey">Create Key</string> <string name="title_createKey">Create Key</string>
<string name="title_editKey">Edit Key</string> <string name="title_editKey">Edit Key</string>
@ -31,15 +33,21 @@
<string name="section_keys">Keys</string> <string name="section_keys">Keys</string>
<string name="btn_send">Send via Email</string> <string name="btn_send">Send via Email</string>
<string name="btn_encrypt">Encrypt</string>
<string name="btn_decrypt">Decrypt</string> <string name="btn_decrypt">Decrypt</string>
<string name="btn_verify">Verify</string> <string name="btn_verify">Verify</string>
<string name="btn_selectEncryptKeys">Select Recipients</string> <string name="btn_selectEncryptKeys">Select Recipients</string>
<string name="btn_reply">Reply</string> <string name="btn_reply">Reply</string>
<string name="btn_encryptMessage">Encrypt Message</string> <string name="btn_encryptMessage">Encrypt Message</string>
<string name="btn_decryptMessage">Decrypt Message</string> <string name="btn_decryptMessage">Decrypt Message</string>
<string name="btn_encryptFile">Encrypt File</string>
<string name="btn_decryptFile">Decrypt File</string>
<string name="btn_save">Save</string> <string name="btn_save">Save</string>
<string name="btn_doNotSave">Cancel</string> <string name="btn_doNotSave">Cancel</string>
<string name="tab_symmetric">Symmetric</string>
<string name="tab_asymmetric">Asymmetric</string>
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="menu_addAccount">Add GMail Account</string> <string name="menu_addAccount">Add GMail Account</string>
<string name="menu_managePublicKeys">Manage Public Keys</string> <string name="menu_managePublicKeys">Manage Public Keys</string>
@ -53,6 +61,9 @@
<string name="unknown_user_id">&lt;unknown&gt;</string> <string name="unknown_user_id">&lt;unknown&gt;</string>
<string name="none">&lt;none&gt;</string> <string name="none">&lt;none&gt;</string>
<string name="label_file">File:</string>
<string name="label_encrypt_keys">Encrypt with:</string>
<string name="sign_only">Sign only</string> <string name="sign_only">Sign only</string>
<string name="encrypt_only">Encrypt only</string> <string name="encrypt_only">Encrypt only</string>
<string name="sign_and_encrypt">Sign and Encrypt</string> <string name="sign_and_encrypt">Sign and Encrypt</string>

View File

@ -98,6 +98,8 @@ public class Apg {
public static class Intent { public static class Intent {
public static final String DECRYPT = "org.thialfihar.android.apg.intent.DECRYPT"; public static final String DECRYPT = "org.thialfihar.android.apg.intent.DECRYPT";
public static final String ENCRYPT = "org.thialfihar.android.apg.intent.ENCRYPT"; public static final String ENCRYPT = "org.thialfihar.android.apg.intent.ENCRYPT";
public static final String DECRYPT_FILE = "org.thialfihar.android.apg.intent.DECRYPT_FILE";
public static final String ENCRYPT_FILE = "org.thialfihar.android.apg.intent.ENCRYPT_FILE";
} }
public static String VERSION = "0.9.0"; public static String VERSION = "0.9.0";
@ -121,8 +123,8 @@ public class Apg {
CompressionAlgorithmTags.BZIP2, CompressionAlgorithmTags.BZIP2,
CompressionAlgorithmTags.ZIP }; CompressionAlgorithmTags.ZIP };
protected static Vector<PGPPublicKeyRing> mPublicKeyRings; protected static Vector<PGPPublicKeyRing> mPublicKeyRings = new Vector<PGPPublicKeyRing>();
protected static Vector<PGPSecretKeyRing> mSecretKeyRings; protected static Vector<PGPSecretKeyRing> mSecretKeyRings = new Vector<PGPSecretKeyRing>();
public static Pattern PGP_MESSAGE = public static Pattern PGP_MESSAGE =
Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
@ -139,9 +141,6 @@ public class Apg {
protected static final int RETURN_OK = 0; protected static final int RETURN_OK = 0;
protected static final int RETURN_UPDATED = 1; protected static final int RETURN_UPDATED = 1;
protected static final int TYPE_PUBLIC = 0;
protected static final int TYPE_SECRET = 1;
protected static HashMap<Long, Integer> mSecretKeyIdToIdMap; protected static HashMap<Long, Integer> mSecretKeyIdToIdMap;
protected static HashMap<Long, PGPSecretKeyRing> mSecretKeyIdToKeyRingMap; protected static HashMap<Long, PGPSecretKeyRing> mSecretKeyIdToKeyRingMap;
protected static HashMap<Long, Integer> mPublicKeyIdToIdMap; protected static HashMap<Long, Integer> mPublicKeyIdToIdMap;
@ -180,13 +179,12 @@ public class Apg {
} }
public static void initialize(Activity context) { public static void initialize(Activity context) {
setPassPhrase(null);
if (mInitialized) { if (mInitialized) {
return; return;
} }
loadKeyRings(context, TYPE_PUBLIC); loadKeyRings(context, Id.type.public_key);
loadKeyRings(context, TYPE_SECRET); loadKeyRings(context, Id.type.secret_key);
mInitialized = true; mInitialized = true;
} }
@ -546,8 +544,8 @@ public class Apg {
saveKeyRing(context, secretKeyRing); saveKeyRing(context, secretKeyRing);
saveKeyRing(context, publicKeyRing); saveKeyRing(context, publicKeyRing);
loadKeyRings(context, TYPE_PUBLIC); loadKeyRings(context, Id.type.public_key);
loadKeyRings(context, TYPE_SECRET); loadKeyRings(context, Id.type.secret_key);
progress.setProgress("done.", 100, 100); progress.setProgress("done.", 100, 100);
} }
@ -617,7 +615,7 @@ public class Apg {
Bundle returnData = new Bundle(); Bundle returnData = new Bundle();
PGPObjectFactory objectFactors = null; PGPObjectFactory objectFactors = null;
if (type == TYPE_SECRET) { if (type == Id.type.secret_key) {
progress.setProgress("importing secret keys...", 0, 100); progress.setProgress("importing secret keys...", 0, 100);
} else { } else {
progress.setProgress("importing public keys...", 0, 100); progress.setProgress("importing public keys...", 0, 100);
@ -647,7 +645,7 @@ public class Apg {
PGPSecretKeyRing secretKeyRing; PGPSecretKeyRing secretKeyRing;
int retValue; int retValue;
if (type == TYPE_SECRET) { if (type == Id.type.secret_key) {
if (!(obj instanceof PGPSecretKeyRing)) { if (!(obj instanceof PGPSecretKeyRing)) {
continue; continue;
} }
@ -729,7 +727,7 @@ public class Apg {
private static void loadKeyRings(Activity context, int type) { private static void loadKeyRings(Activity context, int type) {
Cursor cursor; Cursor cursor;
if (type == TYPE_SECRET) { if (type == Id.type.secret_key) {
mSecretKeyRings.clear(); mSecretKeyRings.clear();
mSecretKeyIdToIdMap.clear(); mSecretKeyIdToIdMap.clear();
mSecretKeyIdToKeyRingMap.clear(); mSecretKeyIdToKeyRingMap.clear();
@ -757,7 +755,7 @@ public class Apg {
long keyId = cursor.getLong(keyIdIndex); long keyId = cursor.getLong(keyIdIndex);
try { try {
if (type == TYPE_SECRET) { if (type == Id.type.secret_key) {
PGPSecretKeyRing key = new PGPSecretKeyRing(keyData); PGPSecretKeyRing key = new PGPSecretKeyRing(keyData);
mSecretKeyRings.add(key); mSecretKeyRings.add(key);
mSecretKeyIdToIdMap.put(keyId, id); mSecretKeyIdToIdMap.put(keyId, id);
@ -775,7 +773,7 @@ public class Apg {
} }
} }
if (type == TYPE_SECRET) { if (type == Id.type.secret_key) {
Collections.sort(mSecretKeyRings, new SecretKeySorter()); Collections.sort(mSecretKeyRings, new SecretKeySorter());
} else { } else {
Collections.sort(mPublicKeyRings, new PublicKeySorter()); Collections.sort(mPublicKeyRings, new PublicKeySorter());
@ -1059,14 +1057,14 @@ public class Apg {
PGPPublicKey masterKey = getMasterKey(keyRing); PGPPublicKey masterKey = getMasterKey(keyRing);
Uri uri = Uri.withAppendedPath(PublicKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID()); Uri uri = Uri.withAppendedPath(PublicKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID());
context.getContentResolver().delete(uri, null, null); context.getContentResolver().delete(uri, null, null);
loadKeyRings(context, TYPE_PUBLIC); loadKeyRings(context, Id.type.public_key);
} }
public static void deleteKey(Activity context, PGPSecretKeyRing keyRing) { public static void deleteKey(Activity context, PGPSecretKeyRing keyRing) {
PGPSecretKey masterKey = getMasterKey(keyRing); PGPSecretKey masterKey = getMasterKey(keyRing);
Uri uri = Uri.withAppendedPath(SecretKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID()); Uri uri = Uri.withAppendedPath(SecretKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID());
context.getContentResolver().delete(uri, null, null); context.getContentResolver().delete(uri, null, null);
loadKeyRings(context, TYPE_SECRET); loadKeyRings(context, Id.type.secret_key);
} }
public static PGPPublicKey findPublicKey(long keyId) { public static PGPPublicKey findPublicKey(long keyId) {

View File

@ -35,8 +35,6 @@ import android.widget.LinearLayout;
import android.widget.Toast; import android.widget.Toast;
public class AskForSecretKeyPassPhrase { public class AskForSecretKeyPassPhrase {
public static final int DIALOG_PASS_PHRASE = 12345;
public static interface PassPhraseCallbackInterface { public static interface PassPhraseCallbackInterface {
void passPhraseCallback(String passPhrase); void passPhraseCallback(String passPhrase);
} }
@ -91,7 +89,7 @@ public class AskForSecretKeyPassPhrase {
alert.setPositiveButton(android.R.string.ok, alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(DIALOG_PASS_PHRASE); activity.removeDialog(Id.dialog.pass_phrase);
String passPhrase = "" + input.getText(); String passPhrase = "" + input.getText();
try { try {
secretKey.extractPrivateKey(passPhrase.toCharArray(), secretKey.extractPrivateKey(passPhrase.toCharArray(),
@ -109,7 +107,7 @@ public class AskForSecretKeyPassPhrase {
alert.setNegativeButton(android.R.string.cancel, alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(DIALOG_PASS_PHRASE); activity.removeDialog(Id.dialog.pass_phrase);
} }
}); });

View File

@ -0,0 +1,235 @@
/*
* 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;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class BaseActivity extends Activity
implements Runnable, ProgressDialogUpdater,
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null;
private long mSecretKeyId = 0;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
handlerCallback(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Apg.initialize(this);
}
@Override
protected Dialog onCreateDialog(int id) {
// in case it is a progress dialog
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
switch (id) {
case Id.dialog.encrypting: {
mProgressDialog.setMessage("initializing...");
return mProgressDialog;
}
case Id.dialog.decrypting: {
mProgressDialog.setMessage("initializing...");
return mProgressDialog;
}
case Id.dialog.saving: {
mProgressDialog.setMessage("saving...");
return mProgressDialog;
}
case Id.dialog.importing: {
mProgressDialog.setMessage("importing...");
return mProgressDialog;
}
case Id.dialog.exporting: {
mProgressDialog.setMessage("exporting...");
return mProgressDialog;
}
default: {
break;
}
}
mProgressDialog = null;
switch (id) {
case Id.dialog.pass_phrase: {
return AskForSecretKeyPassPhrase.createDialog(this, getSecretKeyId(), this);
}
case Id.dialog.pass_phrases_do_not_match: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle("Error");
alert.setMessage("The pass phrases didn't match.");
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.pass_phrases_do_not_match);
}
});
alert.setCancelable(false);
return alert.create();
}
case Id.dialog.no_pass_phrase: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle("Error");
alert.setMessage("Empty pass phrases are not supported.");
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.no_pass_phrase);
}
});
alert.setCancelable(false);
return alert.create();
}
default: {
break;
}
}
return super.onCreateDialog(id);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", Id.message.progress_update);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
@Override
public void setProgress(String message, int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", Id.message.progress_update);
data.putString("message", message);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
public void handlerCallback(Message msg) {
Bundle data = msg.getData();
if (data == null) {
return;
}
int type = data.getInt("type");
switch (type) {
case Id.message.progress_update: {
String message = data.getString("message");
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt("max"));
mProgressDialog.setProgress(data.getInt("progress"));
}
break;
}
case Id.message.import_done: // intentionall no break
case Id.message.export_done: // intentionall no break
case Id.message.done: {
mProgressDialog = null;
doneCallback(msg);
break;
}
}
}
public void doneCallback(Message msg) {
}
public void passPhraseCallback(String passPhrase) {
Log.e("oink", "setting pass phrase to " + passPhrase);
Apg.setPassPhrase(passPhrase);
}
public void sendMessage(Message msg) {
mHandler.sendMessage(msg);
}
public void startThread() {
mRunningThread = new Thread(this);
mRunningThread.start();
}
public void run() {
}
public void setSecretKeyId(long id) {
mSecretKeyId = id;
}
public long getSecretKeyId() {
return mSecretKeyId;
}
}

View File

@ -29,13 +29,9 @@ import org.bouncycastle2.jce.provider.BouncyCastleProvider;
import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.util.Strings; import org.bouncycastle2.util.Strings;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.ClipboardManager; import android.text.ClipboardManager;
import android.view.View; import android.view.View;
@ -47,27 +43,13 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class DecryptMessageActivity extends Activity public class DecryptMessageActivity extends BaseActivity {
implements Runnable, ProgressDialogUpdater,
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
static final int GET_PUCLIC_KEYS = 1;
static final int GET_SECRET_KEY = 2;
static final int DIALOG_DECRYPTING = 1;
static final int MESSAGE_PROGRESS_UPDATE = 1;
static final int MESSAGE_DONE = 2;
private long mDecryptionKeyId = 0;
private long mSignatureKeyId = 0; private long mSignatureKeyId = 0;
private String mReplyTo = null; private String mReplyTo = null;
private String mSubject = null; private String mSubject = null;
private boolean mSignedOnly = false; private boolean mSignedOnly = false;
private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null;
private EditText mMessage = null; private EditText mMessage = null;
private LinearLayout mSignatureLayout = null; private LinearLayout mSignatureLayout = null;
private ImageView mSignatureStatusImage = null; private ImageView mSignatureStatusImage = null;
@ -75,90 +57,11 @@ public class DecryptMessageActivity extends Activity
private TextView mUserIdRest = null; private TextView mUserIdRest = null;
private Button mDecryptButton = null; private Button mDecryptButton = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case MESSAGE_PROGRESS_UPDATE: {
String message = data.getString("message");
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt("max"));
mProgressDialog.setProgress(data.getInt("progress"));
}
break;
}
case MESSAGE_DONE: {
removeDialog(DIALOG_DECRYPTING);
mProgressDialog = null;
mSignatureKeyId = 0;
String error = data.getString("error");
String decryptedMessage = data.getString("decryptedMessage");
if (error != null) {
Toast.makeText(DecryptMessageActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
}
mSignatureLayout.setVisibility(View.INVISIBLE);
if (decryptedMessage != null) {
mMessage.setText(decryptedMessage);
mDecryptButton.setText(R.string.btn_reply);
mDecryptButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
replyClicked();
}
});
if (data.getBoolean("signature")) {
String userId = data.getString("signatureUserId");
mSignatureKeyId = data.getLong("signatureKeyId");
mUserIdRest.setText("id: " +
Long.toHexString(mSignatureKeyId & 0xffffffffL));
if (userId == null) {
userId =
getResources()
.getString(
R.string.unknown_user_id);
}
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mUserIdRest.setText("<" + chunks[1]);
}
mUserId.setText(userId);
if (data.getBoolean("signatureSuccess")) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
} else if (data.getBoolean("signatureUnknown")) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
} else {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
}
mSignatureLayout.setVisibility(View.VISIBLE);
}
}
break;
}
}
}
}
};
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.decrypt_message); setContentView(R.layout.decrypt_message);
Apg.initialize(this);
mMessage = (EditText) findViewById(R.id.message); mMessage = (EditText) findViewById(R.id.message);
mDecryptButton = (Button) findViewById(R.id.btn_decrypt); mDecryptButton = (Button) findViewById(R.id.btn_decrypt);
mSignatureLayout = (LinearLayout) findViewById(R.id.layout_signature); mSignatureLayout = (LinearLayout) findViewById(R.id.layout_signature);
@ -232,48 +135,6 @@ public class DecryptMessageActivity extends Activity
} }
} }
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_DECRYPTING: {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("initializing...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE: {
return AskForSecretKeyPassPhrase.createDialog(this, mDecryptionKeyId, this);
}
}
return super.onCreateDialog(id);
}
@Override
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
@Override
public void setProgress(String message, int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putString("message", message);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
private void decryptClicked() { private void decryptClicked() {
String error = null; String error = null;
String messageData = mMessage.getText().toString(); String messageData = mMessage.getText().toString();
@ -289,8 +150,8 @@ public class DecryptMessageActivity extends Activity
ByteArrayInputStream in = ByteArrayInputStream in =
new ByteArrayInputStream(messageData.getBytes()); new ByteArrayInputStream(messageData.getBytes());
try { try {
mDecryptionKeyId = Apg.getDecryptionKeyId(in); setSecretKeyId(Apg.getDecryptionKeyId(in));
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE); showDialog(Id.dialog.pass_phrase);
} catch (IOException e) { } catch (IOException e) {
error = e.getLocalizedMessage(); error = e.getLocalizedMessage();
} catch (Apg.GeneralException e) { } catch (Apg.GeneralException e) {
@ -311,22 +172,23 @@ public class DecryptMessageActivity extends Activity
intent.putExtra("subject", "Re: " + mSubject); intent.putExtra("subject", "Re: " + mSubject);
intent.putExtra("sendTo", mReplyTo); intent.putExtra("sendTo", mReplyTo);
intent.putExtra("eyId", mSignatureKeyId); intent.putExtra("eyId", mSignatureKeyId);
intent.putExtra("signatureKeyId", mDecryptionKeyId); intent.putExtra("signatureKeyId", getSecretKeyId());
intent.putExtra("encryptionKeyIds", new long[] { mSignatureKeyId }); intent.putExtra("encryptionKeyIds", new long[] { mSignatureKeyId });
startActivity(intent); startActivity(intent);
} }
@Override
public void passPhraseCallback(String passPhrase) { public void passPhraseCallback(String passPhrase) {
Apg.setPassPhrase(passPhrase); super.passPhraseCallback(passPhrase);
decryptStart(); decryptStart();
} }
private void decryptStart() { private void decryptStart() {
showDialog(DIALOG_DECRYPTING); showDialog(Id.dialog.decrypting);
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
@Override
public void run() { public void run() {
String error = null; String error = null;
Security.addProvider(new BouncyCastleProvider()); Security.addProvider(new BouncyCastleProvider());
@ -356,7 +218,7 @@ public class DecryptMessageActivity extends Activity
error = e.getMessage(); error = e.getMessage();
} }
data.putInt("type", MESSAGE_DONE); data.putInt("type", Id.message.done);
if (error != null) { if (error != null) {
data.putString("error", error); data.putString("error", error);
@ -365,6 +227,61 @@ public class DecryptMessageActivity extends Activity
} }
msg.setData(data); msg.setData(data);
mHandler.sendMessage(msg); sendMessage(msg);
}
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
Bundle data = msg.getData();
removeDialog(Id.dialog.decrypting);
mSignatureKeyId = 0;
String error = data.getString("error");
String decryptedMessage = data.getString("decryptedMessage");
if (error != null) {
Toast.makeText(DecryptMessageActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
}
mSignatureLayout.setVisibility(View.INVISIBLE);
if (decryptedMessage != null) {
mMessage.setText(decryptedMessage);
mDecryptButton.setText(R.string.btn_reply);
mDecryptButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
replyClicked();
}
});
if (data.getBoolean("signature")) {
String userId = data.getString("signatureUserId");
mSignatureKeyId = data.getLong("signatureKeyId");
mUserIdRest.setText("id: " +
Long.toHexString(mSignatureKeyId & 0xffffffffL));
if (userId == null) {
userId =
getResources()
.getString(
R.string.unknown_user_id);
}
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mUserIdRest.setText("<" + chunks[1]);
}
mUserId.setText(userId);
if (data.getBoolean("signatureSuccess")) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
} else if (data.getBoolean("signatureUnknown")) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
} else {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
}
mSignatureLayout.setVisibility(View.VISIBLE);
}
}
} }
} }

View File

@ -27,18 +27,16 @@ import org.bouncycastle2.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.ui.widget.SectionView; import org.thialfihar.android.apg.ui.widget.SectionView;
import org.thialfihar.android.apg.utils.IterableIterator; import org.thialfihar.android.apg.utils.IterableIterator;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.InputType; import android.text.InputType;
import android.text.method.PasswordTransformationMethod; import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -50,17 +48,7 @@ import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Toast; import android.widget.Toast;
public class EditKeyActivity extends Activity public class EditKeyActivity extends BaseActivity implements OnClickListener {
implements OnClickListener, ProgressDialogUpdater, Runnable {
static final int OPTION_MENU_NEW_PASS_PHRASE = 1;
static final int DIALOG_NEW_PASS_PHRASE = 1;
static final int DIALOG_PASS_PHRASES_DO_NOT_MATCH = 2;
static final int DIALOG_NO_PASS_PHRASE = 3;
static final int DIALOG_SAVING = 4;
static final int MESSAGE_PROGRESS_UPDATE = 1;
static final int MESSAGE_DONE = 2;
private PGPSecretKeyRing mKeyRing = null; private PGPSecretKeyRing mKeyRing = null;
@ -70,56 +58,8 @@ public class EditKeyActivity extends Activity
private Button mSaveButton; private Button mSaveButton;
private Button mDiscardButton; private Button mDiscardButton;
private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null;
private String mNewPassPhrase = null; private String mNewPassPhrase = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case MESSAGE_PROGRESS_UPDATE: {
String message = data.getString("message");
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt("max"));
mProgressDialog.setProgress(data.getInt("progress"));
}
break;
}
case MESSAGE_DONE: {
removeDialog(DIALOG_SAVING);
mProgressDialog = null;
String error = data.getString("error");
if (error != null) {
Toast.makeText(EditKeyActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(EditKeyActivity.this, R.string.key_saved,
Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
finish();
}
break;
}
default: {
break;
}
}
}
}
};
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -176,13 +116,14 @@ public class EditKeyActivity extends Activity
} }
public boolean havePassPhrase() { public boolean havePassPhrase() {
Log.e("oink", "password is " + Apg.getPassPhrase());
return (Apg.getPassPhrase() != null && !Apg.getPassPhrase().equals("")) || return (Apg.getPassPhrase() != null && !Apg.getPassPhrase().equals("")) ||
(mNewPassPhrase != null && mNewPassPhrase.equals("")); (mNewPassPhrase != null && mNewPassPhrase.equals(""));
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, OPTION_MENU_NEW_PASS_PHRASE, 0, menu.add(0, Id.menu.option.new_pass_phrase, 0,
(havePassPhrase() ? "Change Pass Phrase" : "Set Pass Phrase")) (havePassPhrase() ? "Change Pass Phrase" : "Set Pass Phrase"))
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
return true; return true;
@ -191,8 +132,8 @@ public class EditKeyActivity extends Activity
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case OPTION_MENU_NEW_PASS_PHRASE: { case Id.menu.option.new_pass_phrase: {
showDialog(DIALOG_NEW_PASS_PHRASE); showDialog(Id.dialog.new_pass_phrase);
return true; return true;
} }
@ -206,15 +147,7 @@ public class EditKeyActivity extends Activity
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { switch (id) {
case DIALOG_SAVING: { case Id.dialog.new_pass_phrase: {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("saving...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case DIALOG_NEW_PASS_PHRASE: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
if (havePassPhrase()) { if (havePassPhrase()) {
@ -252,17 +185,17 @@ public class EditKeyActivity extends Activity
alert.setPositiveButton(android.R.string.ok, alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
removeDialog(DIALOG_NEW_PASS_PHRASE); removeDialog(Id.dialog.new_pass_phrase);
String passPhrase1 = "" + input1.getText(); String passPhrase1 = "" + input1.getText();
String passPhrase2 = "" + input2.getText(); String passPhrase2 = "" + input2.getText();
if (!passPhrase1.equals(passPhrase2)) { if (!passPhrase1.equals(passPhrase2)) {
showDialog(DIALOG_PASS_PHRASES_DO_NOT_MATCH); showDialog(Id.dialog.pass_phrases_do_not_match);
return; return;
} }
if (passPhrase1.equals("")) { if (passPhrase1.equals("")) {
showDialog(DIALOG_NO_PASS_PHRASE); showDialog(Id.dialog.no_pass_phrase);
return; return;
} }
@ -273,49 +206,13 @@ public class EditKeyActivity extends Activity
alert.setNegativeButton(android.R.string.cancel, alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
removeDialog(DIALOG_NEW_PASS_PHRASE); removeDialog(Id.dialog.new_pass_phrase);
} }
}); });
return alert.create(); return alert.create();
} }
case DIALOG_PASS_PHRASES_DO_NOT_MATCH: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle("Error");
alert.setMessage("The pass phrases didn't match.");
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(DIALOG_PASS_PHRASES_DO_NOT_MATCH);
}
});
alert.setCancelable(false);
return alert.create();
}
case DIALOG_NO_PASS_PHRASE: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle("Error");
alert.setMessage("Empty pass phrases are not supported.");
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(DIALOG_NO_PASS_PHRASE);
}
});
alert.setCancelable(false);
return alert.create();
}
default: { default: {
break; break;
} }
@ -334,16 +231,15 @@ public class EditKeyActivity extends Activity
} }
private void saveClicked() { private void saveClicked() {
if ((Apg.getPassPhrase() == null || Apg.getPassPhrase().equals("")) && if (!havePassPhrase()) {
(mNewPassPhrase == null || mNewPassPhrase.equals(""))) {
Toast.makeText(this, R.string.set_a_pass_phrase, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.set_a_pass_phrase, Toast.LENGTH_SHORT).show();
return; return;
} }
showDialog(DIALOG_SAVING); showDialog(Id.dialog.saving);
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
@Override
public void run() { public void run() {
String error = null; String error = null;
Bundle data = new Bundle(); Bundle data = new Bundle();
@ -368,34 +264,32 @@ public class EditKeyActivity extends Activity
error = e.getMessage(); error = e.getMessage();
} }
data.putInt("type", MESSAGE_DONE); data.putInt("type", Id.message.done);
if (error != null) { if (error != null) {
data.putString("error", error); data.putString("error", error);
} }
msg.setData(data); msg.setData(data);
mHandler.sendMessage(msg); sendMessage(msg);
} }
public void setProgress(int progress, int max) { @Override
Message msg = new Message(); public void doneCallback(Message msg) {
Bundle data = new Bundle(); super.doneCallback(msg);
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
public void setProgress(String message, int progress, int max) { Bundle data = msg.getData();
Message msg = new Message(); removeDialog(Id.dialog.saving);
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE); String error = data.getString("error");
data.putString("message", message); if (error != null) {
data.putInt("progress", progress); Toast.makeText(EditKeyActivity.this,
data.putInt("max", max); "Error: " + data.getString("error"),
msg.setData(data); Toast.LENGTH_SHORT).show();
mHandler.sendMessage(msg); } else {
Toast.makeText(EditKeyActivity.this, R.string.key_saved, Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
finish();
}
} }
} }

View File

@ -0,0 +1,304 @@
/*
* 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;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.util.Collections;
import java.util.Vector;
import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPPublicKeyRing;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.bouncycastle2.openpgp.PGPSecretKeyRing;
import org.openintents.intents.FileManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.TabHost.TabSpec;
public class EncryptFileActivity extends BaseActivity {
private EditText mFilename = null;
private ImageButton mBrowse = null;
private CheckBox mSign = null;
private TextView mMainUserId = null;
private TextView mMainUserIdRest = null;
private ListView mList;
private Button mEncryptButton = null;
private long mEncryptionKeyIds[] = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.encrypt_file);
TabHost tabHost = (TabHost) findViewById(R.id.tab_host);
tabHost.setup();
TabSpec ts1 = tabHost.newTabSpec("TAB_ASYMMETRIC");
ts1.setIndicator(getString(R.string.tab_asymmetric),
getResources().getDrawable(R.drawable.key));
ts1.setContent(R.id.tab_asymmetric);
tabHost.addTab(ts1);
TabSpec ts2 = tabHost.newTabSpec("TAB_SYMMETRIC");
ts2.setIndicator(getString(R.string.tab_symmetric),
getResources().getDrawable(R.drawable.encrypted));
ts2.setContent(R.id.tab_symmetric);
tabHost.addTab(ts2);
tabHost.setCurrentTab(0);
Vector<PGPPublicKeyRing> keyRings =
(Vector<PGPPublicKeyRing>) Apg.getPublicKeyRings().clone();
Collections.sort(keyRings, new Apg.PublicKeySorter());
mList = (ListView) findViewById(R.id.public_key_list);
mList.setAdapter(new SelectPublicKeyListAdapter(mList, keyRings));
mFilename = (EditText) findViewById(R.id.filename);
mBrowse = (ImageButton) findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openFile();
}
});
mEncryptButton = (Button) findViewById(R.id.btn_encrypt);
mSign = (CheckBox) findViewById(R.id.sign);
mMainUserId = (TextView) findViewById(R.id.main_user_id);
mMainUserIdRest = (TextView) findViewById(R.id.main_user_id_rest);
mSign.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CheckBox checkBox = (CheckBox) v;
if (checkBox.isChecked()) {
selectSecretKey();
} else {
setSecretKeyId(0);
Apg.setPassPhrase(null);
updateView();
}
}
});
mEncryptButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
encryptClicked();
}
});
updateView();
}
private void updateView() {
if (getSecretKeyId() == 0) {
mSign.setText(R.string.sign);
mSign.setChecked(false);
mMainUserId.setText("");
mMainUserIdRest.setText("");
} else {
String uid = getResources().getString(R.string.unknown_user_id);
String uidExtra = "";
PGPSecretKeyRing keyRing = Apg.getSecretKeyRing(getSecretKeyId());
if (keyRing != null) {
PGPSecretKey key = Apg.getMasterKey(keyRing);
if (key != null) {
String userId = Apg.getMainUserIdSafe(this, key);
String chunks[] = userId.split(" <", 2);
uid = chunks[0];
if (chunks.length > 1) {
uidExtra = "<" + chunks[1];
}
}
}
mMainUserId.setText(uid);
mMainUserIdRest.setText(uidExtra);
mSign.setText(R.string.sign_as);
mSign.setChecked(true);
}
}
private void openFile() {
String filename = mFilename.getText().toString();
Intent intent = new Intent(FileManager.ACTION_PICK_FILE);
intent.setData(Uri.parse("file://" + filename));
intent.putExtra(FileManager.EXTRA_TITLE, "Select file to encrypt...");
intent.putExtra(FileManager.EXTRA_BUTTON_TEXT, "Open");
try {
startActivityForResult(intent, Id.request.filename);
} catch (ActivityNotFoundException e) {
// No compatible file manager was found.
Toast.makeText(this, R.string.no_filemanager_installed, Toast.LENGTH_SHORT).show();
}
}
private void selectSecretKey() {
Intent intent = new Intent(this, SelectSecretKeyListActivity.class);
startActivityForResult(intent, Id.request.secret_keys);
}
private void encryptClicked() {
if (getSecretKeyId() != 0 && Apg.getPassPhrase() == null) {
showDialog(Id.dialog.pass_phrase);
} else {
encryptStart();
}
}
@Override
public void passPhraseCallback(String passPhrase) {
super.passPhraseCallback(passPhrase);
encryptStart();
}
private void encryptStart() {
showDialog(Id.dialog.encrypting);
startThread();
}
@Override
public void run() {
String error = null;
Bundle data = new Bundle();
Message msg = new Message();
try {
InputStream in = new FileInputStream(mFilename.getText().toString());
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) {
Apg.encrypt(in, out, true, mEncryptionKeyIds, getSecretKeyId(),
Apg.getPassPhrase(), this);
data.putString("message", new String(out.toByteArray()));
} else {
Apg.signText(in, out, getSecretKeyId(),
Apg.getPassPhrase(), HashAlgorithmTags.SHA256, this);
data.putString("message", new String(out.toByteArray()));
}
} catch (IOException e) {
error = e.getMessage();
} catch (PGPException e) {
error = e.getMessage();
} catch (NoSuchProviderException e) {
error = e.getMessage();
} catch (NoSuchAlgorithmException e) {
error = e.getMessage();
} catch (SignatureException e) {
error = e.getMessage();
} catch (Apg.GeneralException e) {
error = e.getMessage();
}
data.putInt("type", Id.message.done);
if (error != null) {
data.putString("error", error);
}
msg.setData(data);
sendMessage(msg);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString();
if (filename != null) {
// Get rid of URI prefix:
if (filename.startsWith("file://")) {
filename = filename.substring(7);
}
// replace %20 and so on
filename = Uri.decode(filename);
mFilename.setText(filename);
}
}
return;
}
case Id.request.secret_keys: {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
long newId = bundle.getLong("selectedKeyId");
if (getSecretKeyId() != newId) {
Apg.setPassPhrase(null);
}
setSecretKeyId(newId);
} else {
setSecretKeyId(0);
Apg.setPassPhrase(null);
}
updateView();
break;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
Bundle data = msg.getData();
removeDialog(Id.dialog.encrypting);
String error = data.getString("error");
if (error != null) {
Toast.makeText(EncryptFileActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(EncryptFileActivity.this,
"Successfully encrypted.",
Toast.LENGTH_SHORT).show();
}
}
}

View File

@ -32,12 +32,8 @@ import org.bouncycastle2.openpgp.PGPSecretKey;
import org.bouncycastle2.openpgp.PGPSecretKeyRing; import org.bouncycastle2.openpgp.PGPSecretKeyRing;
import org.bouncycastle2.util.Strings; import org.bouncycastle2.util.Strings;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -47,25 +43,11 @@ import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class EncryptMessageActivity extends Activity public class EncryptMessageActivity extends BaseActivity {
implements Runnable, ProgressDialogUpdater,
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
static final int GET_PUCLIC_KEYS = 1;
static final int GET_SECRET_KEY = 2;
static final int DIALOG_ENCRYPTING = 1;
static final int MESSAGE_PROGRESS_UPDATE = 1;
static final int MESSAGE_DONE = 2;
private String mSubject = null; private String mSubject = null;
private String mSendTo = null; private String mSendTo = null;
private long mEncryptionKeyIds[] = null; private long mEncryptionKeyIds[] = null;
private long mSignatureKeyId = 0;
private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null;
private EditText mMessage = null; private EditText mMessage = null;
private Button mSelectKeysButton = null; private Button mSelectKeysButton = null;
@ -74,92 +56,11 @@ public class EncryptMessageActivity extends Activity
private TextView mMainUserId = null; private TextView mMainUserId = null;
private TextView mMainUserIdRest = null; private TextView mMainUserIdRest = null;
private Handler mhandler = new Handler() {
@Override
public void handleMessage(Message mSg) {
Bundle data = mSg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case MESSAGE_PROGRESS_UPDATE: {
String message = data.getString("message");
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt("max"));
mProgressDialog.setProgress(data.getInt("progress"));
}
break;
}
case MESSAGE_DONE: {
removeDialog(DIALOG_ENCRYPTING);
mProgressDialog = null;
String error = data.getString("error");
if (error != null) {
Toast.makeText(EncryptMessageActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
return;
} else {
String message = data.getString("message");
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain; charset=utf-8");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
if (mSubject != null) {
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
mSubject);
}
if (mSendTo != null) {
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
new String[] { mSendTo });
}
EncryptMessageActivity.this.
startActivity(Intent.createChooser(emailIntent, "Send mail..."));
}
break;
}
default: {
break;
}
}
}
}
};
@Override
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mhandler.sendMessage(msg);
}
@Override
public void setProgress(String message, int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putString("message", message);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mhandler.sendMessage(msg);
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.encrypt_message); setContentView(R.layout.encrypt_message);
Apg.initialize(this);
mMessage = (EditText) findViewById(R.id.message); mMessage = (EditText) findViewById(R.id.message);
mSelectKeysButton = (Button) findViewById(R.id.btn_selectEncryptKeys); mSelectKeysButton = (Button) findViewById(R.id.btn_selectEncryptKeys);
mSendButton = (Button) findViewById(R.id.btn_send); mSendButton = (Button) findViewById(R.id.btn_send);
@ -183,7 +84,7 @@ public class EncryptMessageActivity extends Activity
if (masterKey != null) { if (masterKey != null) {
Vector<PGPSecretKey> signKeys = Apg.getUsableSigningKeys(keyRing); Vector<PGPSecretKey> signKeys = Apg.getUsableSigningKeys(keyRing);
if (signKeys.size() > 0) { if (signKeys.size() > 0) {
mSignatureKeyId = masterKey.getKeyID(); setSecretKeyId(masterKey.getKeyID());
} }
} }
} }
@ -240,7 +141,7 @@ public class EncryptMessageActivity extends Activity
if (checkBox.isChecked()) { if (checkBox.isChecked()) {
selectSecretKey(); selectSecretKey();
} else { } else {
mSignatureKeyId = 0; setSecretKeyId(0);
Apg.setPassPhrase(null); Apg.setPassPhrase(null);
updateView(); updateView();
} }
@ -250,69 +151,56 @@ public class EncryptMessageActivity extends Activity
updateView(); updateView();
} }
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_ENCRYPTING: {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("initializing...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE: {
return AskForSecretKeyPassPhrase.createDialog(this, mSignatureKeyId, this);
}
}
return super.onCreateDialog(id);
}
private void sendClicked() { private void sendClicked() {
if (mSignatureKeyId != 0 && Apg.getPassPhrase() == null) { if (getSecretKeyId() != 0 && Apg.getPassPhrase() == null) {
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE); showDialog(Id.dialog.pass_phrase);
} else { } else {
encryptStart(); encryptStart();
} }
} }
@Override
public void passPhraseCallback(String passPhrase) { public void passPhraseCallback(String passPhrase) {
Apg.setPassPhrase(passPhrase); super.passPhraseCallback(passPhrase);
encryptStart(); encryptStart();
} }
private void encryptStart() { private void encryptStart() {
showDialog(DIALOG_ENCRYPTING); showDialog(Id.dialog.encrypting);
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
@Override
public void run() { public void run() {
String error = null; String error = null;
Bundle data = new Bundle(); Bundle data = new Bundle();
Message msg = new Message(); Message msg = new Message();
String message = mMessage.getText().toString();
// fix the message a bit, trailing spaces and newlines break stuff,
// because GMail sends as HTML and such things fuck up the signature,
// TODO: things like "<" and ">" also fuck up the signature
message = message.replaceAll(" +\n", "\n");
message = message.replaceAll("\n\n+", "\n\n");
message = message.replaceFirst("^\n+", "");
// make sure there'll be exactly one newline at the end
message = message.replaceFirst("\n*$", "\n");
ByteArrayInputStream in =
new ByteArrayInputStream(Strings.toUTF8ByteArray(message));
ByteArrayOutputStream out = new ByteArrayOutputStream();
try { try {
if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) { boolean encryptIt = mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0;
Apg.encrypt(in, out, true, mEncryptionKeyIds, mSignatureKeyId,
String message = mMessage.getText().toString();
if (!encryptIt) {
// fix the message a bit, trailing spaces and newlines break stuff,
// because GMail sends as HTML and such things fuck up the signature,
// TODO: things like "<" and ">" also fuck up the signature
message = message.replaceAll(" +\n", "\n");
message = message.replaceAll("\n\n+", "\n\n");
message = message.replaceFirst("^\n+", "");
// make sure there'll be exactly one newline at the end
message = message.replaceFirst("\n*$", "\n");
}
ByteArrayInputStream in =
new ByteArrayInputStream(Strings.toUTF8ByteArray(message));
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (encryptIt) {
Apg.encrypt(in, out, true, mEncryptionKeyIds, getSecretKeyId(),
Apg.getPassPhrase(), this); Apg.getPassPhrase(), this);
data.putString("message", new String(out.toByteArray())); data.putString("message", new String(out.toByteArray()));
} else { } else {
Apg.signText(in, out, mSignatureKeyId, Apg.signText(in, out, getSecretKeyId(),
Apg.getPassPhrase(), HashAlgorithmTags.SHA256, this); Apg.getPassPhrase(), HashAlgorithmTags.SHA256, this);
data.putString("message", new String(out.toByteArray())); data.putString("message", new String(out.toByteArray()));
} }
@ -330,14 +218,14 @@ public class EncryptMessageActivity extends Activity
error = e.getMessage(); error = e.getMessage();
} }
data.putInt("type", MESSAGE_DONE); data.putInt("type", Id.message.done);
if (error != null) { if (error != null) {
data.putString("error", error); data.putString("error", error);
} }
msg.setData(data); msg.setData(data);
mhandler.sendMessage(msg); sendMessage(msg);
} }
private void updateView() { private void updateView() {
@ -350,7 +238,7 @@ public class EncryptMessageActivity extends Activity
getResources().getString(R.string.n_keys_selected)); getResources().getString(R.string.n_keys_selected));
} }
if (mSignatureKeyId == 0) { if (getSecretKeyId() == 0) {
mSign.setText(R.string.sign); mSign.setText(R.string.sign);
mSign.setChecked(false); mSign.setChecked(false);
mMainUserId.setText(""); mMainUserId.setText("");
@ -358,7 +246,7 @@ public class EncryptMessageActivity extends Activity
} else { } else {
String uid = getResources().getString(R.string.unknown_user_id); String uid = getResources().getString(R.string.unknown_user_id);
String uidExtra = ""; String uidExtra = "";
PGPSecretKeyRing keyRing = Apg.getSecretKeyRing(mSignatureKeyId); PGPSecretKeyRing keyRing = Apg.getSecretKeyRing(getSecretKeyId());
if (keyRing != null) { if (keyRing != null) {
PGPSecretKey key = Apg.getMasterKey(keyRing); PGPSecretKey key = Apg.getMasterKey(keyRing);
if (key != null) { if (key != null) {
@ -380,18 +268,18 @@ public class EncryptMessageActivity extends Activity
private void selectPublicKeys() { private void selectPublicKeys() {
Intent intent = new Intent(this, SelectPublicKeyListActivity.class); Intent intent = new Intent(this, SelectPublicKeyListActivity.class);
intent.putExtra("selection", mEncryptionKeyIds); intent.putExtra("selection", mEncryptionKeyIds);
startActivityForResult(intent, GET_PUCLIC_KEYS); startActivityForResult(intent, Id.request.public_keys);
} }
private void selectSecretKey() { private void selectSecretKey() {
Intent intent = new Intent(this, SelectSecretKeyListActivity.class); Intent intent = new Intent(this, SelectSecretKeyListActivity.class);
startActivityForResult(intent, GET_SECRET_KEY); startActivityForResult(intent, Id.request.secret_keys);
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case GET_PUCLIC_KEYS: { case Id.request.public_keys: {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras(); Bundle bundle = data.getExtras();
mEncryptionKeyIds = bundle.getLongArray("selection"); mEncryptionKeyIds = bundle.getLongArray("selection");
@ -400,26 +288,58 @@ public class EncryptMessageActivity extends Activity
break; break;
} }
case GET_SECRET_KEY: { case Id.request.secret_keys: {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras(); Bundle bundle = data.getExtras();
long newId = bundle.getLong("selectedKeyId"); long newId = bundle.getLong("selectedKeyId");
if (mSignatureKeyId != newId) { if (getSecretKeyId() != newId) {
Apg.setPassPhrase(null); Apg.setPassPhrase(null);
} }
mSignatureKeyId = newId; setSecretKeyId(newId);
} else { } else {
mSignatureKeyId = 0; setSecretKeyId(0);
Apg.setPassPhrase(null); Apg.setPassPhrase(null);
} }
updateView(); updateView();
break; break;
} }
default: default: {
break; break;
}
} }
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
removeDialog(Id.dialog.encrypting);
Bundle data = msg.getData();
String error = data.getString("error");
if (error != null) {
Toast.makeText(EncryptMessageActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
return;
} else {
String message = data.getString("message");
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain; charset=utf-8");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
if (mSubject != null) {
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
mSubject);
}
if (mSendTo != null) {
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
new String[] { mSendTo });
}
EncryptMessageActivity.this.
startActivity(Intent.createChooser(emailIntent, "Send mail..."));
}
}
} }

View File

@ -32,8 +32,7 @@ import android.widget.ImageButton;
import android.widget.Toast; import android.widget.Toast;
public class FileDialog { public class FileDialog {
public static final int REQUEST_CODE_PICK_FILE_OR_DIRECTORY = 12345; private static EditText mFilename;
private static EditText mInput;
private static ImageButton mBrowse; private static ImageButton mBrowse;
private static Activity mActivity; private static Activity mActivity;
private static String mFileManagerTitle; private static String mFileManagerTitle;
@ -57,8 +56,8 @@ public class FileDialog {
View view = (View) inflater.inflate(R.layout.file_dialog, null); View view = (View) inflater.inflate(R.layout.file_dialog, null);
mActivity = activity; mActivity = activity;
mInput = (EditText) view.findViewById(R.id.input); mFilename = (EditText) view.findViewById(R.id.input);
mInput.setText(defaultFile); mFilename.setText(defaultFile);
mBrowse = (ImageButton) view.findViewById(R.id.btn_browse); mBrowse = (ImageButton) view.findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() { mBrowse.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -75,7 +74,7 @@ public class FileDialog {
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
clickListener.onOkClick(mInput.getText().toString()); clickListener.onOkClick(mFilename.getText().toString());
} }
}); });
@ -89,8 +88,8 @@ public class FileDialog {
} }
public static void setFilename(String filename) { public static void setFilename(String filename) {
if (mInput != null) { if (mFilename != null) {
mInput.setText(filename); mFilename.setText(filename);
} }
} }
@ -98,17 +97,17 @@ public class FileDialog {
* Opens the file manager to select a file to open. * Opens the file manager to select a file to open.
*/ */
private static void openFile() { private static void openFile() {
String fileName = mInput.getText().toString(); String filename = mFilename.getText().toString();
Intent intent = new Intent(FileManager.ACTION_PICK_FILE); Intent intent = new Intent(FileManager.ACTION_PICK_FILE);
intent.setData(Uri.parse("file://" + fileName)); intent.setData(Uri.parse("file://" + filename));
intent.putExtra(FileManager.EXTRA_TITLE, mFileManagerTitle); intent.putExtra(FileManager.EXTRA_TITLE, mFileManagerTitle);
intent.putExtra(FileManager.EXTRA_BUTTON_TEXT, mFileManagerButton); intent.putExtra(FileManager.EXTRA_BUTTON_TEXT, mFileManagerButton);
try { try {
mActivity.startActivityForResult(intent, REQUEST_CODE_PICK_FILE_OR_DIRECTORY); mActivity.startActivityForResult(intent, Id.request.filename);
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
// No compatible file manager was found. // No compatible file manager was found.
Toast.makeText(mActivity, R.string.no_filemanager_installed, Toast.LENGTH_SHORT).show(); Toast.makeText(mActivity, R.string.no_filemanager_installed, Toast.LENGTH_SHORT).show();

View File

@ -0,0 +1,82 @@
/*
* 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;
public final class Id {
public static final class menu {
public static final int export = 0x21070001;
public static final int delete = 0x21070002;
public static final int edit = 0x21070003;
public static final class option {
public static final int new_pass_phrase = 0x21070001;
public static final int create = 0x21070002;
public static final int about = 0x21070003;
public static final int manage_public_keys = 0x21070004;
public static final int manage_secret_keys = 0x21070005;
public static final int import_keys = 0x21070006;
public static final int export_keys = 0x21070007;
}
}
public static final class message {
public static final int progress_update = 0x21070001;
public static final int done = 0x21070002;
public static final int import_keys = 0x21070003;
public static final int export_keys = 0x21070004;
public static final int import_done = 0x21070005;
public static final int export_done = 0x21070006;
public static final int create_key = 0x21070007;
public static final int edit_key = 0x21070008;
}
public static final class request {
public static final int public_keys = 0x21070001;
public static final int secret_keys = 0x21070002;
public static final int filename = 0x21070003;
}
public static final class dialog {
public static final int pass_phrase = 0x21070001;
public static final int encrypting = 0x21070002;
public static final int decrypting = 0x21070003;
public static final int new_pass_phrase = 0x21070004;
public static final int pass_phrases_do_not_match = 0x21070005;
public static final int no_pass_phrase = 0x21070006;
public static final int saving = 0x21070007;
public static final int delete_key = 0x21070008;
public static final int import_keys = 0x21070009;
public static final int importing = 0x2107000a;
public static final int export_key = 0x2107000b;
public static final int export_keys = 0x2107000c;
public static final int exporting = 0x2107000d;
public static final int new_account = 0x2107000e;
public static final int about = 0x2107000f;
public static final int change_log = 0x21070010;
}
public static final class task {
public static final int import_keys = 0x21070001;
public static final int export_keys = 0x21070002;
}
public static final class type {
public static final int public_key = 0x21070001;
public static final int secret_key = 0x21070002;
}
}

View File

@ -37,7 +37,7 @@ import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
public class MailListActivity extends ListActivity { public class MailListActivity extends ListActivity {
LayoutInflater minflater = null; LayoutInflater mInflater = null;
private static class Conversation { private static class Conversation {
public long id; public long id;
@ -82,7 +82,7 @@ public class MailListActivity extends ListActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
minflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mconversations = new Vector<Conversation>(); mconversations = new Vector<Conversation>();
mmessages = new Vector<Message>(); mmessages = new Vector<Message>();
@ -191,7 +191,7 @@ public class MailListActivity extends ListActivity {
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
View view = minflater.inflate(R.layout.mailbox_message_item, null); View view = mInflater.inflate(R.layout.mailbox_message_item, null);
Message message = (Message) getItem(position); Message message = (Message) getItem(position);

View File

@ -51,17 +51,7 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
public class MainActivity extends Activity { public class MainActivity extends BaseActivity {
private static final int DIALOG_NEW_ACCOUNT = 1;
private static final int DIALOG_ABOUT = 2;
private static final int DIALOG_CHANGE_LOG = 3;
private static final int OPTION_MENU_ADD_ACCOUNT = 1;
private static final int OPTION_MENU_ABOUT = 2;
private static final int OPTION_MENU_MANAGE_PUBLIC_KEYS = 3;
private static final int OPTION_MENU_MANAGE_SECRET_KEYS = 4;
private static final int MENU_DELETE_ACCOUNT = 1;
private static String PREF_SEEN_CHANGE_LOG = "seenChangeLogDialog" + Apg.VERSION; private static String PREF_SEEN_CHANGE_LOG = "seenChangeLogDialog" + Apg.VERSION;
@ -72,10 +62,10 @@ public class MainActivity extends Activity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.main); setContentView(R.layout.main);
Apg.initialize(this);
Button encryptMessageButton = (Button) findViewById(R.id.btn_encryptMessage); Button encryptMessageButton = (Button) findViewById(R.id.btn_encryptMessage);
Button decryptMessageButton = (Button) findViewById(R.id.btn_decryptMessage); Button decryptMessageButton = (Button) findViewById(R.id.btn_decryptMessage);
Button encryptFileButton = (Button) findViewById(R.id.btn_encryptFile);
Button decryptFileButton = (Button) findViewById(R.id.btn_decryptFile);
mAccounts = (ListView) findViewById(R.id.account_list); mAccounts = (ListView) findViewById(R.id.account_list);
encryptMessageButton.setOnClickListener(new OnClickListener() { encryptMessageButton.setOnClickListener(new OnClickListener() {
@ -92,6 +82,20 @@ public class MainActivity extends Activity {
} }
}); });
encryptFileButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startEncryptFileActivity();
}
});
decryptFileButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startDecryptFileActivity();
}
});
Cursor accountCursor = managedQuery(Accounts.CONTENT_URI, null, null, null, null); Cursor accountCursor = managedQuery(Accounts.CONTENT_URI, null, null, null, null);
mAccounts.setAdapter(new AccountListAdapter(this, accountCursor)); mAccounts.setAdapter(new AccountListAdapter(this, accountCursor));
@ -113,14 +117,14 @@ public class MainActivity extends Activity {
SharedPreferences prefs = getPreferences(MODE_PRIVATE); SharedPreferences prefs = getPreferences(MODE_PRIVATE);
if (!prefs.getBoolean(PREF_SEEN_CHANGE_LOG, false)) { if (!prefs.getBoolean(PREF_SEEN_CHANGE_LOG, false)) {
showDialog(DIALOG_CHANGE_LOG); showDialog(Id.dialog.change_log);
} }
} }
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { switch (id) {
case DIALOG_NEW_ACCOUNT: { case Id.dialog.new_account: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Add Account"); alert.setTitle("Add Account");
@ -132,7 +136,7 @@ public class MainActivity extends Activity {
alert.setPositiveButton(android.R.string.ok, alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
MainActivity.this.removeDialog(DIALOG_NEW_ACCOUNT); MainActivity.this.removeDialog(Id.dialog.new_account);
String accountName = "" + input.getText(); String accountName = "" + input.getText();
Cursor testCursor = Cursor testCursor =
@ -165,14 +169,14 @@ public class MainActivity extends Activity {
alert.setNegativeButton(android.R.string.cancel, alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
MainActivity.this.removeDialog(DIALOG_NEW_ACCOUNT); MainActivity.this.removeDialog(Id.dialog.new_account);
} }
}); });
return alert.create(); return alert.create();
} }
case DIALOG_ABOUT: { case Id.dialog.about: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("About " + Apg.FULL_VERSION); alert.setTitle("About " + Apg.FULL_VERSION);
@ -205,14 +209,14 @@ public class MainActivity extends Activity {
alert.setPositiveButton(android.R.string.ok, alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
MainActivity.this.removeDialog(DIALOG_ABOUT); MainActivity.this.removeDialog(Id.dialog.about);
} }
}); });
return alert.create(); return alert.create();
} }
case DIALOG_CHANGE_LOG: { case Id.dialog.change_log: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Changes " + Apg.FULL_VERSION); alert.setTitle("Changes " + Apg.FULL_VERSION);
@ -246,7 +250,7 @@ public class MainActivity extends Activity {
alert.setPositiveButton(android.R.string.ok, alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
MainActivity.this.removeDialog(DIALOG_CHANGE_LOG); MainActivity.this.removeDialog(Id.dialog.change_log);
SharedPreferences prefs = getPreferences(MODE_PRIVATE); SharedPreferences prefs = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PREF_SEEN_CHANGE_LOG, true); editor.putBoolean(PREF_SEEN_CHANGE_LOG, true);
@ -261,18 +265,19 @@ public class MainActivity extends Activity {
break; break;
} }
} }
return super.onCreateDialog(id); return super.onCreateDialog(id);
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, OPTION_MENU_MANAGE_PUBLIC_KEYS, 0, R.string.menu_managePublicKeys) menu.add(0, Id.menu.option.manage_public_keys, 0, R.string.menu_managePublicKeys)
.setIcon(android.R.drawable.ic_menu_manage); .setIcon(android.R.drawable.ic_menu_manage);
menu.add(0, OPTION_MENU_MANAGE_SECRET_KEYS, 1, R.string.menu_manageSecretKeys) menu.add(0, Id.menu.option.manage_secret_keys, 1, R.string.menu_manageSecretKeys)
.setIcon(android.R.drawable.ic_menu_manage); .setIcon(android.R.drawable.ic_menu_manage);
menu.add(1, OPTION_MENU_ADD_ACCOUNT, 2, R.string.menu_addAccount) menu.add(1, Id.menu.option.create, 2, R.string.menu_addAccount)
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
menu.add(1, OPTION_MENU_ABOUT, 3, R.string.menu_about) menu.add(1, Id.menu.option.about, 3, R.string.menu_about)
.setIcon(android.R.drawable.ic_menu_info_details); .setIcon(android.R.drawable.ic_menu_info_details);
return true; return true;
} }
@ -280,22 +285,22 @@ public class MainActivity extends Activity {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case OPTION_MENU_ADD_ACCOUNT: { case Id.menu.option.create: {
showDialog(DIALOG_NEW_ACCOUNT); showDialog(Id.dialog.new_account);
return true; return true;
} }
case OPTION_MENU_ABOUT: { case Id.menu.option.about: {
showDialog(DIALOG_ABOUT); showDialog(Id.dialog.about);
return true; return true;
} }
case OPTION_MENU_MANAGE_PUBLIC_KEYS: { case Id.menu.option.manage_public_keys: {
startPublicKeyManager(); startPublicKeyManager();
return true; return true;
} }
case OPTION_MENU_MANAGE_SECRET_KEYS: { case Id.menu.option.manage_secret_keys: {
startSecretKeyManager(); startSecretKeyManager();
return true; return true;
} }
@ -314,7 +319,7 @@ public class MainActivity extends Activity {
TextView nameTextView = (TextView) v.findViewById(R.id.account_name); TextView nameTextView = (TextView) v.findViewById(R.id.account_name);
if (nameTextView != null) { if (nameTextView != null) {
menu.setHeaderTitle(nameTextView.getText()); menu.setHeaderTitle(nameTextView.getText());
menu.add(0, MENU_DELETE_ACCOUNT, 0, "Delete Account"); menu.add(0, Id.menu.delete, 0, "Delete Account");
} }
} }
@ -324,7 +329,7 @@ public class MainActivity extends Activity {
(AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case MENU_DELETE_ACCOUNT: { case Id.menu.delete: {
Uri uri = Uri.withAppendedPath(Accounts.CONTENT_URI, "" + info.id); Uri uri = Uri.withAppendedPath(Accounts.CONTENT_URI, "" + info.id);
this.getContentResolver().delete(uri, null, null); this.getContentResolver().delete(uri, null, null);
return true; return true;
@ -342,7 +347,6 @@ public class MainActivity extends Activity {
public void startSecretKeyManager() { public void startSecretKeyManager() {
startActivity(new Intent(this, SecretKeyListActivity.class)); startActivity(new Intent(this, SecretKeyListActivity.class));
//startActivity(new Intent(this, EditKeyActivity.class));
} }
public void startEncryptMessageActivity() { public void startEncryptMessageActivity() {
@ -353,6 +357,14 @@ public class MainActivity extends Activity {
startActivity(new Intent(this, DecryptMessageActivity.class)); startActivity(new Intent(this, DecryptMessageActivity.class));
} }
public void startEncryptFileActivity() {
startActivity(new Intent(this, EncryptFileActivity.class));
}
public void startDecryptFileActivity() {
//startActivity(new Intent(this, DecryptFileActivity.class));
}
public void startMailListActivity(String account) { public void startMailListActivity(String account) {
startActivity(new Intent(this, MailListActivity.class).putExtra("account", account)); startActivity(new Intent(this, MailListActivity.class).putExtra("account", account));
} }

View File

@ -27,17 +27,13 @@ import org.thialfihar.android.apg.utils.IterableIterator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.ExpandableListActivity;
import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@ -52,155 +48,30 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
public class PublicKeyListActivity extends ExpandableListActivity public class PublicKeyListActivity extends BaseActivity {
implements Runnable, ProgressDialogUpdater { ExpandableListView mList;
static final int MENU_DELETE = 1;
static final int MENU_EXPORT = 2;
static final int OPTION_MENU_IMPORT_KEYS = 1;
static final int OPTION_MENU_EXPORT_KEYS = 2;
static final int MESSAGE_PROGRESS_UPDATE = 1;
static final int MESSAGE_IMPORT_DONE = 2;
static final int MESSAGE_EXPORT_DONE = 3;
static final int DIALOG_DELETE_KEY = 1;
static final int DIALOG_IMPORT_KEYS = 2;
static final int DIALOG_IMPORTING = 3;
static final int DIALOG_EXPORT_KEYS = 4;
static final int DIALOG_EXPORTING = 5;
static final int DIALOG_EXPORT_KEY = 6;
static final int TASK_IMPORT = 1;
static final int TASK_EXPORT = 2;
protected int mSelectedItem = -1; protected int mSelectedItem = -1;
protected int mTask = 0; protected int mTask = 0;
private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null;
private String mImportFilename = Environment.getExternalStorageDirectory() + "/pubring.gpg"; private String mImportFilename = Environment.getExternalStorageDirectory() + "/pubring.gpg";
private String mExportFilename = Environment.getExternalStorageDirectory() + "/pubexport.asc"; private String mExportFilename = Environment.getExternalStorageDirectory() + "/pubexport.asc";
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case MESSAGE_PROGRESS_UPDATE: {
String message = data.getString("message");
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt("max"));
mProgressDialog.setProgress(data.getInt("progress"));
}
break;
}
case MESSAGE_IMPORT_DONE: {
removeDialog(DIALOG_IMPORTING);
mProgressDialog = null;
String error = data.getString("error");
if (error != null) {
Toast.makeText(PublicKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int added = data.getInt("added");
int updated = data.getInt("updated");
String message;
if (added > 0 && updated > 0) {
message = "Succssfully added " + added + " keys and updated " +
updated + " keys.";
} else if (added > 0) {
message = "Succssfully added " + added + " keys.";
} else if (updated > 0) {
message = "Succssfully updated " + updated + " keys.";
} else {
message = "No keys added or updated.";
}
Toast.makeText(PublicKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
refreshList();
break;
}
case MESSAGE_EXPORT_DONE: {
removeDialog(DIALOG_EXPORTING);
mProgressDialog = null;
String error = data.getString("error");
if (error != null) {
Toast.makeText(PublicKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int exported = data.getInt("exported");
String message;
if (exported == 1) {
message = "Succssfully exported 1 key.";
} else if (exported > 0) {
message = "Succssfully exported " + exported + " keys.";
} else{
message = "No keys exported.";
}
Toast.makeText(PublicKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
break;
}
default: {
break;
}
}
}
}
};
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
public void setProgress(String message, int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putString("message", message);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.key_list);
Apg.initialize(this); mList = (ExpandableListView) findViewById(R.id.list);
mList.setAdapter(new PublicKeyListAdapter(this));
setListAdapter(new PublicKeyListAdapter(this)); registerForContextMenu(mList);
registerForContextMenu(getExpandableListView());
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, OPTION_MENU_IMPORT_KEYS, 0, "Import Keys") menu.add(0, Id.menu.option.import_keys, 0, "Import Keys")
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
menu.add(0, OPTION_MENU_EXPORT_KEYS, 1, "Export Keys") menu.add(0, Id.menu.option.export_keys, 1, "Export Keys")
.setIcon(android.R.drawable.ic_menu_save); .setIcon(android.R.drawable.ic_menu_save);
return true; return true;
} }
@ -208,13 +79,13 @@ public class PublicKeyListActivity extends ExpandableListActivity
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case OPTION_MENU_IMPORT_KEYS: { case Id.menu.option.import_keys: {
showDialog(DIALOG_IMPORT_KEYS); showDialog(Id.dialog.import_keys);
return true; return true;
} }
case OPTION_MENU_EXPORT_KEYS: { case Id.menu.option.export_keys: {
showDialog(DIALOG_EXPORT_KEYS); showDialog(Id.dialog.export_keys);
return true; return true;
} }
@ -237,8 +108,8 @@ public class PublicKeyListActivity extends ExpandableListActivity
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition); PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition);
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
menu.setHeaderTitle(userId); menu.setHeaderTitle(userId);
menu.add(0, MENU_EXPORT, 0, "Export Key"); menu.add(0, Id.menu.export, 0, "Export Key");
menu.add(0, MENU_DELETE, 1, "Delete Key"); menu.add(0, Id.menu.delete, 1, "Delete Key");
} }
} }
@ -253,15 +124,15 @@ public class PublicKeyListActivity extends ExpandableListActivity
} }
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case MENU_EXPORT: { case Id.menu.export: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(DIALOG_EXPORT_KEY); showDialog(Id.dialog.export_key);
return true; return true;
} }
case MENU_DELETE: { case Id.menu.delete: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(DIALOG_DELETE_KEY); showDialog(Id.dialog.delete_key);
return true; return true;
} }
@ -276,7 +147,7 @@ public class PublicKeyListActivity extends ExpandableListActivity
boolean singleKeyExport = false; boolean singleKeyExport = false;
switch (id) { switch (id) {
case DIALOG_DELETE_KEY: { case Id.dialog.delete_key: {
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(mSelectedItem); PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(mSelectedItem);
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
@ -289,20 +160,20 @@ public class PublicKeyListActivity extends ExpandableListActivity
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
deleteKey(mSelectedItem); deleteKey(mSelectedItem);
mSelectedItem = -1; mSelectedItem = -1;
removeDialog(DIALOG_DELETE_KEY); removeDialog(Id.dialog.delete_key);
} }
}); });
builder.setNegativeButton(android.R.string.cancel, builder.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
mSelectedItem = -1; mSelectedItem = -1;
removeDialog(DIALOG_DELETE_KEY); removeDialog(Id.dialog.delete_key);
} }
}); });
return builder.create(); return builder.create();
} }
case DIALOG_IMPORT_KEYS: { case Id.dialog.import_keys: {
return FileDialog.build(this, "Import Keys", return FileDialog.build(this, "Import Keys",
"Please specify which file to import from.", "Please specify which file to import from.",
mImportFilename, mImportFilename,
@ -310,33 +181,33 @@ public class PublicKeyListActivity extends ExpandableListActivity
@Override @Override
public void onOkClick(String filename) { public void onOkClick(String filename) {
removeDialog(DIALOG_IMPORT_KEYS); removeDialog(Id.dialog.import_keys);
mImportFilename = filename; mImportFilename = filename;
importKeys(); importKeys();
} }
@Override @Override
public void onCancelClick() { public void onCancelClick() {
removeDialog(DIALOG_IMPORT_KEYS); removeDialog(Id.dialog.import_keys);
} }
}, },
getString(R.string.filemanager_title_open), getString(R.string.filemanager_title_open),
getString(R.string.filemanager_btn_open)); getString(R.string.filemanager_btn_open));
} }
case DIALOG_EXPORT_KEY: { case Id.dialog.export_key: {
singleKeyExport = true; singleKeyExport = true;
// break intentionally omitted, to use the DIALOG_EXPORT_KEYS dialog // break intentionally omitted, to use the Id.dialog.export_keys dialog
} }
case DIALOG_EXPORT_KEYS: { case Id.dialog.export_keys: {
String title = "Export Key"; String title = "Export Key";
if (!singleKeyExport) { if (!singleKeyExport) {
// plural "Keys" // plural "Keys"
title += "s"; title += "s";
} }
final int thisDialogId = (singleKeyExport ? DIALOG_EXPORT_KEY : DIALOG_EXPORT_KEYS); final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys);
return FileDialog.build(this, title, return FileDialog.build(this, title,
"Please specify which file to export to.\n" + "Please specify which file to export to.\n" +
@ -360,54 +231,42 @@ public class PublicKeyListActivity extends ExpandableListActivity
getString(R.string.filemanager_btn_save)); getString(R.string.filemanager_btn_save));
} }
case DIALOG_IMPORTING: { default: {
mProgressDialog = new ProgressDialog(this); break;
mProgressDialog.setMessage("importing...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case DIALOG_EXPORTING: {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("exporting...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
} }
} }
return super.onCreateDialog(id); return super.onCreateDialog(id);
} }
public void importKeys() { public void importKeys() {
showDialog(DIALOG_IMPORTING); showDialog(Id.dialog.importing);
mTask = TASK_IMPORT; mTask = Id.task.import_keys;
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
public void exportKeys() { public void exportKeys() {
showDialog(DIALOG_EXPORTING); showDialog(Id.dialog.exporting);
mTask = TASK_EXPORT; mTask = Id.task.export_keys;
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
@Override
public void run() { public void run() {
String error = null; String error = null;
Bundle data = new Bundle(); Bundle data = new Bundle();
Message msg = new Message(); Message msg = new Message();
String filename = null; String filename = null;
if (mTask == TASK_IMPORT) { if (mTask == Id.task.import_keys) {
filename = mImportFilename; filename = mImportFilename;
} else { } else {
filename = mExportFilename; filename = mExportFilename;
} }
try { try {
if (mTask == TASK_IMPORT) { if (mTask == Id.task.import_keys) {
data = Apg.importKeyRings(this, Apg.TYPE_PUBLIC, filename, this); data = Apg.importKeyRings(this, Id.type.public_key, filename, this);
} else { } else {
Vector<Object> keys = new Vector<Object>(); Vector<Object> keys = new Vector<Object>();
if (mSelectedItem == -1) { if (mSelectedItem == -1) {
@ -429,10 +288,10 @@ public class PublicKeyListActivity extends ExpandableListActivity
error = e.getMessage(); error = e.getMessage();
} }
if (mTask == TASK_IMPORT) { if (mTask == Id.task.import_keys) {
data.putInt("type", MESSAGE_IMPORT_DONE); data.putInt("type", Id.message.import_done);
} else { } else {
data.putInt("type", MESSAGE_EXPORT_DONE); data.putInt("type", Id.message.export_done);
} }
if (error != null) { if (error != null) {
@ -440,7 +299,7 @@ public class PublicKeyListActivity extends ExpandableListActivity
} }
msg.setData(data); msg.setData(data);
mHandler.sendMessage(msg); sendMessage(msg);
} }
private void deleteKey(int index) { private void deleteKey(int index) {
@ -450,7 +309,75 @@ public class PublicKeyListActivity extends ExpandableListActivity
} }
private void refreshList() { private void refreshList() {
((PublicKeyListAdapter) getExpandableListAdapter()).notifyDataSetChanged(); ((PublicKeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged();
}
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
Bundle data = msg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case Id.message.import_done: {
removeDialog(Id.dialog.importing);
String error = data.getString("error");
if (error != null) {
Toast.makeText(PublicKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int added = data.getInt("added");
int updated = data.getInt("updated");
String message;
if (added > 0 && updated > 0) {
message = "Succssfully added " + added + " keys and updated " +
updated + " keys.";
} else if (added > 0) {
message = "Succssfully added " + added + " keys.";
} else if (updated > 0) {
message = "Succssfully updated " + updated + " keys.";
} else {
message = "No keys added or updated.";
}
Toast.makeText(PublicKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
refreshList();
break;
}
case Id.message.export_done: {
removeDialog(Id.dialog.exporting);
String error = data.getString("error");
if (error != null) {
Toast.makeText(PublicKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int exported = data.getInt("exported");
String message;
if (exported == 1) {
message = "Succssfully exported 1 key.";
} else if (exported > 0) {
message = "Succssfully exported " + exported + " keys.";
} else{
message = "No keys exported.";
}
Toast.makeText(PublicKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
break;
}
default: {
break;
}
}
}
} }
private static class PublicKeyListAdapter extends BaseExpandableListAdapter { private static class PublicKeyListAdapter extends BaseExpandableListAdapter {
@ -633,7 +560,7 @@ public class PublicKeyListActivity extends ExpandableListActivity
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case FileDialog.REQUEST_CODE_PICK_FILE_OR_DIRECTORY: { case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString(); String filename = data.getDataString();
if (filename != null) { if (filename != null) {

View File

@ -27,15 +27,12 @@ import org.thialfihar.android.apg.utils.IterableIterator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.ExpandableListActivity;
import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -52,165 +49,33 @@ import android.widget.Toast;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ExpandableListView.OnChildClickListener;
public class SecretKeyListActivity extends ExpandableListActivity public class SecretKeyListActivity extends BaseActivity implements OnChildClickListener {
implements Runnable, ProgressDialogUpdater, OnChildClickListener, ExpandableListView mList;
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
static final int CREATE_SECRET_KEY = 1;
static final int EDIT_SECRET_KEY = 2;
static final int MENU_EDIT = 1;
static final int MENU_EXPORT = 2;
static final int MENU_DELETE = 3;
static final int OPTION_MENU_IMPORT_KEYS = 1;
static final int OPTION_MENU_EXPORT_KEYS = 2;
static final int OPTION_MENU_CREATE_KEY = 3;
static final int MESSAGE_PROGRESS_UPDATE = 1;
static final int MESSAGE_DONE = 2;
static final int MESSAGE_IMPORT_DONE = 2;
static final int MESSAGE_EXPORT_DONE = 3;
static final int DIALOG_DELETE_KEY = 1;
static final int DIALOG_IMPORT_KEYS = 2;
static final int DIALOG_IMPORTING = 3;
static final int DIALOG_EXPORT_KEYS = 4;
static final int DIALOG_EXPORTING = 5;
static final int DIALOG_EXPORT_KEY = 6;
static final int TASK_IMPORT = 1;
static final int TASK_EXPORT = 2;
protected int mSelectedItem = -1; protected int mSelectedItem = -1;
protected int mTask = 0; protected int mTask = 0;
private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null;
private String mImportFilename = Environment.getExternalStorageDirectory() + "/secring.gpg"; private String mImportFilename = Environment.getExternalStorageDirectory() + "/secring.gpg";
private String mExportFilename = Environment.getExternalStorageDirectory() + "/secexport.asc"; private String mExportFilename = Environment.getExternalStorageDirectory() + "/secexport.asc";
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case MESSAGE_PROGRESS_UPDATE: {
String message = data.getString("message");
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt("max"));
mProgressDialog.setProgress(data.getInt("progress"));
}
break;
}
case MESSAGE_IMPORT_DONE: {
removeDialog(DIALOG_IMPORTING);
mProgressDialog = null;
String error = data.getString("error");
if (error != null) {
Toast.makeText(SecretKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int added = data.getInt("added");
int updated = data.getInt("updated");
String message;
if (added > 0 && updated > 0) {
message = "Succssfully added " + added + " keys and updated " +
updated + " keys.";
} else if (added > 0) {
message = "Succssfully added " + added + " keys.";
} else if (updated > 0) {
message = "Succssfully updated " + updated + " keys.";
} else {
message = "No keys added or updated.";
}
Toast.makeText(SecretKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
refreshList();
break;
}
case MESSAGE_EXPORT_DONE: {
removeDialog(DIALOG_EXPORTING);
mProgressDialog = null;
String error = data.getString("error");
if (error != null) {
Toast.makeText(SecretKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int exported = data.getInt("exported");
String message;
if (exported == 1) {
message = "Succssfully exported 1 key.";
} else if (exported > 0) {
message = "Succssfully exported " + exported + " keys.";
} else{
message = "No keys exported.";
}
Toast.makeText(SecretKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
break;
}
default: {
break;
}
}
}
}
};
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
public void setProgress(String message, int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt("type", MESSAGE_PROGRESS_UPDATE);
data.putString("message", message);
data.putInt("progress", progress);
data.putInt("max", max);
msg.setData(data);
mHandler.sendMessage(msg);
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.key_list);
Apg.initialize(this); mList = (ExpandableListView) findViewById(R.id.list);
mList.setAdapter(new SecretKeyListAdapter(this));
setListAdapter(new SecretKeyListAdapter(this)); registerForContextMenu(mList);
registerForContextMenu(getExpandableListView()); mList.setOnChildClickListener(this);
getExpandableListView().setOnChildClickListener(this);
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, OPTION_MENU_IMPORT_KEYS, 0, "Import Keys") menu.add(0, Id.menu.option.import_keys, 0, "Import Keys")
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
menu.add(0, OPTION_MENU_EXPORT_KEYS, 1, "Export Keys") menu.add(0, Id.menu.option.export_keys, 1, "Export Keys")
.setIcon(android.R.drawable.ic_menu_save); .setIcon(android.R.drawable.ic_menu_save);
menu.add(1, OPTION_MENU_CREATE_KEY, 2, "Create Key") menu.add(1, Id.menu.option.create, 2, "Create Key")
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
return true; return true;
} }
@ -218,17 +83,17 @@ public class SecretKeyListActivity extends ExpandableListActivity
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case OPTION_MENU_IMPORT_KEYS: { case Id.menu.option.import_keys: {
showDialog(DIALOG_IMPORT_KEYS); showDialog(Id.dialog.import_keys);
return true; return true;
} }
case OPTION_MENU_EXPORT_KEYS: { case Id.menu.option.export_keys: {
showDialog(DIALOG_EXPORT_KEYS); showDialog(Id.dialog.export_keys);
return true; return true;
} }
case OPTION_MENU_CREATE_KEY: { case Id.menu.option.create: {
createKey(); createKey();
return true; return true;
} }
@ -241,8 +106,7 @@ public class SecretKeyListActivity extends ExpandableListActivity
} }
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
ExpandableListView.ExpandableListContextMenuInfo info = ExpandableListView.ExpandableListContextMenuInfo info =
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo; (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
@ -253,9 +117,9 @@ public class SecretKeyListActivity extends ExpandableListActivity
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition); PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition);
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
menu.setHeaderTitle(userId); menu.setHeaderTitle(userId);
menu.add(0, MENU_EDIT, 0, "Edit Key"); menu.add(0, Id.menu.edit, 0, "Edit Key");
menu.add(0, MENU_EXPORT, 1, "Export Key"); menu.add(0, Id.menu.export, 1, "Export Key");
menu.add(0, MENU_DELETE, 2, "Delete Key"); menu.add(0, Id.menu.delete, 2, "Delete Key");
} }
} }
@ -270,21 +134,21 @@ public class SecretKeyListActivity extends ExpandableListActivity
} }
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case MENU_EDIT: { case Id.menu.edit: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE); showDialog(Id.dialog.pass_phrase);
return true; return true;
} }
case MENU_EXPORT: { case Id.menu.export: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(DIALOG_EXPORT_KEY); showDialog(Id.dialog.export_key);
return true; return true;
} }
case MENU_DELETE: { case Id.menu.delete: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(DIALOG_DELETE_KEY); showDialog(Id.dialog.delete_key);
return true; return true;
} }
@ -298,7 +162,7 @@ public class SecretKeyListActivity extends ExpandableListActivity
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) { int childPosition, long id) {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE); showDialog(Id.dialog.pass_phrase);
return true; return true;
} }
@ -307,7 +171,7 @@ public class SecretKeyListActivity extends ExpandableListActivity
boolean singleKeyExport = false; boolean singleKeyExport = false;
switch (id) { switch (id) {
case DIALOG_DELETE_KEY: { case Id.dialog.delete_key: {
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem); PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
@ -321,20 +185,20 @@ public class SecretKeyListActivity extends ExpandableListActivity
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
deleteKey(mSelectedItem); deleteKey(mSelectedItem);
mSelectedItem = -1; mSelectedItem = -1;
removeDialog(DIALOG_DELETE_KEY); removeDialog(Id.dialog.delete_key);
} }
}); });
builder.setNegativeButton(android.R.string.ok, builder.setNegativeButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
mSelectedItem = -1; mSelectedItem = -1;
removeDialog(DIALOG_DELETE_KEY); removeDialog(Id.dialog.delete_key);
} }
}); });
return builder.create(); return builder.create();
} }
case DIALOG_IMPORT_KEYS: { case Id.dialog.import_keys: {
return FileDialog.build(this, "Import Keys", return FileDialog.build(this, "Import Keys",
"Please specify which file to import from.", "Please specify which file to import from.",
mImportFilename, mImportFilename,
@ -342,33 +206,33 @@ public class SecretKeyListActivity extends ExpandableListActivity
@Override @Override
public void onOkClick(String filename) { public void onOkClick(String filename) {
removeDialog(DIALOG_IMPORT_KEYS); removeDialog(Id.dialog.import_keys);
mImportFilename = filename; mImportFilename = filename;
importKeys(); importKeys();
} }
@Override @Override
public void onCancelClick() { public void onCancelClick() {
removeDialog(DIALOG_IMPORT_KEYS); removeDialog(Id.dialog.import_keys);
} }
}, },
getString(R.string.filemanager_title_open), getString(R.string.filemanager_title_open),
getString(R.string.filemanager_btn_open)); getString(R.string.filemanager_btn_open));
} }
case DIALOG_EXPORT_KEY: { case Id.dialog.export_key: {
singleKeyExport = true; singleKeyExport = true;
// break intentionally omitted, to use the DIALOG_EXPORT_KEYS dialog // break intentionally omitted, to use the Id.dialog.export_keys dialog
} }
case DIALOG_EXPORT_KEYS: { case Id.dialog.export_keys: {
String title = "Export Key"; String title = "Export Key";
if (!singleKeyExport) { if (!singleKeyExport) {
// plural "Keys" // plural "Keys"
title += "s"; title += "s";
} }
final int thisDialogId = (singleKeyExport ? DIALOG_DELETE_KEY : DIALOG_EXPORT_KEYS); final int thisDialogId = (singleKeyExport ? Id.dialog.delete_key : Id.dialog.export_keys);
return FileDialog.build(this, title, return FileDialog.build(this, title,
"Please specify which file to export to.\n" + "Please specify which file to export to.\n" +
@ -393,23 +257,7 @@ public class SecretKeyListActivity extends ExpandableListActivity
getString(R.string.filemanager_btn_save)); getString(R.string.filemanager_btn_save));
} }
case DIALOG_IMPORTING: { case Id.dialog.pass_phrase: {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("importing...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case DIALOG_EXPORTING: {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("exporting...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE: {
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem); PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
long keyId = keyRing.getSecretKey().getKeyID(); long keyId = keyRing.getSecretKey().getKeyID();
return AskForSecretKeyPassPhrase.createDialog(this, keyId, this); return AskForSecretKeyPassPhrase.createDialog(this, keyId, this);
@ -418,14 +266,15 @@ public class SecretKeyListActivity extends ExpandableListActivity
return super.onCreateDialog(id); return super.onCreateDialog(id);
} }
@Override
public void passPhraseCallback(String passPhrase) { public void passPhraseCallback(String passPhrase) {
Apg.setPassPhrase(passPhrase); super.passPhraseCallback(passPhrase);
editKey(); editKey();
} }
private void createKey() { private void createKey() {
Intent intent = new Intent(this, EditKeyActivity.class); Intent intent = new Intent(this, EditKeyActivity.class);
startActivityForResult(intent, CREATE_SECRET_KEY); startActivityForResult(intent, Id.message.create_key);
} }
private void editKey() { private void editKey() {
@ -433,21 +282,21 @@ public class SecretKeyListActivity extends ExpandableListActivity
long keyId = keyRing.getSecretKey().getKeyID(); long keyId = keyRing.getSecretKey().getKeyID();
Intent intent = new Intent(this, EditKeyActivity.class); Intent intent = new Intent(this, EditKeyActivity.class);
intent.putExtra("keyId", keyId); intent.putExtra("keyId", keyId);
startActivityForResult(intent, EDIT_SECRET_KEY); startActivityForResult(intent, Id.message.edit_key);
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case CREATE_SECRET_KEY: // intentionally no break case Id.message.create_key: // intentionally no break
case EDIT_SECRET_KEY: { case Id.message.edit_key: {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
refreshList(); refreshList();
} }
break; break;
} }
case FileDialog.REQUEST_CODE_PICK_FILE_OR_DIRECTORY: { case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString(); String filename = data.getDataString();
if (filename != null) { if (filename != null) {
@ -465,42 +314,42 @@ public class SecretKeyListActivity extends ExpandableListActivity
return; return;
} }
default: default: {
break; break;
}
} }
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
public void importKeys() { public void importKeys() {
showDialog(DIALOG_IMPORTING); showDialog(Id.dialog.importing);
mTask = TASK_IMPORT; mTask = Id.task.import_keys;
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
public void exportKeys() { public void exportKeys() {
showDialog(DIALOG_EXPORTING); showDialog(Id.dialog.exporting);
mTask = TASK_EXPORT; mTask = Id.task.export_keys;
mRunningThread = new Thread(this); startThread();
mRunningThread.start();
} }
@Override
public void run() { public void run() {
String error = null; String error = null;
Bundle data = new Bundle(); Bundle data = new Bundle();
Message msg = new Message(); Message msg = new Message();
String filename = null; String filename = null;
if (mTask == TASK_IMPORT) { if (mTask == Id.task.import_keys) {
filename = mImportFilename; filename = mImportFilename;
} else { } else {
filename = mExportFilename; filename = mExportFilename;
} }
try { try {
if (mTask == TASK_IMPORT) { if (mTask == Id.task.import_keys) {
data = Apg.importKeyRings(this, Apg.TYPE_SECRET, filename, this); data = Apg.importKeyRings(this, Id.type.secret_key, filename, this);
} else { } else {
Vector<Object> keys = new Vector<Object>(); Vector<Object> keys = new Vector<Object>();
if (mSelectedItem == -1) { if (mSelectedItem == -1) {
@ -522,10 +371,10 @@ public class SecretKeyListActivity extends ExpandableListActivity
error = e.getMessage(); error = e.getMessage();
} }
if (mTask == TASK_IMPORT) { if (mTask == Id.task.import_keys) {
data.putInt("type", MESSAGE_IMPORT_DONE); data.putInt("type", Id.message.import_done);
} else { } else {
data.putInt("type", MESSAGE_EXPORT_DONE); data.putInt("type", Id.message.export_done);
} }
if (error != null) { if (error != null) {
@ -533,7 +382,7 @@ public class SecretKeyListActivity extends ExpandableListActivity
} }
msg.setData(data); msg.setData(data);
mHandler.sendMessage(msg); sendMessage(msg);
} }
private void deleteKey(int index) { private void deleteKey(int index) {
@ -543,8 +392,75 @@ public class SecretKeyListActivity extends ExpandableListActivity
} }
private void refreshList() { private void refreshList() {
((SecretKeyListAdapter) getExpandableListAdapter()) ((SecretKeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged();
.notifyDataSetChanged(); }
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
Bundle data = msg.getData();
if (data != null) {
int type = data.getInt("type");
switch (type) {
case Id.message.import_done: {
removeDialog(Id.dialog.importing);
String error = data.getString("error");
if (error != null) {
Toast.makeText(SecretKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int added = data.getInt("added");
int updated = data.getInt("updated");
String message;
if (added > 0 && updated > 0) {
message = "Succssfully added " + added + " keys and updated " +
updated + " keys.";
} else if (added > 0) {
message = "Succssfully added " + added + " keys.";
} else if (updated > 0) {
message = "Succssfully updated " + updated + " keys.";
} else {
message = "No keys added or updated.";
}
Toast.makeText(SecretKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
refreshList();
break;
}
case Id.message.export_done: {
removeDialog(Id.dialog.exporting);
String error = data.getString("error");
if (error != null) {
Toast.makeText(SecretKeyListActivity.this,
"Error: " + data.getString("error"),
Toast.LENGTH_SHORT).show();
} else {
int exported = data.getInt("exported");
String message;
if (exported == 1) {
message = "Succssfully exported 1 key.";
} else if (exported > 0) {
message = "Succssfully exported " + exported + " keys.";
} else{
message = "No keys exported.";
}
Toast.makeText(SecretKeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
}
break;
}
default: {
break;
}
}
}
} }
private static class SecretKeyListAdapter extends BaseExpandableListAdapter { private static class SecretKeyListAdapter extends BaseExpandableListAdapter {

View File

@ -16,40 +16,28 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.text.DateFormat;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.Vector; import java.util.Vector;
import org.bouncycastle2.openpgp.PGPPublicKey; import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPPublicKeyRing; import org.bouncycastle2.openpgp.PGPPublicKeyRing;
import org.thialfihar.android.apg.utils.IterableIterator;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView;
public class SelectPublicKeyListActivity extends Activity { public class SelectPublicKeyListActivity extends BaseActivity {
protected Vector<PGPPublicKeyRing> mKeyRings;
protected LayoutInflater mInflater;
protected Intent mIntent; protected Intent mIntent;
protected ListView mList; protected ListView mList;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.select_public_key);
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// fill things // fill things
mIntent = getIntent(); mIntent = getIntent();
@ -58,17 +46,15 @@ public class SelectPublicKeyListActivity extends Activity {
selectedKeyIds = mIntent.getExtras().getLongArray("selection"); selectedKeyIds = mIntent.getExtras().getLongArray("selection");
} }
Apg.initialize(this);
mKeyRings = (Vector<PGPPublicKeyRing>) Apg.getPublicKeyRings().clone();
Collections.sort(mKeyRings, new Apg.PublicKeySorter());
setContentView(R.layout.select_public_key);
mList = (ListView) findViewById(R.id.list); mList = (ListView) findViewById(R.id.list);
mList.setAdapter(new PublicKeyListAdapter(this)); Vector<PGPPublicKeyRing> keyRings =
(Vector<PGPPublicKeyRing>) Apg.getPublicKeyRings().clone();
Collections.sort(keyRings, new Apg.PublicKeySorter());
mList.setAdapter(new SelectPublicKeyListAdapter(mList, keyRings));
if (selectedKeyIds != null) { if (selectedKeyIds != null) {
for (int i = 0; i < mKeyRings.size(); ++i) { for (int i = 0; i < keyRings.size(); ++i) {
PGPPublicKeyRing keyRing = mKeyRings.get(i); PGPPublicKeyRing keyRing = keyRings.get(i);
PGPPublicKey key = Apg.getMasterKey(keyRing); PGPPublicKey key = Apg.getMasterKey(keyRing);
if (key == null) { if (key == null) {
continue; continue;
@ -122,138 +108,4 @@ public class SelectPublicKeyListActivity extends Activity {
setResult(RESULT_OK, data); setResult(RESULT_OK, data);
finish(); finish();
} }
private class PublicKeyListAdapter extends BaseAdapter {
public PublicKeyListAdapter(Context context) {
}
@Override
public boolean isEnabled(int position) {
PGPPublicKeyRing keyRing = mKeyRings.get(position);
if (Apg.getMasterKey(keyRing) == null) {
return false;
}
Vector<PGPPublicKey> encryptKeys = Apg.getUsableEncryptKeys(keyRing);
if (encryptKeys.size() == 0) {
return false;
}
return true;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public int getCount() {
return mKeyRings.size();
}
@Override
public Object getItem(int position) {
return mKeyRings.get(position);
}
@Override
public long getItemId(int position) {
PGPPublicKeyRing keyRing = mKeyRings.get(position);
PGPPublicKey key = Apg.getMasterKey(keyRing);
if (key != null) {
return key.getKeyID();
}
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = mInflater.inflate(R.layout.select_public_key_item, null);
boolean enabled = isEnabled(position);
PGPPublicKeyRing keyRing = mKeyRings.get(position);
PGPPublicKey key = null;
for (PGPPublicKey tKey : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
if (tKey.isMasterKey()) {
key = tKey;
break;
}
}
Vector<PGPPublicKey> encryptKeys = Apg.getEncryptKeys(keyRing);
Vector<PGPPublicKey> usableKeys = Apg.getUsableEncryptKeys(keyRing);
TextView mainUserId = (TextView) view.findViewById(R.id.main_user_id);
mainUserId.setText(R.string.unknown_user_id);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.main_user_id_rest);
mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.key_id);
keyId.setText("<no key>");
TextView creation = (TextView) view.findViewById(R.id.creation);
creation.setText("-");
TextView expiry = (TextView) view.findViewById(R.id.expiry);
expiry.setText("no expire");
TextView status = (TextView) view.findViewById(R.id.status);
status.setText("???");
if (key != null) {
String userId = Apg.getMainUserId(key);
if (userId != null) {
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]);
}
mainUserId.setText(userId);
}
keyId.setText("" + Long.toHexString(key.getKeyID() & 0xffffffffL));
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
PGPPublicKey timespanKey = key;
if (usableKeys.size() > 0) {
timespanKey = usableKeys.get(0);
status.setText("can encrypt");
} else if (encryptKeys.size() > 0) {
timespanKey = encryptKeys.get(0);
Date now = new Date();
if (now.compareTo(Apg.getCreationDate(timespanKey)) > 0) {
status.setText("not valid");
} else {
status.setText("expired");
}
} else {
status.setText("no key");
}
creation.setText(DateFormat.getDateInstance().format(Apg.getCreationDate(timespanKey)));
Date expiryDate = Apg.getExpiryDate(timespanKey);
if (expiryDate != null) {
expiry.setText(DateFormat.getDateInstance().format(expiryDate));
}
status.setText(status.getText() + " ");
CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
selected.setChecked(mList.isItemChecked(position));
view.setEnabled(enabled);
mainUserId.setEnabled(enabled);
mainUserIdRest.setEnabled(enabled);
keyId.setEnabled(enabled);
creation.setEnabled(enabled);
expiry.setEnabled(enabled);
selected.setEnabled(enabled);
status.setEnabled(enabled);
return view;
}
}
} }

View File

@ -0,0 +1,186 @@
/*
* 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;
import java.text.DateFormat;
import java.util.Date;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPPublicKeyRing;
import org.thialfihar.android.apg.utils.IterableIterator;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
public class SelectPublicKeyListAdapter extends BaseAdapter {
protected Vector<PGPPublicKeyRing> mKeyRings;
protected LayoutInflater mInflater;
protected ListView mParent;
public SelectPublicKeyListAdapter(ListView parent,
Vector<PGPPublicKeyRing> keyRings) {
setKeyRings(keyRings);
mParent = parent;
mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setKeyRings(Vector<PGPPublicKeyRing> keyRings) {
mKeyRings = keyRings;
notifyDataSetChanged();
}
public Vector<PGPPublicKeyRing> getKeyRings() {
return mKeyRings;
}
@Override
public boolean isEnabled(int position) {
PGPPublicKeyRing keyRing = mKeyRings.get(position);
if (Apg.getMasterKey(keyRing) == null) {
return false;
}
Vector<PGPPublicKey> encryptKeys = Apg.getUsableEncryptKeys(keyRing);
if (encryptKeys.size() == 0) {
return false;
}
return true;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public int getCount() {
return mKeyRings.size();
}
@Override
public Object getItem(int position) {
return mKeyRings.get(position);
}
@Override
public long getItemId(int position) {
PGPPublicKeyRing keyRing = mKeyRings.get(position);
PGPPublicKey key = Apg.getMasterKey(keyRing);
if (key != null) {
return key.getKeyID();
}
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = mInflater.inflate(R.layout.select_public_key_item, null);
boolean enabled = isEnabled(position);
PGPPublicKeyRing keyRing = mKeyRings.get(position);
PGPPublicKey key = null;
for (PGPPublicKey tKey : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
if (tKey.isMasterKey()) {
key = tKey;
break;
}
}
Vector<PGPPublicKey> encryptKeys = Apg.getEncryptKeys(keyRing);
Vector<PGPPublicKey> usableKeys = Apg.getUsableEncryptKeys(keyRing);
TextView mainUserId = (TextView) view.findViewById(R.id.main_user_id);
mainUserId.setText(R.string.unknown_user_id);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.main_user_id_rest);
mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.key_id);
keyId.setText("<no key>");
TextView creation = (TextView) view.findViewById(R.id.creation);
creation.setText("-");
TextView expiry = (TextView) view.findViewById(R.id.expiry);
expiry.setText("no expire");
TextView status = (TextView) view.findViewById(R.id.status);
status.setText("???");
if (key != null) {
String userId = Apg.getMainUserId(key);
if (userId != null) {
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]);
}
mainUserId.setText(userId);
}
keyId.setText("" + Long.toHexString(key.getKeyID() & 0xffffffffL));
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
PGPPublicKey timespanKey = key;
if (usableKeys.size() > 0) {
timespanKey = usableKeys.get(0);
status.setText("can encrypt");
} else if (encryptKeys.size() > 0) {
timespanKey = encryptKeys.get(0);
Date now = new Date();
if (now.compareTo(Apg.getCreationDate(timespanKey)) > 0) {
status.setText("not valid");
} else {
status.setText("expired");
}
} else {
status.setText("no key");
}
creation.setText(DateFormat.getDateInstance().format(Apg.getCreationDate(timespanKey)));
Date expiryDate = Apg.getExpiryDate(timespanKey);
if (expiryDate != null) {
expiry.setText(DateFormat.getDateInstance().format(expiryDate));
}
status.setText(status.getText() + " ");
CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
selected.setChecked(mParent.isItemChecked(position));
view.setEnabled(enabled);
mainUserId.setEnabled(enabled);
mainUserIdRest.setEnabled(enabled);
keyId.setEnabled(enabled);
creation.setEnabled(enabled);
expiry.setEnabled(enabled);
selected.setEnabled(enabled);
status.setEnabled(enabled);
return view;
}
}

View File

@ -38,7 +38,7 @@ import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
public class SelectSecretKeyListActivity extends Activity { public class SelectSecretKeyListActivity extends BaseActivity {
protected Vector<PGPSecretKeyRing> mKeyRings; protected Vector<PGPSecretKeyRing> mKeyRings;
protected LayoutInflater mInflater; protected LayoutInflater mInflater;
protected Intent mIntent; protected Intent mIntent;
@ -55,8 +55,6 @@ public class SelectSecretKeyListActivity extends Activity {
// fill things // fill things
mIntent = getIntent(); mIntent = getIntent();
Apg.initialize(this);
mKeyRings = (Vector<PGPSecretKeyRing>) Apg.getSecretKeyRings().clone(); mKeyRings = (Vector<PGPSecretKeyRing>) Apg.getSecretKeyRings().clone();
Collections.sort(mKeyRings, new Apg.SecretKeySorter()); Collections.sort(mKeyRings, new Apg.SecretKeySorter());