mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
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:
parent
09741b0286
commit
d5c5a2c43b
8
.classpath
Normal file
8
.classpath
Normal 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
33
.project
Normal 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>
|
@ -14,71 +14,98 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.thialfihar.android.apg"
|
package="org.thialfihar.android.apg"
|
||||||
android:versionName="0.9.0" android:versionCode="5">
|
android:versionName="0.9.0" android:versionCode="5">
|
||||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
|
||||||
<activity android:name=".MainActivity"
|
<application
|
||||||
|
android:icon="@drawable/icon"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
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:name=".PublicKeyListActivity"
|
||||||
android:label="@string/title_managePublicKeys"
|
android:label="@string/title_managePublicKeys"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
android:configChanges="keyboardHidden|orientation|keyboard" />
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name=".SecretKeyListActivity"
|
<activity
|
||||||
|
android:name=".SecretKeyListActivity"
|
||||||
android:label="@string/title_manageSecretKeys"
|
android:label="@string/title_manageSecretKeys"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name=".EditKeyActivity"
|
<activity
|
||||||
|
android:name=".EditKeyActivity"
|
||||||
android:label="@string/title_editKey"
|
android:label="@string/title_editKey"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name=".SelectPublicKeyListActivity"
|
<activity
|
||||||
|
android:name=".SelectPublicKeyListActivity"
|
||||||
android:label="@string/title_selectRecipients"
|
android:label="@string/title_selectRecipients"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name=".SelectSecretKeyListActivity"
|
<activity
|
||||||
|
android:name=".SelectSecretKeyListActivity"
|
||||||
android:label="@string/title_selectSignature"
|
android:label="@string/title_selectSignature"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name=".EncryptMessageActivity"
|
<activity
|
||||||
|
android:name=".EncryptMessageActivity"
|
||||||
android:label="@string/title_encryptMessage"
|
android:label="@string/title_encryptMessage"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
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:name=".EncryptFileActivity"
|
||||||
|
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:label="@string/title_decryptMessage"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
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:name=".MailListActivity"
|
||||||
android:label="@string/title_mailInbox"
|
android:label="@string/title_mailInbox"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard">
|
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<provider android:name="org.thialfihar.android.apg.provider.DataProvider"
|
<provider
|
||||||
|
android:name="org.thialfihar.android.apg.provider.DataProvider"
|
||||||
android:authorities="org.thialfihar.android.apg.provider" />
|
android:authorities="org.thialfihar.android.apg.provider" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
BIN
bin/APG 0.9.x.apk
Normal file
BIN
bin/APG 0.9.x.apk
Normal file
Binary file not shown.
BIN
bin/classes.dex
Normal file
BIN
bin/classes.dex
Normal file
Binary file not shown.
BIN
bin/resources.ap_
Normal file
BIN
bin/resources.ap_
Normal file
Binary file not shown.
@ -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>
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content">
|
android:layout_width="wrap_content">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ic_signature"
|
android:id="@+id/ic_signature"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -79,9 +80,11 @@
|
|||||||
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="left"/>
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@ -94,4 +97,3 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -26,12 +26,14 @@
|
|||||||
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
|
<LinearLayout
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginRight="?android:attr/scrollbarSize"/>
|
android:layout_marginRight="?android:attr/scrollbarSize"/>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -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>
|
||||||
|
@ -31,18 +31,24 @@
|
|||||||
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">
|
||||||
|
|
||||||
<TableLayout
|
<TableLayout
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="0dip"
|
android:layout_width="0dip"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginLeft="16dip"
|
android:layout_marginLeft="16dip"
|
||||||
android:stretchColumns="1">
|
android:stretchColumns="1">
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TextView android:id="@+id/label_key_id" android:text="Key ID"
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_key_id"
|
||||||
|
android:text="Key ID"
|
||||||
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"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/key_id"
|
android:id="@+id/key_id"
|
||||||
android:text="00000000 00000000"
|
android:text="00000000 00000000"
|
||||||
@ -50,56 +56,79 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:paddingRight="5dip"
|
android:paddingRight="5dip"
|
||||||
android:typeface="monospace"/>
|
android:typeface="monospace"/>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<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"/>
|
||||||
<TextView android:id="@+id/algorithm"
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/algorithm"
|
||||||
android:text="Name"
|
android:text="Name"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:paddingRight="5dip"/>
|
android:paddingRight="5dip"/>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TextView android:id="@+id/label_creation"
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_creation"
|
||||||
android:text="Creation"
|
android:text="Creation"
|
||||||
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"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/creation"
|
android:id="@+id/creation"
|
||||||
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_expiry"
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_expiry"
|
||||||
android:text="Expiry"
|
android:text="Expiry"
|
||||||
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"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/expiry"
|
android:id="@+id/expiry"
|
||||||
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_usage"
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_usage"
|
||||||
android:text="Usage"
|
android:text="Usage"
|
||||||
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/usage"
|
android:id="@+id/usage"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
</TableLayout>
|
</TableLayout>
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
@ -110,4 +139,5 @@
|
|||||||
android:layout_gravity="center_vertical"/>
|
android:layout_gravity="center_vertical"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</org.thialfihar.android.apg.ui.widget.KeyEditor>
|
</org.thialfihar.android.apg.ui.widget.KeyEditor>
|
||||||
|
@ -28,20 +28,25 @@
|
|||||||
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_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_marginLeft="20dip"/>
|
android:layout_marginLeft="20dip"/>
|
||||||
|
|
||||||
<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">
|
||||||
|
|
||||||
<TableLayout
|
<TableLayout
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="0dip"
|
android:layout_width="0dip"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginLeft="16dip">
|
android:layout_marginLeft="16dip">
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/name_label"
|
android:id="@+id/name_label"
|
||||||
android:text="Name"
|
android:text="Name"
|
||||||
@ -49,13 +54,17 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:paddingRight="5dip"/>
|
android:paddingRight="5dip"/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="fill_parent"/>
|
android:layout_width="fill_parent"/>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/email_label"
|
android:id="@+id/email_label"
|
||||||
android:text="Email"
|
android:text="Email"
|
||||||
@ -63,13 +72,17 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:paddingRight="5dip"/>
|
android:paddingRight="5dip"/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/email"
|
android:id="@+id/email"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="fill_parent"/>
|
android:layout_width="fill_parent"/>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/comment_label"
|
android:id="@+id/comment_label"
|
||||||
android:text="Comment"
|
android:text="Comment"
|
||||||
@ -77,12 +90,15 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:paddingRight="5dip"/>
|
android:paddingRight="5dip"/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/comment"
|
android:id="@+id/comment"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="fill_parent"/>
|
android:layout_width="fill_parent"/>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
</TableLayout>
|
</TableLayout>
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
@ -93,4 +109,5 @@
|
|||||||
android:layout_gravity="center_vertical"/>
|
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
166
res/layout/encrypt_file.xml
Normal 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>
|
@ -27,12 +27,12 @@
|
|||||||
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"
|
||||||
@ -54,18 +54,18 @@
|
|||||||
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>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -91,5 +91,3 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,18 +18,20 @@
|
|||||||
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="horizontal"
|
||||||
android:paddingLeft="5dip"
|
android:paddingLeft="5dip"
|
||||||
android:paddingRight="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
28
res/layout/key_list.xml
Normal 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>
|
@ -19,7 +19,8 @@
|
|||||||
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"
|
||||||
@ -32,14 +33,17 @@
|
|||||||
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"
|
||||||
@ -48,11 +52,14 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="fill_parent" android:paddingBottom="2dip" android:paddingTop="2dip" android:layout_height="fill_parent" android:layout_gravity="center_vertical">
|
android:paddingBottom="2dip"
|
||||||
|
android:paddingTop="2dip"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_gravity="center_vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ic_encrypt_key"
|
android:id="@+id/ic_encrypt_key"
|
||||||
@ -69,4 +76,5 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -33,7 +33,9 @@
|
|||||||
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"
|
||||||
@ -42,7 +44,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@ -67,4 +68,5 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -24,7 +24,8 @@
|
|||||||
<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"
|
||||||
|
@ -32,17 +32,21 @@
|
|||||||
<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">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_encryptMessage"
|
android:id="@+id/btn_encryptMessage"
|
||||||
android:text="@string/btn_encryptMessage"
|
android:text="@string/btn_encryptMessage"
|
||||||
@ -59,4 +63,27 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</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>
|
@ -26,8 +26,7 @@
|
|||||||
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"
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
<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"/>
|
||||||
|
|
||||||
@ -50,6 +50,7 @@
|
|||||||
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
|
||||||
@ -64,7 +65,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/key_id"
|
android:id="@+id/key_id"
|
||||||
android:text="BBBBBBBB"
|
android:text="BBBBBBBB"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:typeface="monospace"
|
android:typeface="monospace"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="fill_parent"/>
|
android:layout_height="fill_parent"/>
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
<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>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<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"/>
|
||||||
|
|
||||||
@ -43,6 +43,7 @@
|
|||||||
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
|
||||||
@ -56,7 +57,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/key_id"
|
android:id="@+id/key_id"
|
||||||
android:text="BBBBBBBB"
|
android:text="BBBBBBBB"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:typeface="monospace"
|
android:typeface="monospace"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="fill_parent"/>
|
android:layout_height="fill_parent"/>
|
||||||
|
@ -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"><unknown></string>
|
<string name="unknown_user_id"><unknown></string>
|
||||||
<string name="none"><none></string>
|
<string name="none"><none></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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
235
src/org/thialfihar/android/apg/BaseActivity.java
Normal file
235
src/org/thialfihar/android/apg/BaseActivity.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
304
src/org/thialfihar/android/apg/EncryptFileActivity.java
Normal file
304
src/org/thialfihar/android/apg/EncryptFileActivity.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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,49 +151,36 @@ 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();
|
||||||
|
|
||||||
|
try {
|
||||||
|
boolean encryptIt = mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0;
|
||||||
|
|
||||||
String message = mMessage.getText().toString();
|
String message = mMessage.getText().toString();
|
||||||
|
if (!encryptIt) {
|
||||||
// fix the message a bit, trailing spaces and newlines break stuff,
|
// fix the message a bit, trailing spaces and newlines break stuff,
|
||||||
// because GMail sends as HTML and such things fuck up the signature,
|
// because GMail sends as HTML and such things fuck up the signature,
|
||||||
// TODO: things like "<" and ">" also fuck up the signature
|
// TODO: things like "<" and ">" also fuck up the signature
|
||||||
@ -301,18 +189,18 @@ public class EncryptMessageActivity extends Activity
|
|||||||
message = message.replaceFirst("^\n+", "");
|
message = message.replaceFirst("^\n+", "");
|
||||||
// make sure there'll be exactly one newline at the end
|
// make sure there'll be exactly one newline at the end
|
||||||
message = message.replaceFirst("\n*$", "\n");
|
message = message.replaceFirst("\n*$", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
ByteArrayInputStream in =
|
ByteArrayInputStream in =
|
||||||
new ByteArrayInputStream(Strings.toUTF8ByteArray(message));
|
new ByteArrayInputStream(Strings.toUTF8ByteArray(message));
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
try {
|
if (encryptIt) {
|
||||||
if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) {
|
Apg.encrypt(in, out, true, mEncryptionKeyIds, getSecretKeyId(),
|
||||||
Apg.encrypt(in, out, true, mEncryptionKeyIds, mSignatureKeyId,
|
|
||||||
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..."));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -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();
|
||||||
|
82
src/org/thialfihar/android/apg/Id.java
Normal file
82
src/org/thialfihar/android/apg/Id.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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,59 +48,280 @@ 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
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.key_list);
|
||||||
|
|
||||||
|
mList = (ExpandableListView) findViewById(R.id.list);
|
||||||
|
mList.setAdapter(new PublicKeyListAdapter(this));
|
||||||
|
registerForContextMenu(mList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
menu.add(0, Id.menu.option.import_keys, 0, "Import Keys")
|
||||||
|
.setIcon(android.R.drawable.ic_menu_add);
|
||||||
|
menu.add(0, Id.menu.option.export_keys, 1, "Export Keys")
|
||||||
|
.setIcon(android.R.drawable.ic_menu_save);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case Id.menu.option.import_keys: {
|
||||||
|
showDialog(Id.dialog.import_keys);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.menu.option.export_keys: {
|
||||||
|
showDialog(Id.dialog.export_keys);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||||
|
super.onCreateContextMenu(menu, v, menuInfo);
|
||||||
|
ExpandableListView.ExpandableListContextMenuInfo info =
|
||||||
|
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
|
||||||
|
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
||||||
|
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
||||||
|
|
||||||
|
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
||||||
|
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition);
|
||||||
|
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
||||||
|
menu.setHeaderTitle(userId);
|
||||||
|
menu.add(0, Id.menu.export, 0, "Export Key");
|
||||||
|
menu.add(0, Id.menu.delete, 1, "Delete Key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||||
|
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
|
||||||
|
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
||||||
|
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
||||||
|
|
||||||
|
if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
||||||
|
return super.onContextItemSelected(menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (menuItem.getItemId()) {
|
||||||
|
case Id.menu.export: {
|
||||||
|
mSelectedItem = groupPosition;
|
||||||
|
showDialog(Id.dialog.export_key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.menu.delete: {
|
||||||
|
mSelectedItem = groupPosition;
|
||||||
|
showDialog(Id.dialog.delete_key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return super.onContextItemSelected(menuItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Dialog onCreateDialog(int id) {
|
||||||
|
boolean singleKeyExport = false;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case Id.dialog.delete_key: {
|
||||||
|
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(mSelectedItem);
|
||||||
|
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle("Warning ");
|
||||||
|
builder.setMessage("Do you really want to delete the key '" + userId + "'?\n" +
|
||||||
|
"You can't undo this!");
|
||||||
|
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
||||||
|
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
deleteKey(mSelectedItem);
|
||||||
|
mSelectedItem = -1;
|
||||||
|
removeDialog(Id.dialog.delete_key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(android.R.string.cancel,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
mSelectedItem = -1;
|
||||||
|
removeDialog(Id.dialog.delete_key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.import_keys: {
|
||||||
|
return FileDialog.build(this, "Import Keys",
|
||||||
|
"Please specify which file to import from.",
|
||||||
|
mImportFilename,
|
||||||
|
new FileDialog.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOkClick(String filename) {
|
||||||
|
removeDialog(Id.dialog.import_keys);
|
||||||
|
mImportFilename = filename;
|
||||||
|
importKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelClick() {
|
||||||
|
removeDialog(Id.dialog.import_keys);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getString(R.string.filemanager_title_open),
|
||||||
|
getString(R.string.filemanager_btn_open));
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.export_key: {
|
||||||
|
singleKeyExport = true;
|
||||||
|
// break intentionally omitted, to use the Id.dialog.export_keys dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.export_keys: {
|
||||||
|
String title = "Export Key";
|
||||||
|
|
||||||
|
if (!singleKeyExport) {
|
||||||
|
// plural "Keys"
|
||||||
|
title += "s";
|
||||||
|
}
|
||||||
|
final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys);
|
||||||
|
|
||||||
|
return FileDialog.build(this, title,
|
||||||
|
"Please specify which file to export to.\n" +
|
||||||
|
"WARNING! File will be overwritten if it exists.",
|
||||||
|
mExportFilename,
|
||||||
|
new FileDialog.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOkClick(String filename) {
|
||||||
|
removeDialog(thisDialogId);
|
||||||
|
mExportFilename = filename;
|
||||||
|
exportKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelClick() {
|
||||||
|
removeDialog(thisDialogId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getString(R.string.filemanager_title_save),
|
||||||
|
getString(R.string.filemanager_btn_save));
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onCreateDialog(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void importKeys() {
|
||||||
|
showDialog(Id.dialog.importing);
|
||||||
|
mTask = Id.task.import_keys;
|
||||||
|
startThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportKeys() {
|
||||||
|
showDialog(Id.dialog.exporting);
|
||||||
|
mTask = Id.task.export_keys;
|
||||||
|
startThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String error = null;
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
Message msg = new Message();
|
||||||
|
|
||||||
|
String filename = null;
|
||||||
|
if (mTask == Id.task.import_keys) {
|
||||||
|
filename = mImportFilename;
|
||||||
|
} else {
|
||||||
|
filename = mExportFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mTask == Id.task.import_keys) {
|
||||||
|
data = Apg.importKeyRings(this, Id.type.public_key, filename, this);
|
||||||
|
} else {
|
||||||
|
Vector<Object> keys = new Vector<Object>();
|
||||||
|
if (mSelectedItem == -1) {
|
||||||
|
for (PGPPublicKeyRing key : Apg.getPublicKeyRings()) {
|
||||||
|
keys.add(key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keys.add(Apg.getPublicKeyRings().get(mSelectedItem));
|
||||||
|
}
|
||||||
|
data = Apg.exportKeyRings(this, keys, filename, this);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
error = "file '" + filename + "' not found";
|
||||||
|
} catch (IOException e) {
|
||||||
|
error = e.getMessage();
|
||||||
|
} catch (PGPException e) {
|
||||||
|
error = e.getMessage();
|
||||||
|
} catch (Apg.GeneralException e) {
|
||||||
|
error = e.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTask == Id.task.import_keys) {
|
||||||
|
data.putInt("type", Id.message.import_done);
|
||||||
|
} else {
|
||||||
|
data.putInt("type", Id.message.export_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != null) {
|
||||||
|
data.putString("error", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.setData(data);
|
||||||
|
sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteKey(int index) {
|
||||||
|
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(index);
|
||||||
|
Apg.deleteKey(this, keyRing);
|
||||||
|
refreshList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshList() {
|
||||||
|
((PublicKeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doneCallback(Message msg) {
|
||||||
|
super.doneCallback(msg);
|
||||||
|
|
||||||
Bundle data = msg.getData();
|
Bundle data = msg.getData();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
int type = data.getInt("type");
|
int type = data.getInt("type");
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MESSAGE_PROGRESS_UPDATE: {
|
case Id.message.import_done: {
|
||||||
String message = data.getString("message");
|
removeDialog(Id.dialog.importing);
|
||||||
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");
|
String error = data.getString("error");
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -132,9 +349,8 @@ public class PublicKeyListActivity extends ExpandableListActivity
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MESSAGE_EXPORT_DONE: {
|
case Id.message.export_done: {
|
||||||
removeDialog(DIALOG_EXPORTING);
|
removeDialog(Id.dialog.exporting);
|
||||||
mProgressDialog = null;
|
|
||||||
|
|
||||||
String error = data.getString("error");
|
String error = data.getString("error");
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -163,295 +379,6 @@ public class PublicKeyListActivity extends ExpandableListActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
Apg.initialize(this);
|
|
||||||
|
|
||||||
setListAdapter(new PublicKeyListAdapter(this));
|
|
||||||
registerForContextMenu(getExpandableListView());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
menu.add(0, OPTION_MENU_IMPORT_KEYS, 0, "Import Keys")
|
|
||||||
.setIcon(android.R.drawable.ic_menu_add);
|
|
||||||
menu.add(0, OPTION_MENU_EXPORT_KEYS, 1, "Export Keys")
|
|
||||||
.setIcon(android.R.drawable.ic_menu_save);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case OPTION_MENU_IMPORT_KEYS: {
|
|
||||||
showDialog(DIALOG_IMPORT_KEYS);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OPTION_MENU_EXPORT_KEYS: {
|
|
||||||
showDialog(DIALOG_EXPORT_KEYS);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
|
||||||
super.onCreateContextMenu(menu, v, menuInfo);
|
|
||||||
ExpandableListView.ExpandableListContextMenuInfo info =
|
|
||||||
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
|
|
||||||
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
|
||||||
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
|
||||||
|
|
||||||
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
|
||||||
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition);
|
|
||||||
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
|
||||||
menu.setHeaderTitle(userId);
|
|
||||||
menu.add(0, MENU_EXPORT, 0, "Export Key");
|
|
||||||
menu.add(0, MENU_DELETE, 1, "Delete Key");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
|
||||||
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
|
|
||||||
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
|
||||||
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
|
||||||
|
|
||||||
if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
|
||||||
return super.onContextItemSelected(menuItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
|
||||||
case MENU_EXPORT: {
|
|
||||||
mSelectedItem = groupPosition;
|
|
||||||
showDialog(DIALOG_EXPORT_KEY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MENU_DELETE: {
|
|
||||||
mSelectedItem = groupPosition;
|
|
||||||
showDialog(DIALOG_DELETE_KEY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return super.onContextItemSelected(menuItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Dialog onCreateDialog(int id) {
|
|
||||||
boolean singleKeyExport = false;
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
case DIALOG_DELETE_KEY: {
|
|
||||||
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(mSelectedItem);
|
|
||||||
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
||||||
builder.setTitle("Warning ");
|
|
||||||
builder.setMessage("Do you really want to delete the key '" + userId + "'?\n" +
|
|
||||||
"You can't undo this!");
|
|
||||||
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
|
||||||
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
deleteKey(mSelectedItem);
|
|
||||||
mSelectedItem = -1;
|
|
||||||
removeDialog(DIALOG_DELETE_KEY);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.cancel,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
mSelectedItem = -1;
|
|
||||||
removeDialog(DIALOG_DELETE_KEY);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_IMPORT_KEYS: {
|
|
||||||
return FileDialog.build(this, "Import Keys",
|
|
||||||
"Please specify which file to import from.",
|
|
||||||
mImportFilename,
|
|
||||||
new FileDialog.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOkClick(String filename) {
|
|
||||||
removeDialog(DIALOG_IMPORT_KEYS);
|
|
||||||
mImportFilename = filename;
|
|
||||||
importKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancelClick() {
|
|
||||||
removeDialog(DIALOG_IMPORT_KEYS);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getString(R.string.filemanager_title_open),
|
|
||||||
getString(R.string.filemanager_btn_open));
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_EXPORT_KEY: {
|
|
||||||
singleKeyExport = true;
|
|
||||||
// break intentionally omitted, to use the DIALOG_EXPORT_KEYS dialog
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_EXPORT_KEYS: {
|
|
||||||
String title = "Export Key";
|
|
||||||
|
|
||||||
if (!singleKeyExport) {
|
|
||||||
// plural "Keys"
|
|
||||||
title += "s";
|
|
||||||
}
|
|
||||||
final int thisDialogId = (singleKeyExport ? DIALOG_EXPORT_KEY : DIALOG_EXPORT_KEYS);
|
|
||||||
|
|
||||||
return FileDialog.build(this, title,
|
|
||||||
"Please specify which file to export to.\n" +
|
|
||||||
"WARNING! File will be overwritten if it exists.",
|
|
||||||
mExportFilename,
|
|
||||||
new FileDialog.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOkClick(String filename) {
|
|
||||||
removeDialog(thisDialogId);
|
|
||||||
mExportFilename = filename;
|
|
||||||
exportKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancelClick() {
|
|
||||||
removeDialog(thisDialogId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getString(R.string.filemanager_title_save),
|
|
||||||
getString(R.string.filemanager_btn_save));
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_IMPORTING: {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onCreateDialog(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void importKeys() {
|
|
||||||
showDialog(DIALOG_IMPORTING);
|
|
||||||
mTask = TASK_IMPORT;
|
|
||||||
mRunningThread = new Thread(this);
|
|
||||||
mRunningThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exportKeys() {
|
|
||||||
showDialog(DIALOG_EXPORTING);
|
|
||||||
mTask = TASK_EXPORT;
|
|
||||||
mRunningThread = new Thread(this);
|
|
||||||
mRunningThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
String error = null;
|
|
||||||
Bundle data = new Bundle();
|
|
||||||
Message msg = new Message();
|
|
||||||
|
|
||||||
String filename = null;
|
|
||||||
if (mTask == TASK_IMPORT) {
|
|
||||||
filename = mImportFilename;
|
|
||||||
} else {
|
|
||||||
filename = mExportFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (mTask == TASK_IMPORT) {
|
|
||||||
data = Apg.importKeyRings(this, Apg.TYPE_PUBLIC, filename, this);
|
|
||||||
} else {
|
|
||||||
Vector<Object> keys = new Vector<Object>();
|
|
||||||
if (mSelectedItem == -1) {
|
|
||||||
for (PGPPublicKeyRing key : Apg.getPublicKeyRings()) {
|
|
||||||
keys.add(key);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
keys.add(Apg.getPublicKeyRings().get(mSelectedItem));
|
|
||||||
}
|
|
||||||
data = Apg.exportKeyRings(this, keys, filename, this);
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
error = "file '" + filename + "' not found";
|
|
||||||
} catch (IOException e) {
|
|
||||||
error = e.getMessage();
|
|
||||||
} catch (PGPException e) {
|
|
||||||
error = e.getMessage();
|
|
||||||
} catch (Apg.GeneralException e) {
|
|
||||||
error = e.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTask == TASK_IMPORT) {
|
|
||||||
data.putInt("type", MESSAGE_IMPORT_DONE);
|
|
||||||
} else {
|
|
||||||
data.putInt("type", MESSAGE_EXPORT_DONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error != null) {
|
|
||||||
data.putString("error", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.setData(data);
|
|
||||||
mHandler.sendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteKey(int index) {
|
|
||||||
PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(index);
|
|
||||||
Apg.deleteKey(this, keyRing);
|
|
||||||
refreshList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshList() {
|
|
||||||
((PublicKeyListAdapter) getExpandableListAdapter()).notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PublicKeyListAdapter extends BaseExpandableListAdapter {
|
private static class PublicKeyListAdapter extends BaseExpandableListAdapter {
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
@ -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) {
|
||||||
|
@ -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,66 +49,362 @@ 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
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
Bundle data = msg.getData();
|
super.onCreate(savedInstanceState);
|
||||||
if (data != null) {
|
setContentView(R.layout.key_list);
|
||||||
int type = data.getInt("type");
|
|
||||||
switch (type) {
|
mList = (ExpandableListView) findViewById(R.id.list);
|
||||||
case MESSAGE_PROGRESS_UPDATE: {
|
mList.setAdapter(new SecretKeyListAdapter(this));
|
||||||
String message = data.getString("message");
|
registerForContextMenu(mList);
|
||||||
if (mProgressDialog != null) {
|
mList.setOnChildClickListener(this);
|
||||||
if (message != null) {
|
|
||||||
mProgressDialog.setMessage(message);
|
|
||||||
}
|
}
|
||||||
mProgressDialog.setMax(data.getInt("max"));
|
|
||||||
mProgressDialog.setProgress(data.getInt("progress"));
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
menu.add(0, Id.menu.option.import_keys, 0, "Import Keys")
|
||||||
|
.setIcon(android.R.drawable.ic_menu_add);
|
||||||
|
menu.add(0, Id.menu.option.export_keys, 1, "Export Keys")
|
||||||
|
.setIcon(android.R.drawable.ic_menu_save);
|
||||||
|
menu.add(1, Id.menu.option.create, 2, "Create Key")
|
||||||
|
.setIcon(android.R.drawable.ic_menu_add);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case Id.menu.option.import_keys: {
|
||||||
|
showDialog(Id.dialog.import_keys);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.menu.option.export_keys: {
|
||||||
|
showDialog(Id.dialog.export_keys);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.menu.option.create: {
|
||||||
|
createKey();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||||
|
super.onCreateContextMenu(menu, v, menuInfo);
|
||||||
|
ExpandableListView.ExpandableListContextMenuInfo info =
|
||||||
|
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
|
||||||
|
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
||||||
|
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
||||||
|
|
||||||
|
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
||||||
|
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition);
|
||||||
|
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
||||||
|
menu.setHeaderTitle(userId);
|
||||||
|
menu.add(0, Id.menu.edit, 0, "Edit Key");
|
||||||
|
menu.add(0, Id.menu.export, 1, "Export Key");
|
||||||
|
menu.add(0, Id.menu.delete, 2, "Delete Key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||||
|
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
|
||||||
|
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
||||||
|
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
||||||
|
|
||||||
|
if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
||||||
|
return super.onContextItemSelected(menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (menuItem.getItemId()) {
|
||||||
|
case Id.menu.edit: {
|
||||||
|
mSelectedItem = groupPosition;
|
||||||
|
showDialog(Id.dialog.pass_phrase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.menu.export: {
|
||||||
|
mSelectedItem = groupPosition;
|
||||||
|
showDialog(Id.dialog.export_key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.menu.delete: {
|
||||||
|
mSelectedItem = groupPosition;
|
||||||
|
showDialog(Id.dialog.delete_key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return super.onContextItemSelected(menuItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
|
||||||
|
int childPosition, long id) {
|
||||||
|
mSelectedItem = groupPosition;
|
||||||
|
showDialog(Id.dialog.pass_phrase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Dialog onCreateDialog(int id) {
|
||||||
|
boolean singleKeyExport = false;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case Id.dialog.delete_key: {
|
||||||
|
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
|
||||||
|
|
||||||
|
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle("Warning ");
|
||||||
|
builder.setMessage("Do you really want to delete the key '" + userId + "'?\n" +
|
||||||
|
"You can't undo this!");
|
||||||
|
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
||||||
|
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
deleteKey(mSelectedItem);
|
||||||
|
mSelectedItem = -1;
|
||||||
|
removeDialog(Id.dialog.delete_key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(android.R.string.ok,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
mSelectedItem = -1;
|
||||||
|
removeDialog(Id.dialog.delete_key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.import_keys: {
|
||||||
|
return FileDialog.build(this, "Import Keys",
|
||||||
|
"Please specify which file to import from.",
|
||||||
|
mImportFilename,
|
||||||
|
new FileDialog.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOkClick(String filename) {
|
||||||
|
removeDialog(Id.dialog.import_keys);
|
||||||
|
mImportFilename = filename;
|
||||||
|
importKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelClick() {
|
||||||
|
removeDialog(Id.dialog.import_keys);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getString(R.string.filemanager_title_open),
|
||||||
|
getString(R.string.filemanager_btn_open));
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.export_key: {
|
||||||
|
singleKeyExport = true;
|
||||||
|
// break intentionally omitted, to use the Id.dialog.export_keys dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.export_keys: {
|
||||||
|
String title = "Export Key";
|
||||||
|
|
||||||
|
if (!singleKeyExport) {
|
||||||
|
// plural "Keys"
|
||||||
|
title += "s";
|
||||||
|
}
|
||||||
|
final int thisDialogId = (singleKeyExport ? Id.dialog.delete_key : Id.dialog.export_keys);
|
||||||
|
|
||||||
|
return FileDialog.build(this, title,
|
||||||
|
"Please specify which file to export to.\n" +
|
||||||
|
"WARNING! You are about to export SECRET keys.\n" +
|
||||||
|
"WARNING! File will be overwritten if it exists.",
|
||||||
|
mExportFilename,
|
||||||
|
new FileDialog.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOkClick(String filename) {
|
||||||
|
removeDialog(thisDialogId);
|
||||||
|
mExportFilename = filename;
|
||||||
|
exportKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelClick() {
|
||||||
|
removeDialog(thisDialogId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getString(R.string.filemanager_title_save),
|
||||||
|
getString(R.string.filemanager_btn_save));
|
||||||
|
}
|
||||||
|
|
||||||
|
case Id.dialog.pass_phrase: {
|
||||||
|
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
|
||||||
|
long keyId = keyRing.getSecretKey().getKeyID();
|
||||||
|
return AskForSecretKeyPassPhrase.createDialog(this, keyId, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onCreateDialog(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void passPhraseCallback(String passPhrase) {
|
||||||
|
super.passPhraseCallback(passPhrase);
|
||||||
|
editKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createKey() {
|
||||||
|
Intent intent = new Intent(this, EditKeyActivity.class);
|
||||||
|
startActivityForResult(intent, Id.message.create_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void editKey() {
|
||||||
|
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
|
||||||
|
long keyId = keyRing.getSecretKey().getKeyID();
|
||||||
|
Intent intent = new Intent(this, EditKeyActivity.class);
|
||||||
|
intent.putExtra("keyId", keyId);
|
||||||
|
startActivityForResult(intent, Id.message.edit_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
switch (requestCode) {
|
||||||
|
case Id.message.create_key: // intentionally no break
|
||||||
|
case Id.message.edit_key: {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
refreshList();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MESSAGE_IMPORT_DONE: {
|
case Id.request.filename: {
|
||||||
removeDialog(DIALOG_IMPORTING);
|
if (resultCode == RESULT_OK && data != null) {
|
||||||
mProgressDialog = 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);
|
||||||
|
|
||||||
|
FileDialog.setFilename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void importKeys() {
|
||||||
|
showDialog(Id.dialog.importing);
|
||||||
|
mTask = Id.task.import_keys;
|
||||||
|
startThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportKeys() {
|
||||||
|
showDialog(Id.dialog.exporting);
|
||||||
|
mTask = Id.task.export_keys;
|
||||||
|
startThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String error = null;
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
Message msg = new Message();
|
||||||
|
|
||||||
|
String filename = null;
|
||||||
|
if (mTask == Id.task.import_keys) {
|
||||||
|
filename = mImportFilename;
|
||||||
|
} else {
|
||||||
|
filename = mExportFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mTask == Id.task.import_keys) {
|
||||||
|
data = Apg.importKeyRings(this, Id.type.secret_key, filename, this);
|
||||||
|
} else {
|
||||||
|
Vector<Object> keys = new Vector<Object>();
|
||||||
|
if (mSelectedItem == -1) {
|
||||||
|
for (PGPSecretKeyRing key : Apg.getSecretKeyRings()) {
|
||||||
|
keys.add(key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keys.add(Apg.getSecretKeyRings().get(mSelectedItem));
|
||||||
|
}
|
||||||
|
data = Apg.exportKeyRings(this, keys, filename, this);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
error = "file '" + filename + "' not found";
|
||||||
|
} catch (IOException e) {
|
||||||
|
error = e.getMessage();
|
||||||
|
} catch (PGPException e) {
|
||||||
|
error = e.getMessage();
|
||||||
|
} catch (Apg.GeneralException e) {
|
||||||
|
error = e.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTask == Id.task.import_keys) {
|
||||||
|
data.putInt("type", Id.message.import_done);
|
||||||
|
} else {
|
||||||
|
data.putInt("type", Id.message.export_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != null) {
|
||||||
|
data.putString("error", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.setData(data);
|
||||||
|
sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteKey(int index) {
|
||||||
|
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(index);
|
||||||
|
Apg.deleteKey(this, keyRing);
|
||||||
|
refreshList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshList() {
|
||||||
|
((SecretKeyListAdapter) 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");
|
String error = data.getString("error");
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -139,9 +432,8 @@ public class SecretKeyListActivity extends ExpandableListActivity
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MESSAGE_EXPORT_DONE: {
|
case Id.message.export_done: {
|
||||||
removeDialog(DIALOG_EXPORTING);
|
removeDialog(Id.dialog.exporting);
|
||||||
mProgressDialog = null;
|
|
||||||
|
|
||||||
String error = data.getString("error");
|
String error = data.getString("error");
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -170,382 +462,6 @@ public class SecretKeyListActivity extends ExpandableListActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
Apg.initialize(this);
|
|
||||||
|
|
||||||
setListAdapter(new SecretKeyListAdapter(this));
|
|
||||||
registerForContextMenu(getExpandableListView());
|
|
||||||
getExpandableListView().setOnChildClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
menu.add(0, OPTION_MENU_IMPORT_KEYS, 0, "Import Keys")
|
|
||||||
.setIcon(android.R.drawable.ic_menu_add);
|
|
||||||
menu.add(0, OPTION_MENU_EXPORT_KEYS, 1, "Export Keys")
|
|
||||||
.setIcon(android.R.drawable.ic_menu_save);
|
|
||||||
menu.add(1, OPTION_MENU_CREATE_KEY, 2, "Create Key")
|
|
||||||
.setIcon(android.R.drawable.ic_menu_add);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case OPTION_MENU_IMPORT_KEYS: {
|
|
||||||
showDialog(DIALOG_IMPORT_KEYS);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OPTION_MENU_EXPORT_KEYS: {
|
|
||||||
showDialog(DIALOG_EXPORT_KEYS);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OPTION_MENU_CREATE_KEY: {
|
|
||||||
createKey();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
|
||||||
ContextMenuInfo menuInfo) {
|
|
||||||
super.onCreateContextMenu(menu, v, menuInfo);
|
|
||||||
ExpandableListView.ExpandableListContextMenuInfo info =
|
|
||||||
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
|
|
||||||
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
|
||||||
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
|
||||||
|
|
||||||
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
|
||||||
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition);
|
|
||||||
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
|
||||||
menu.setHeaderTitle(userId);
|
|
||||||
menu.add(0, MENU_EDIT, 0, "Edit Key");
|
|
||||||
menu.add(0, MENU_EXPORT, 1, "Export Key");
|
|
||||||
menu.add(0, MENU_DELETE, 2, "Delete Key");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
|
||||||
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
|
|
||||||
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
|
|
||||||
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
|
|
||||||
|
|
||||||
if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
|
|
||||||
return super.onContextItemSelected(menuItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
|
||||||
case MENU_EDIT: {
|
|
||||||
mSelectedItem = groupPosition;
|
|
||||||
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MENU_EXPORT: {
|
|
||||||
mSelectedItem = groupPosition;
|
|
||||||
showDialog(DIALOG_EXPORT_KEY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MENU_DELETE: {
|
|
||||||
mSelectedItem = groupPosition;
|
|
||||||
showDialog(DIALOG_DELETE_KEY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return super.onContextItemSelected(menuItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
|
|
||||||
int childPosition, long id) {
|
|
||||||
mSelectedItem = groupPosition;
|
|
||||||
showDialog(AskForSecretKeyPassPhrase.DIALOG_PASS_PHRASE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Dialog onCreateDialog(int id) {
|
|
||||||
boolean singleKeyExport = false;
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
case DIALOG_DELETE_KEY: {
|
|
||||||
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
|
|
||||||
|
|
||||||
String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing));
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
||||||
builder.setTitle("Warning ");
|
|
||||||
builder.setMessage("Do you really want to delete the key '" + userId + "'?\n" +
|
|
||||||
"You can't undo this!");
|
|
||||||
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
|
||||||
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
deleteKey(mSelectedItem);
|
|
||||||
mSelectedItem = -1;
|
|
||||||
removeDialog(DIALOG_DELETE_KEY);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.ok,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
mSelectedItem = -1;
|
|
||||||
removeDialog(DIALOG_DELETE_KEY);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_IMPORT_KEYS: {
|
|
||||||
return FileDialog.build(this, "Import Keys",
|
|
||||||
"Please specify which file to import from.",
|
|
||||||
mImportFilename,
|
|
||||||
new FileDialog.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOkClick(String filename) {
|
|
||||||
removeDialog(DIALOG_IMPORT_KEYS);
|
|
||||||
mImportFilename = filename;
|
|
||||||
importKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancelClick() {
|
|
||||||
removeDialog(DIALOG_IMPORT_KEYS);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getString(R.string.filemanager_title_open),
|
|
||||||
getString(R.string.filemanager_btn_open));
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_EXPORT_KEY: {
|
|
||||||
singleKeyExport = true;
|
|
||||||
// break intentionally omitted, to use the DIALOG_EXPORT_KEYS dialog
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_EXPORT_KEYS: {
|
|
||||||
String title = "Export Key";
|
|
||||||
|
|
||||||
if (!singleKeyExport) {
|
|
||||||
// plural "Keys"
|
|
||||||
title += "s";
|
|
||||||
}
|
|
||||||
final int thisDialogId = (singleKeyExport ? DIALOG_DELETE_KEY : DIALOG_EXPORT_KEYS);
|
|
||||||
|
|
||||||
return FileDialog.build(this, title,
|
|
||||||
"Please specify which file to export to.\n" +
|
|
||||||
"WARNING! You are about to export SECRET keys.\n" +
|
|
||||||
"WARNING! File will be overwritten if it exists.",
|
|
||||||
mExportFilename,
|
|
||||||
new FileDialog.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOkClick(String filename) {
|
|
||||||
removeDialog(thisDialogId);
|
|
||||||
mExportFilename = filename;
|
|
||||||
exportKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancelClick() {
|
|
||||||
removeDialog(thisDialogId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getString(R.string.filemanager_title_save),
|
|
||||||
getString(R.string.filemanager_btn_save));
|
|
||||||
}
|
|
||||||
|
|
||||||
case DIALOG_IMPORTING: {
|
|
||||||
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);
|
|
||||||
long keyId = keyRing.getSecretKey().getKeyID();
|
|
||||||
return AskForSecretKeyPassPhrase.createDialog(this, keyId, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onCreateDialog(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void passPhraseCallback(String passPhrase) {
|
|
||||||
Apg.setPassPhrase(passPhrase);
|
|
||||||
editKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createKey() {
|
|
||||||
Intent intent = new Intent(this, EditKeyActivity.class);
|
|
||||||
startActivityForResult(intent, CREATE_SECRET_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void editKey() {
|
|
||||||
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem);
|
|
||||||
long keyId = keyRing.getSecretKey().getKeyID();
|
|
||||||
Intent intent = new Intent(this, EditKeyActivity.class);
|
|
||||||
intent.putExtra("keyId", keyId);
|
|
||||||
startActivityForResult(intent, EDIT_SECRET_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
switch (requestCode) {
|
|
||||||
case CREATE_SECRET_KEY: // intentionally no break
|
|
||||||
case EDIT_SECRET_KEY: {
|
|
||||||
if (resultCode == RESULT_OK) {
|
|
||||||
refreshList();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FileDialog.REQUEST_CODE_PICK_FILE_OR_DIRECTORY: {
|
|
||||||
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);
|
|
||||||
|
|
||||||
FileDialog.setFilename(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void importKeys() {
|
|
||||||
showDialog(DIALOG_IMPORTING);
|
|
||||||
mTask = TASK_IMPORT;
|
|
||||||
mRunningThread = new Thread(this);
|
|
||||||
mRunningThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exportKeys() {
|
|
||||||
showDialog(DIALOG_EXPORTING);
|
|
||||||
mTask = TASK_EXPORT;
|
|
||||||
mRunningThread = new Thread(this);
|
|
||||||
mRunningThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
String error = null;
|
|
||||||
Bundle data = new Bundle();
|
|
||||||
Message msg = new Message();
|
|
||||||
|
|
||||||
String filename = null;
|
|
||||||
if (mTask == TASK_IMPORT) {
|
|
||||||
filename = mImportFilename;
|
|
||||||
} else {
|
|
||||||
filename = mExportFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (mTask == TASK_IMPORT) {
|
|
||||||
data = Apg.importKeyRings(this, Apg.TYPE_SECRET, filename, this);
|
|
||||||
} else {
|
|
||||||
Vector<Object> keys = new Vector<Object>();
|
|
||||||
if (mSelectedItem == -1) {
|
|
||||||
for (PGPSecretKeyRing key : Apg.getSecretKeyRings()) {
|
|
||||||
keys.add(key);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
keys.add(Apg.getSecretKeyRings().get(mSelectedItem));
|
|
||||||
}
|
|
||||||
data = Apg.exportKeyRings(this, keys, filename, this);
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
error = "file '" + filename + "' not found";
|
|
||||||
} catch (IOException e) {
|
|
||||||
error = e.getMessage();
|
|
||||||
} catch (PGPException e) {
|
|
||||||
error = e.getMessage();
|
|
||||||
} catch (Apg.GeneralException e) {
|
|
||||||
error = e.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTask == TASK_IMPORT) {
|
|
||||||
data.putInt("type", MESSAGE_IMPORT_DONE);
|
|
||||||
} else {
|
|
||||||
data.putInt("type", MESSAGE_EXPORT_DONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error != null) {
|
|
||||||
data.putString("error", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.setData(data);
|
|
||||||
mHandler.sendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteKey(int index) {
|
|
||||||
PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(index);
|
|
||||||
Apg.deleteKey(this, keyRing);
|
|
||||||
refreshList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshList() {
|
|
||||||
((SecretKeyListAdapter) getExpandableListAdapter())
|
|
||||||
.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class SecretKeyListAdapter extends BaseExpandableListAdapter {
|
private static class SecretKeyListAdapter extends BaseExpandableListAdapter {
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
186
src/org/thialfihar/android/apg/SelectPublicKeyListAdapter.java
Normal file
186
src/org/thialfihar/android/apg/SelectPublicKeyListAdapter.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user