renaming whole package to org.apg to simplifiy name

This commit is contained in:
Dominik 2012-03-09 16:27:29 +01:00
parent df6933bfb8
commit 8452fb62b7
69 changed files with 1914 additions and 1628 deletions

View File

@ -3,7 +3,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="org.thialfihar.android.apg"
package="org.apg"
android:versionCode="11000"
android:versionName="1.1" >
@ -33,7 +33,7 @@
android:icon="@drawable/icon"
android:label="@string/app_name" >
<activity
android:name=".MainActivity"
android:name=".ui.MainActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/app_name" >
<intent-filter>
@ -43,7 +43,7 @@
</intent-filter>
</activity>
<activity
android:name=".PublicKeyListActivity"
android:name=".ui.PublicKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_managePublicKeys"
android:launchMode="singleTop" >
@ -56,7 +56,7 @@
android:resource="@xml/searchable_public_keys" />
</activity>
<activity
android:name=".SecretKeyListActivity"
android:name=".ui.SecretKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_manageSecretKeys"
android:launchMode="singleTop" >
@ -69,11 +69,11 @@
android:resource="@xml/searchable_secret_keys" />
</activity>
<activity
android:name=".EditKeyActivity"
android:name=".ui.EditKeyActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_editKey" />
<activity
android:name=".SelectPublicKeyListActivity"
android:name=".ui.SelectPublicKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_selectRecipients"
android:launchMode="singleTop" >
@ -91,7 +91,7 @@
android:resource="@xml/searchable_public_keys" />
</activity>
<activity
android:name=".SelectSecretKeyListActivity"
android:name=".ui.SelectSecretKeyListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_selectSignature"
android:launchMode="singleTop" >
@ -109,7 +109,7 @@
android:resource="@xml/searchable_secret_keys" />
</activity>
<activity
android:name=".EncryptActivity"
android:name=".ui.EncryptActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_encrypt" >
<intent-filter>
@ -124,7 +124,7 @@
</intent-filter>
</activity>
<activity
android:name=".DecryptActivity"
android:name=".ui.DecryptActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_decrypt" >
<intent-filter>
@ -138,7 +138,7 @@
</intent-filter>
</activity>
<activity
android:name=".GeneralActivity"
android:name=".ui.GeneralActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog" >
@ -170,31 +170,31 @@
</intent-filter>
</activity>
<activity
android:name=".MailListActivity"
android:name=".ui.MailListActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_mailInbox" />
<activity
android:name=".KeyServerQueryActivity"
android:name=".ui.KeyServerQueryActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_keyServerQuery" />
<activity
android:name=".SendKeyActivity"
android:name=".ui.SendKeyActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_sendKey" />
<activity
android:name=".PreferencesActivity"
android:name=".ui.PreferencesActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_preferences" />
<activity
android:name=".KeyServerPreferenceActivity"
android:name=".ui.KeyServerPreferenceActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_keyServerPreference" />
<activity
android:name=".SignKeyActivity"
android:name=".ui.SignKeyActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_signKey" />
<activity
android:name=".ImportFromQRCodeActivity"
android:name=".ui.ImportFromQRCodeActivity"
android:configChanges="keyboardHidden|orientation|keyboard"
android:label="@string/title_importFromQRCode" />
@ -215,11 +215,11 @@
</service>
<provider
android:name="org.thialfihar.android.apg.provider.DataProvider"
android:name=".provider.DataProvider"
android:authorities="org.thialfihar.android.apg.provider"
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
<provider
android:name="org.thialfihar.android.apg.provider.ApgServiceBlobProvider"
android:name=".provider.ApgServiceBlobProvider"
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider"
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" />
</application>

202
COPYING Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -14,7 +14,7 @@
limitations under the License.
-->
<org.thialfihar.android.apg.ui.widget.SectionView
<org.apg.ui.widget.SectionView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@ -63,4 +63,4 @@
android:paddingBottom="6dip"
android:orientation="vertical"/>
</org.thialfihar.android.apg.ui.widget.SectionView>
</org.apg.ui.widget.SectionView>

View File

@ -14,7 +14,7 @@
limitations under the License.
-->
<org.thialfihar.android.apg.ui.widget.UserIdEditor
<org.apg.ui.widget.UserIdEditor
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@ -112,4 +112,4 @@
</LinearLayout>
</org.thialfihar.android.apg.ui.widget.UserIdEditor>
</org.apg.ui.widget.UserIdEditor>

View File

@ -14,7 +14,7 @@
limitations under the License.
-->
<org.thialfihar.android.apg.ui.widget.KeyServerEditor
<org.apg.ui.widget.KeyServerEditor
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@ -49,4 +49,4 @@
android:layout_height="1dip"
android:background="?android:attr/listDivider"/>
</org.thialfihar.android.apg.ui.widget.KeyServerEditor>
</org.apg.ui.widget.KeyServerEditor>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
<!--
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.
@ -15,6 +16,7 @@
-->
<resources>
<style name="MinusButton">
<item name="android:background">@drawable/btn_circle</item>
<item name="android:src">@drawable/ic_btn_round_minus</item>
@ -24,4 +26,5 @@
<item name="android:background">@drawable/btn_circle</item>
<item name="android:src">@drawable/ic_btn_round_plus</item>
</style>
</resources>
</resources>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
<!--
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.
@ -14,71 +15,56 @@
limitations under the License.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/section_general">
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="@string/section_general" >
<ListPreference
android:key="language"
android:title="@string/label_language"
android:dialogTitle="@string/label_language"
android:entries="@array/language_entries"
android:entryValues="@array/language_values"
android:dialogTitle="@string/label_language" />
android:key="language"
android:title="@string/label_language" />
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
android:persistent="false"
android:key="passPhraseCacheTtl"
<org.apg.ui.widget.IntegerListPreference
android:entries="@array/pass_phrase_cache_ttl_entries"
android:entryValues="@array/pass_phrase_cache_ttl_values"
android:key="passPhraseCacheTtl"
android:persistent="false"
android:title="@string/label_passPhraseCacheTtl" />
<PreferenceScreen
android:persistent="false"
android:key="keyServers"
android:persistent="false"
android:title="@string/label_keyServers" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/section_defaults">
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
android:persistent="false"
<PreferenceCategory android:title="@string/section_defaults" >
<org.apg.ui.widget.IntegerListPreference
android:key="defaultEncryptionAlgorithm"
android:persistent="false"
android:title="@string/label_encryptionAlgorithm" />
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
android:persistent="false"
<org.apg.ui.widget.IntegerListPreference
android:key="defaultHashAlgorithm"
android:persistent="false"
android:title="@string/label_hashAlgorithm" />
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
android:persistent="false"
<org.apg.ui.widget.IntegerListPreference
android:key="defaultMessageCompression"
android:title="@string/label_messageCompression" />
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
android:persistent="false"
android:title="@string/label_messageCompression" />
<org.apg.ui.widget.IntegerListPreference
android:key="defaultFileCompression"
android:persistent="false"
android:title="@string/label_fileCompression" />
<CheckBoxPreference
android:persistent="false"
android:key="defaultAsciiArmour"
android:title="@string/label_asciiArmour" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/section_advanced">
<CheckBoxPreference
android:persistent="false"
android:title="@string/label_asciiArmour" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/section_advanced" >
<CheckBoxPreference
android:key="forceV3Signatures"
android:persistent="false"
android:title="@string/label_forceV3Signature" />
</PreferenceCategory>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
<!--
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.
@ -14,8 +15,8 @@
limitations under the License.
-->
<searchable
xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/hint_publicKeys">
</searchable>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/hint_publicKeys"
android:label="@string/app_name" >
</searchable>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
<!--
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.
@ -14,8 +15,8 @@
limitations under the License.
-->
<searchable
xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/hint_secretKeys">
</searchable>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/hint_secretKeys"
android:label="@string/app_name" >
</searchable>

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -11,9 +11,10 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.apg.provider.KeyRings;
import org.apg.provider.Keys;
import org.apg.provider.UserIds;
import org.apg.IApgService;
import android.content.ContentResolver;
import android.content.Intent;
@ -31,28 +32,22 @@ public class ApgService extends Service {
@Override
public IBinder onBind(Intent intent) {
if( LOCAL_LOGD ) Log.d(TAG, "bound");
if (LOCAL_LOGD)
Log.d(TAG, "bound");
return mBinder;
}
/** error status */
private static enum error {
ARGUMENTS_MISSING,
APG_FAILURE,
NO_MATCHING_SECRET_KEY,
PRIVATE_KEY_PASSPHRASE_WRONG,
PRIVATE_KEY_PASSPHRASE_MISSING;
ARGUMENTS_MISSING, APG_FAILURE, NO_MATCHING_SECRET_KEY, PRIVATE_KEY_PASSPHRASE_WRONG, PRIVATE_KEY_PASSPHRASE_MISSING;
public int shiftedOrdinal() {
return ordinal() + 100;
}
}
private static enum call {
encrypt_with_passphrase,
encrypt_with_public_key,
decrypt,
get_keys
encrypt_with_passphrase, encrypt_with_public_key, decrypt, get_keys
}
/** all arguments that can be passed by calling application */
@ -139,42 +134,49 @@ public class ApgService extends Service {
private static final HashMap<String, Method> FUNCTIONS_DEFAULTS_METHODS = new HashMap<String, Method>();
static {
try {
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm", Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultHashAlgorithm", Preferences.class.getMethod("getDefaultHashAlgorithm"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultAsciiArmour", Preferences.class.getMethod("getDefaultAsciiArmour"));
FUNCTIONS_DEFAULTS_METHODS.put("getForceV3Signatures", Preferences.class.getMethod("getForceV3Signatures"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultMessageCompression", Preferences.class.getMethod("getDefaultMessageCompression"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm",
Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultHashAlgorithm",
Preferences.class.getMethod("getDefaultHashAlgorithm"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultAsciiArmour",
Preferences.class.getMethod("getDefaultAsciiArmour"));
FUNCTIONS_DEFAULTS_METHODS.put("getForceV3Signatures",
Preferences.class.getMethod("getForceV3Signatures"));
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultMessageCompression",
Preferences.class.getMethod("getDefaultMessageCompression"));
} catch (Exception e) {
Log.e(TAG, "Function method exception: " + e.getMessage());
}
}
private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[8];
int len = 0;
while( (len = is.read(buffer)) != -1) {
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
}
private static Cursor getKeyEntries(HashMap<String, Object> pParams) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME
+ "." + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME
+ " ON " + "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "."
+ UserIds.RANK + " = '0') ");
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
+ Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
+ " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
+ Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
+ UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') ");
String orderBy = pParams.containsKey("order_by") ? (String) pParams.get("order_by") : UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC";
String orderBy = pParams.containsKey("order_by") ? (String) pParams.get("order_by")
: UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC";
String typeVal[] = null;
String typeWhere = null;
if (pParams.containsKey("key_type")) {
typeWhere = KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?";
typeVal = new String[] {
"" + pParams.get("key_type")
};
typeVal = new String[] { "" + pParams.get("key_type") };
}
return qb.query(Apg.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere, typeVal, null, null, orderBy);
return qb.query(Apg.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere,
typeVal, null, null, orderBy);
}
/**
@ -197,40 +199,43 @@ public class ApgService extends Service {
return 0;
}
}
/**
* maps fingerprints or user ids of keys to master keys in database
*
* @param search_keys
* a list of keys (fingerprints or user ids) to look for in
* database
* a list of keys (fingerprints or user ids) to look for in database
* @return an array of master keys
*/
private static long[] getMasterKey(ArrayList<String> pSearchKeys, Bundle pReturn) {
HashMap<String, Object> qParams = new HashMap<String, Object>();
qParams.put("columns", new String[] {
KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 0
qParams.put("columns", new String[] { KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 0
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 1
});
qParams.put("key_type", Id.database.type_public);
Cursor mCursor = getKeyEntries(qParams);
if( LOCAL_LOGV ) Log.v(TAG, "going through installed user keys");
if (LOCAL_LOGV)
Log.v(TAG, "going through installed user keys");
ArrayList<Long> masterKeys = new ArrayList<Long>();
while (mCursor.moveToNext()) {
long curMkey = mCursor.getLong(0);
String curUser = mCursor.getString(1);
String curFprint = Apg.getSmallFingerPrint(curMkey);
if( LOCAL_LOGV ) Log.v(TAG, "current user: " + curUser + " (" + curFprint + ")");
if (LOCAL_LOGV)
Log.v(TAG, "current user: " + curUser + " (" + curFprint + ")");
if (pSearchKeys.contains(curFprint) || pSearchKeys.contains(curUser)) {
if( LOCAL_LOGV ) Log.v(TAG, "master key found for: " + curFprint);
if (LOCAL_LOGV)
Log.v(TAG, "master key found for: " + curFprint);
masterKeys.add(curMkey);
pSearchKeys.remove(curFprint);
} else {
if( LOCAL_LOGV ) Log.v(TAG, "Installed key " + curFprint + " is not in the list of public keys to encrypt with");
if (LOCAL_LOGV)
Log.v(TAG, "Installed key " + curFprint
+ " is not in the list of public keys to encrypt with");
}
}
mCursor.close();
@ -243,12 +248,14 @@ public class ApgService extends Service {
if (i == 0) {
Log.w(TAG, "Found not one public key");
pReturn.getStringArrayList(ret.WARNINGS.name()).add("Searched for public key(s) but found not one");
pReturn.getStringArrayList(ret.WARNINGS.name()).add(
"Searched for public key(s) but found not one");
}
for (String key : pSearchKeys) {
Log.w(TAG, "Searched for key " + key + " but cannot find it in APG");
pReturn.getStringArrayList(ret.WARNINGS.name()).add("Searched for key " + key + " but cannot find it in APG");
pReturn.getStringArrayList(ret.WARNINGS.name()).add(
"Searched for key " + key + " but cannot find it in APG");
}
return masterKeyLongs;
@ -269,18 +276,27 @@ public class ApgService extends Service {
while (iter.hasNext()) {
arg currentArg = iter.next();
String currentKey = currentArg.name();
if (!pArgs.containsKey(currentKey) && FUNCTIONS_OPTIONAL_ARGS.get(pCall).contains(currentArg)) {
if (!pArgs.containsKey(currentKey)
&& FUNCTIONS_OPTIONAL_ARGS.get(pCall).contains(currentArg)) {
String currentFunctionName = FUNCTIONS_DEFAULTS.get(currentArg);
try {
Class<?> returnType = FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName).getReturnType();
Class<?> returnType = FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
.getReturnType();
if (returnType == String.class) {
pArgs.putString(currentKey, (String) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName).invoke(preferences));
pArgs.putString(currentKey,
(String) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
.invoke(preferences));
} else if (returnType == boolean.class) {
pArgs.putBoolean(currentKey, (Boolean) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName).invoke(preferences));
pArgs.putBoolean(currentKey,
(Boolean) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
.invoke(preferences));
} else if (returnType == int.class) {
pArgs.putInt(currentKey, (Integer) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName).invoke(preferences));
pArgs.putInt(currentKey,
(Integer) FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
.invoke(preferences));
} else {
Log.e(TAG, "Unknown return type " + returnType.toString() + " for default option");
Log.e(TAG, "Unknown return type " + returnType.toString()
+ " for default option");
}
} catch (Exception e) {
Log.e(TAG, "Exception in add_default_arguments " + e.getMessage());
@ -320,19 +336,21 @@ public class ApgService extends Service {
while (iter.hasNext()) {
String curArg = iter.next().name();
if (!pArgs.containsKey(curArg)) {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Argument missing: " + curArg);
pReturn.getStringArrayList(ret.ERRORS.name())
.add("Argument missing: " + curArg);
}
}
}
if(pFunction.equals(call.encrypt_with_passphrase.name()) ||
pFunction.equals(call.encrypt_with_public_key.name()) ||
pFunction.equals(call.decrypt.name())) {
if (pFunction.equals(call.encrypt_with_passphrase.name())
|| pFunction.equals(call.encrypt_with_public_key.name())
|| pFunction.equals(call.decrypt.name())) {
// check that either MESSAGE or BLOB are there
if( !pArgs.containsKey(arg.MESSAGE.name()) && !pArgs.containsKey(arg.BLOB.name())) {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Arguments missing: Neither MESSAGE nor BLOG found");
if (!pArgs.containsKey(arg.MESSAGE.name()) && !pArgs.containsKey(arg.BLOB.name())) {
pReturn.getStringArrayList(ret.ERRORS.name()).add(
"Arguments missing: Neither MESSAGE nor BLOG found");
}
}
}
@ -363,7 +381,8 @@ public class ApgService extends Service {
try {
arg curArg = arg.valueOf(curKey);
if (!allArgs.contains(curArg)) {
pReturn.getStringArrayList(ret.WARNINGS.name()).add("Unknown argument: " + curKey);
pReturn.getStringArrayList(ret.WARNINGS.name()).add(
"Unknown argument: " + curKey);
unknownArgs.add(curKey);
}
} catch (Exception e) {
@ -386,23 +405,28 @@ public class ApgService extends Service {
/* add default arguments if missing */
addDefaultArguments(pCall, pArgs);
if( LOCAL_LOGV ) Log.v(TAG, "add_default_arguments");
if (LOCAL_LOGV)
Log.v(TAG, "add_default_arguments");
/* check for required arguments */
checkForRequiredArgs(pCall, pArgs, pReturn);
if( LOCAL_LOGV ) Log.v(TAG, "check_required_args");
if (LOCAL_LOGV)
Log.v(TAG, "check_required_args");
/* check for unknown arguments and add to warning if found */
checkForUnknownArgs(pCall, pArgs, pReturn);
if( LOCAL_LOGV ) Log.v(TAG, "check_unknown_args");
if (LOCAL_LOGV)
Log.v(TAG, "check_unknown_args");
/* return if errors happened */
if (pReturn.getStringArrayList(ret.ERRORS.name()).size() != 0) {
if( LOCAL_LOGV ) Log.v(TAG, "Errors after preparing, not executing "+pCall);
if (LOCAL_LOGV)
Log.v(TAG, "Errors after preparing, not executing " + pCall);
pReturn.putInt(ret.ERROR.name(), error.ARGUMENTS_MISSING.shiftedOrdinal());
return false;
}
if( LOCAL_LOGV ) Log.v(TAG, "error return");
if (LOCAL_LOGV)
Log.v(TAG, "error return");
return true;
}
@ -414,7 +438,8 @@ public class ApgService extends Service {
if (pArgs.containsKey(arg.PUBLIC_KEYS.name())) {
ArrayList<String> list = pArgs.getStringArrayList(arg.PUBLIC_KEYS.name());
ArrayList<String> pubKeys = new ArrayList<String>();
if( LOCAL_LOGV ) Log.v(TAG, "Long size: " + list.size());
if (LOCAL_LOGV)
Log.v(TAG, "Long size: " + list.size());
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
pubKeys.add(iter.next());
@ -423,7 +448,7 @@ public class ApgService extends Service {
}
InputStream inStream = null;
if(isBlob) {
if (isBlob) {
ContentResolver cr = getContentResolver();
try {
inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
@ -436,14 +461,16 @@ public class ApgService extends Service {
InputData in = new InputData(inStream, 0); // XXX Size second param?
OutputStream out = new ByteArrayOutputStream();
if( LOCAL_LOGV ) Log.v(TAG, "About to encrypt");
if (LOCAL_LOGV)
Log.v(TAG, "About to encrypt");
try {
Apg.encrypt(getBaseContext(), // context
in, // input stream
out, // output stream
pArgs.getBoolean(arg.ARMORED_OUTPUT.name()), // ARMORED_OUTPUT
pubMasterKeys, // encryption keys
getMasterKey(pArgs.getString(arg.SIGNATURE_KEY.name()), pReturn), // signature key
getMasterKey(pArgs.getString(arg.SIGNATURE_KEY.name()), pReturn), // signature
// key
pArgs.getString(arg.PRIVATE_KEY_PASSPHRASE.name()), // signature passphrase
null, // progress
pArgs.getInt(arg.ENCRYPTION_ALGORYTHM.name()), // encryption
@ -451,27 +478,38 @@ public class ApgService extends Service {
pArgs.getInt(arg.COMPRESSION.name()), // compression
pArgs.getBoolean(arg.FORCE_V3_SIGNATURE.name()), // mPreferences.getForceV3Signatures(),
pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) // passPhrase
);
);
} catch (Exception e) {
Log.e(TAG, "Exception in encrypt");
String msg = e.getMessage();
if (msg.equals(getBaseContext().getString(R.string.error_noSignaturePassPhrase))) {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " missing): " + msg);
pReturn.putInt(ret.ERROR.name(), error.PRIVATE_KEY_PASSPHRASE_MISSING.shiftedOrdinal());
} else if (msg.equals(getBaseContext().getString(R.string.error_couldNotExtractPrivateKey))) {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " probably wrong): " + msg);
pReturn.putInt(ret.ERROR.name(), error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
pReturn.getStringArrayList(ret.ERRORS.name()).add(
"Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " missing): "
+ msg);
pReturn.putInt(ret.ERROR.name(),
error.PRIVATE_KEY_PASSPHRASE_MISSING.shiftedOrdinal());
} else if (msg.equals(getBaseContext().getString(
R.string.error_couldNotExtractPrivateKey))) {
pReturn.getStringArrayList(ret.ERRORS.name()).add(
"Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name()
+ " probably wrong): " + msg);
pReturn.putInt(ret.ERROR.name(),
error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
} else {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Internal failure (" + e.getClass() + ") in APG when encrypting: " + e.getMessage());
pReturn.getStringArrayList(ret.ERRORS.name()).add(
"Internal failure (" + e.getClass() + ") in APG when encrypting: "
+ e.getMessage());
pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.shiftedOrdinal());
}
return false;
}
if( LOCAL_LOGV ) Log.v(TAG, "Encrypted");
if(isBlob) {
if (LOCAL_LOGV)
Log.v(TAG, "Encrypted");
if (isBlob) {
ContentResolver cr = getContentResolver();
try {
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
.name())));
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
outStream.close();
} catch (Exception e) {
@ -501,7 +539,8 @@ public class ApgService extends Service {
ArrayList<String> fPrints = new ArrayList<String>();
ArrayList<String> ids = new ArrayList<String>();
while (cursor.moveToNext()) {
if( LOCAL_LOGV ) Log.v(TAG, "adding key "+Apg.getSmallFingerPrint(cursor.getLong(0)));
if (LOCAL_LOGV)
Log.v(TAG, "adding key " + Apg.getSmallFingerPrint(cursor.getLong(0)));
fPrints.add(Apg.getSmallFingerPrint(cursor.getLong(0)));
ids.add(cursor.getString(1));
}
@ -533,14 +572,15 @@ public class ApgService extends Service {
if (!prepareArgs("decrypt", pArgs, pReturn)) {
return false;
}
boolean isBlob = pArgs.containsKey(arg.BLOB.name());
String passphrase = pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null ? pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) : pArgs
String passphrase = pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null ? pArgs
.getString(arg.SYMMETRIC_PASSPHRASE.name()) : pArgs
.getString(arg.PRIVATE_KEY_PASSPHRASE.name());
InputStream inStream = null;
if(isBlob) {
if (isBlob) {
ContentResolver cr = getContentResolver();
try {
inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
@ -550,14 +590,15 @@ public class ApgService extends Service {
} else {
inStream = new ByteArrayInputStream(pArgs.getString(arg.MESSAGE.name()).getBytes());
}
InputData in = new InputData(inStream, 0); // XXX what size in second parameter?
OutputStream out = new ByteArrayOutputStream();
if( LOCAL_LOGV ) Log.v(TAG, "About to decrypt");
if (LOCAL_LOGV)
Log.v(TAG, "About to decrypt");
try {
Apg.decrypt(getBaseContext(), in, out, passphrase, null, // progress
pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null // symmetric
);
);
} catch (Exception e) {
Log.e(TAG, "Exception in decrypt");
String msg = e.getMessage();
@ -565,25 +606,33 @@ public class ApgService extends Service {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Cannot decrypt: " + msg);
pReturn.putInt(ret.ERROR.name(), error.NO_MATCHING_SECRET_KEY.shiftedOrdinal());
} else if (msg.equals(getBaseContext().getString(R.string.error_wrongPassPhrase))) {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Cannot decrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " wrong/missing): " + msg);
pReturn.putInt(ret.ERROR.name(), error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
pReturn.getStringArrayList(ret.ERRORS.name()).add(
"Cannot decrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name()
+ " wrong/missing): " + msg);
pReturn.putInt(ret.ERROR.name(),
error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
} else {
pReturn.getStringArrayList(ret.ERRORS.name()).add("Internal failure (" + e.getClass() + ") in APG when decrypting: " + msg);
pReturn.getStringArrayList(ret.ERRORS.name()).add(
"Internal failure (" + e.getClass() + ") in APG when decrypting: "
+ msg);
pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.shiftedOrdinal());
}
return false;
}
if( LOCAL_LOGV ) Log.v(TAG, "... decrypted");
if (LOCAL_LOGV)
Log.v(TAG, "... decrypted");
if(isBlob) {
if (isBlob) {
ContentResolver cr = getContentResolver();
try {
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
.name())));
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()),
outStream);
outStream.close();
} catch (Exception e) {
Log.e(TAG, "... exception on writing blob", e);
}
}
} else {
pReturn.putString(ret.RESULT.name(), out.toString());
}

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.apg.R;
import android.app.Activity;
import android.app.AlertDialog;
@ -38,7 +39,7 @@ public class AskForSecretKeyPassPhrase {
}
public static Dialog createDialog(Activity context, long secretKeyId,
PassPhraseCallbackInterface callback) {
PassPhraseCallbackInterface callback) {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(R.string.title_authentication);
@ -66,8 +67,8 @@ public class AskForSecretKeyPassPhrase {
alert.setMessage(context.getString(R.string.passPhraseFor, userId));
}
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.pass_phrase, null);
final EditText input = (EditText) view.findViewById(R.id.passPhrase);
final EditText inputNotUsed = (EditText) view.findViewById(R.id.passPhraseAgain);
@ -76,42 +77,38 @@ public class AskForSecretKeyPassPhrase {
alert.setView(view);
final PassPhraseCallbackInterface cb = callback;
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(Id.dialog.pass_phrase);
String passPhrase = "" + input.getText();
long keyId;
if (secretKey != null) {
try {
PGPPrivateKey testKey = secretKey.extractPrivateKey(passPhrase.toCharArray(),
new BouncyCastleProvider());
if (testKey == null) {
Toast.makeText(activity,
R.string.error_couldNotExtractPrivateKey,
Toast.LENGTH_SHORT).show();
return;
}
} catch (PGPException e) {
Toast.makeText(activity,
R.string.wrongPassPhrase,
Toast.LENGTH_SHORT).show();
return;
}
keyId = secretKey.getKeyID();
} else {
keyId = Id.key.symmetric;
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(Id.dialog.pass_phrase);
String passPhrase = "" + input.getText();
long keyId;
if (secretKey != null) {
try {
PGPPrivateKey testKey = secretKey.extractPrivateKey(
passPhrase.toCharArray(), new BouncyCastleProvider());
if (testKey == null) {
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
Toast.LENGTH_SHORT).show();
return;
}
cb.passPhraseCallback(keyId, passPhrase);
} catch (PGPException e) {
Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
.show();
return;
}
});
keyId = secretKey.getKeyID();
} else {
keyId = Id.key.symmetric;
}
cb.passPhraseCallback(keyId, passPhrase);
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(Id.dialog.pass_phrase);
}
});
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(Id.dialog.pass_phrase);
}
});
return alert.create();
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
public class CachedPassPhrase {
public final long timestamp;
@ -11,14 +11,14 @@ public class CachedPassPhrase {
}
@Override
public int hashCode() {
int hc1 = (int)(this.timestamp & 0xffffffff);
public int hashCode() {
int hc1 = (int) (this.timestamp & 0xffffffff);
int hc2 = (this.passPhrase == null ? 0 : this.passPhrase.hashCode());
return (hc1 + hc2) * hc2 + hc1;
}
@Override
public boolean equals(Object other) {
public boolean equals(Object other) {
if (!(other instanceof CachedPassPhrase)) {
return false;
}
@ -42,7 +42,7 @@ public class CachedPassPhrase {
}
@Override
public String toString() {
public String toString() {
return "(" + timestamp + ", *******)";
}
}

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
import android.os.Environment;
public final class Constants {
public static final String tag = "APG";
public static final class path {
public static final String app_dir = Environment.getExternalStorageDirectory() + "/APG";
}

View File

@ -0,0 +1,81 @@
package org.apg;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apg.Apg.GeneralException;
import org.apg.R;
import android.content.Context;
import android.os.Environment;
public class DataDestination {
private String mStreamFilename;
private String mFilename;
private int mMode = Id.mode.undefined;
public DataDestination() {
}
public void setMode(int mode) {
mMode = mode;
}
public void setFilename(String filename) {
mFilename = filename;
}
public String getStreamFilename() {
return mStreamFilename;
}
public OutputStream getOutputStream(Context context) throws Apg.GeneralException,
FileNotFoundException, IOException {
OutputStream out = null;
mStreamFilename = null;
switch (mMode) {
case Id.mode.stream: {
try {
while (true) {
mStreamFilename = Apg.generateRandomString(32);
if (mStreamFilename == null) {
throw new Apg.GeneralException("couldn't generate random file name");
}
context.openFileInput(mStreamFilename).close();
}
} catch (FileNotFoundException e) {
// found a name that isn't used yet
}
out = context.openFileOutput(mStreamFilename, Context.MODE_PRIVATE);
break;
}
case Id.mode.byte_array: {
out = new ByteArrayOutputStream();
break;
}
case Id.mode.file: {
if (mFilename.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new GeneralException(
context.getString(R.string.error_externalStorageNotReady));
}
}
out = new FileOutputStream(mFilename);
break;
}
default: {
break;
}
}
return out;
}
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import java.io.ByteArrayInputStream;
import java.io.File;
@ -7,7 +7,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.thialfihar.android.apg.Apg.GeneralException;
import org.apg.Apg.GeneralException;
import org.apg.R;
import android.content.Context;
import android.net.Uri;
@ -56,8 +57,8 @@ public class DataSource {
return mData != null || mContentUri != null;
}
public InputData getInputData(Context context, boolean withSize)
throws GeneralException, FileNotFoundException, IOException {
public InputData getInputData(Context context, boolean withSize) throws GeneralException,
FileNotFoundException, IOException {
InputStream in = null;
long size = 0;
@ -67,7 +68,8 @@ public class DataSource {
String path = Uri.decode(mContentUri.toString().substring(7));
if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new GeneralException(context.getString(R.string.error_externalStorageNotReady));
throw new GeneralException(
context.getString(R.string.error_externalStorageNotReady));
}
}
in = new FileInputStream(path);

View File

@ -14,7 +14,9 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
import org.apg.R;
import android.app.Activity;
import android.app.AlertDialog;
@ -41,18 +43,17 @@ public class FileDialog {
public static interface OnClickListener {
public void onCancelClick();
public void onOkClick(String filename, boolean checkbox);
}
public static AlertDialog build(Activity activity, String title, String message,
String defaultFile, OnClickListener onClickListener,
String fileManagerTitle, String fileManagerButton,
String checkboxText,
int requestCode) {
String defaultFile, OnClickListener onClickListener, String fileManagerTitle,
String fileManagerButton, String checkboxText, int requestCode) {
// TODO: fileManagerTitle and fileManagerButton are deprecated, no use for them right now,
// but maybe the Intent now used will someday support them again, so leaving them in
LayoutInflater inflater =
(LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle(title);
@ -87,22 +88,20 @@ public class FileDialog {
final OnClickListener clickListener = onClickListener;
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
boolean checked = false;
if (mCheckBox.isEnabled()) {
checked = mCheckBox.isChecked();
}
clickListener.onOkClick(mFilename.getText().toString(),
checked);
}
});
public void onClick(DialogInterface dialog, int id) {
boolean checked = false;
if (mCheckBox.isEnabled()) {
checked = mCheckBox.isChecked();
}
clickListener.onOkClick(mFilename.getText().toString(), checked);
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
clickListener.onCancelClick();
}
});
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
clickListener.onCancelClick();
}
});
return alert.create();
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -56,9 +56,15 @@ public class HkpKeyServer extends KeyServer {
private short mPort = 11371;
// example:
// pub 2048R/<a href="/pks/lookup?op=get&search=0x887DF4BE9F5C9090">9F5C9090</a> 2009-08-17 <a href="/pks/lookup?op=vindex&search=0x887DF4BE9F5C9090">Jörg Runge &lt;joerg@joergrunge.de&gt;</a>
public static Pattern PUB_KEY_LINE = Pattern.compile("pub +([0-9]+)([a-z]+)/.*?0x([0-9a-z]+).*? +([0-9-]+) +(.+)[\n\r]+((?: +.+[\n\r]+)*)", Pattern.CASE_INSENSITIVE);
public static Pattern USER_ID_LINE = Pattern.compile("^ +(.+)$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
// pub 2048R/<a href="/pks/lookup?op=get&search=0x887DF4BE9F5C9090">9F5C9090</a> 2009-08-17 <a
// href="/pks/lookup?op=vindex&search=0x887DF4BE9F5C9090">Jörg Runge
// &lt;joerg@joergrunge.de&gt;</a>
public static Pattern PUB_KEY_LINE = Pattern
.compile(
"pub +([0-9]+)([a-z]+)/.*?0x([0-9a-z]+).*? +([0-9-]+) +(.+)[\n\r]+((?: +.+[\n\r]+)*)",
Pattern.CASE_INSENSITIVE);
public static Pattern USER_ID_LINE = Pattern.compile("^ +(.+)$", Pattern.MULTILINE
| Pattern.CASE_INSENSITIVE);
public HkpKeyServer(String host) {
mHost = host;
@ -119,7 +125,8 @@ public class HkpKeyServer extends KeyServer {
// TODO: replace this with httpclient
@Override
List<KeyInfo> search(String query) throws QueryException, TooManyResponses, InsufficientQuery {
public List<KeyInfo> search(String query) throws QueryException, TooManyResponses,
InsufficientQuery {
Vector<KeyInfo> results = new Vector<KeyInfo>();
if (query.length() < 3) {
@ -160,7 +167,8 @@ public class HkpKeyServer extends KeyServer {
info.keyId = Apg.keyFromHex(matcher.group(3));
info.fingerPrint = Apg.getSmallFingerPrint(info.keyId);
String chunks[] = matcher.group(4).split("-");
info.date = new GregorianCalendar(Integer.parseInt(chunks[0]), Integer.parseInt(chunks[1]), Integer.parseInt(chunks[2])).getTime();
info.date = new GregorianCalendar(Integer.parseInt(chunks[0]),
Integer.parseInt(chunks[1]), Integer.parseInt(chunks[2])).getTime();
info.userIds = new Vector<String>();
if (matcher.group(5).startsWith("*** KEY")) {
info.revoked = matcher.group(5);
@ -184,16 +192,17 @@ public class HkpKeyServer extends KeyServer {
}
@Override
String get(long keyId) throws QueryException {
public String get(long keyId) throws QueryException {
HttpClient client = new DefaultHttpClient();
try {
HttpGet get = new HttpGet("http://" + mHost + ":" + mPort + "/pks/lookup?op=get&search=0x" + Apg.keyToHex(keyId));
HttpGet get = new HttpGet("http://" + mHost + ":" + mPort
+ "/pks/lookup?op=get&search=0x" + Apg.keyToHex(keyId));
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new QueryException("not found");
}
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
String data = readAll(is, EntityUtils.getContentCharSet(entity));
@ -206,7 +215,7 @@ public class HkpKeyServer extends KeyServer {
} finally {
client.getConnectionManager().shutdown();
}
return null;
}
@ -215,11 +224,11 @@ public class HkpKeyServer extends KeyServer {
HttpClient client = new DefaultHttpClient();
try {
HttpPost post = new HttpPost("http://" + mHost + ":" + mPort + "/pks/add");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("keytext", armouredText));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new AddKeyException();

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
interface IApgService {

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
public final class Id {
public static final String TAG = "APG";
public static final class menu {
public static final int export = 0x21070001;
public static final int delete = 0x21070002;

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import java.io.InputStream;
@ -6,7 +6,7 @@ public class InputData {
private PositionAwareInputStream mInputStream;
private long mSize;
InputData(InputStream inputStream, long size) {
public InputData(InputStream inputStream, long size) {
mInputStream = new PositionAwareInputStream(inputStream);
mSize = size;
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import java.io.Serializable;
import java.util.Date;
@ -8,35 +8,39 @@ import java.util.Vector;
public abstract class KeyServer {
static public class QueryException extends Exception {
private static final long serialVersionUID = 2703768928624654512L;
public QueryException(String message) {
super(message);
}
}
static public class TooManyResponses extends Exception {
private static final long serialVersionUID = 2703768928624654513L;
}
static public class InsufficientQuery extends Exception {
private static final long serialVersionUID = 2703768928624654514L;
}
static public class AddKeyException extends Exception {
private static final long serialVersionUID = -507574859137295530L;
}
static public class KeyInfo implements Serializable {
private static final long serialVersionUID = -7797972113284992662L;
Vector<String> userIds;
String revoked;
Date date;
String fingerPrint;
long keyId;
int size;
String algorithm;
public Vector<String> userIds;
public String revoked;
public Date date;
public String fingerPrint;
public long keyId;
public int size;
public String algorithm;
}
abstract List<KeyInfo> search(String query) throws QueryException, TooManyResponses, InsufficientQuery;
abstract List<KeyInfo> search(String query) throws QueryException, TooManyResponses,
InsufficientQuery;
abstract String get(long keyId) throws QueryException;
abstract void add(String armouredText) throws AddKeyException;
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
public class PausableThread extends Thread {
private boolean mPaused = false;
@ -22,8 +22,8 @@ public class PausableThread extends Thread {
public void unpause() {
synchronized (this) {
mPaused = false;
notify();
mPaused = false;
notify();
}
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import java.io.IOException;
import java.io.InputStream;

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
@ -15,17 +15,15 @@ public class Preferences {
public static synchronized Preferences getPreferences(Context context) {
return getPreferences(context, false);
}
public static synchronized Preferences getPreferences(Context context, boolean force_new)
{
public static synchronized Preferences getPreferences(Context context, boolean force_new) {
if (mPreferences == null || force_new) {
mPreferences = new Preferences(context);
}
return mPreferences;
}
private Preferences(Context context)
{
private Preferences(Context context) {
mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_PRIVATE);
}
@ -57,7 +55,7 @@ public class Preferences {
public int getDefaultEncryptionAlgorithm() {
return mSharedPreferences.getInt(Constants.pref.default_encryption_algorithm,
PGPEncryptedData.AES_256);
PGPEncryptedData.AES_256);
}
public void setDefaultEncryptionAlgorithm(int value) {
@ -68,7 +66,7 @@ public class Preferences {
public int getDefaultHashAlgorithm() {
return mSharedPreferences.getInt(Constants.pref.default_hash_algorithm,
HashAlgorithmTags.SHA256);
HashAlgorithmTags.SHA256);
}
public void setDefaultHashAlgorithm(int value) {
@ -79,7 +77,7 @@ public class Preferences {
public int getDefaultMessageCompression() {
return mSharedPreferences.getInt(Constants.pref.default_message_compression,
Id.choice.compression.zlib);
Id.choice.compression.zlib);
}
public void setDefaultMessageCompression(int value) {
@ -90,7 +88,7 @@ public class Preferences {
public int getDefaultFileCompression() {
return mSharedPreferences.getInt(Constants.pref.default_file_compression,
Id.choice.compression.none);
Id.choice.compression.none);
}
public void setDefaultFileCompression(int value) {
@ -120,8 +118,7 @@ public class Preferences {
}
public boolean hasSeenChangeLog(String version) {
return mSharedPreferences.getBoolean(Constants.pref.has_seen_change_log + version,
false);
return mSharedPreferences.getBoolean(Constants.pref.has_seen_change_log + version, false);
}
public void setHasSeenChangeLog(String version, boolean value) {
@ -142,7 +139,7 @@ public class Preferences {
public String[] getKeyServers() {
String rawData = mSharedPreferences.getString(Constants.pref.key_servers,
Constants.defaults.key_servers);
Constants.defaults.key_servers);
Vector<String> servers = new Vector<String>();
String chunks[] = rawData.split(",");
for (int i = 0; i < chunks.length; ++i) {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
import java.math.BigInteger;

View File

@ -14,10 +14,12 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
public interface ProgressDialogUpdater {
void setProgress(String message, int current, int total);
void setProgress(int resourceId, int current, int total);
void setProgress(int current, int total);
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
import android.content.Intent;
import android.os.Binder;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import android.provider.BaseColumns;

View File

@ -1,6 +1,6 @@
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import org.thialfihar.android.apg.ApgService;
import org.apg.ApgService;
import android.content.ContentUris;
import android.content.ContentValues;

View File

@ -1,7 +1,7 @@
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import org.thialfihar.android.apg.ApgService;
import org.thialfihar.android.apg.Constants;
import org.apg.ApgService;
import org.apg.Constants;
import android.content.ContentProvider;
import android.content.ContentValues;

View File

@ -14,13 +14,13 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import org.thialfihar.android.apg.Id;
import org.apg.Id;
import android.content.ContentProvider;
import android.content.ContentValues;

View File

@ -1,13 +1,13 @@
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import org.apg.Apg;
import org.apg.Id;
import org.apg.util.IterableIterator;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.utils.IterableIterator;
import android.content.ContentValues;
import android.content.Context;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import android.provider.BaseColumns;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import android.provider.BaseColumns;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.provider;
package org.apg.provider;
import android.provider.BaseColumns;

View File

@ -0,0 +1,461 @@
/*
* 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.apg.ui;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import org.apg.Apg;
import org.apg.AskForSecretKeyPassPhrase;
import org.apg.Constants;
import org.apg.Id;
import org.apg.PausableThread;
import org.apg.Preferences;
import org.apg.ProgressDialogUpdater;
import org.apg.Service;
import org.apg.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class BaseActivity extends Activity implements Runnable, ProgressDialogUpdater,
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
private ProgressDialog mProgressDialog = null;
private PausableThread mRunningThread = null;
private Thread mDeletingThread = null;
private long mSecretKeyId = 0;
private String mDeleteFile = null;
protected Preferences mPreferences;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
handlerCallback(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreferences = Preferences.getPreferences(this);
setLanguage(this, mPreferences.getLanguage());
Apg.initialize(this);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File dir = new File(Constants.path.app_dir);
if (!dir.exists() && !dir.mkdirs()) {
// ignore this for now, it's not crucial
// that the directory doesn't exist at this point
}
}
startCacheService(this, mPreferences);
}
public static void startCacheService(Activity activity, Preferences preferences) {
Intent intent = new Intent(activity, Service.class);
intent.putExtra(Service.EXTRA_TTL, preferences.getPassPhraseCacheTtl());
activity.startService(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences).setIcon(
android.R.drawable.ic_menu_preferences);
menu.add(0, Id.menu.option.about, 1, R.string.menu_about).setIcon(
android.R.drawable.ic_menu_info_details);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case Id.menu.option.about: {
showDialog(Id.dialog.about);
return true;
}
case Id.menu.option.preferences: {
startActivity(new Intent(this, PreferencesActivity.class));
return true;
}
case Id.menu.option.search: {
startSearch("", false, null, false);
return true;
}
default: {
break;
}
}
return false;
}
@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(this.getString(R.string.progress_initializing));
return mProgressDialog;
}
case Id.dialog.decrypting: {
mProgressDialog.setMessage(this.getString(R.string.progress_initializing));
return mProgressDialog;
}
case Id.dialog.saving: {
mProgressDialog.setMessage(this.getString(R.string.progress_saving));
return mProgressDialog;
}
case Id.dialog.importing: {
mProgressDialog.setMessage(this.getString(R.string.progress_importing));
return mProgressDialog;
}
case Id.dialog.exporting: {
mProgressDialog.setMessage(this.getString(R.string.progress_exporting));
return mProgressDialog;
}
case Id.dialog.deleting: {
mProgressDialog.setMessage(this.getString(R.string.progress_initializing));
return mProgressDialog;
}
case Id.dialog.querying: {
mProgressDialog.setMessage(this.getString(R.string.progress_querying));
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case Id.dialog.signing: {
mProgressDialog.setMessage(this.getString(R.string.progress_signing));
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
default: {
break;
}
}
mProgressDialog = null;
switch (id) {
case Id.dialog.about: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("About " + Apg.getFullVersion(this));
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.info, null);
TextView message = (TextView) layout.findViewById(R.id.message);
message.setText("This is an attempt to bring OpenPGP to Android. "
+ "It is far from complete, but more features are planned (see website).\n\n"
+ "Feel free to send bug reports, suggestions, feature requests, feedback, "
+ "photographs.\n\n" + "mail: thi@thialfihar.org\n"
+ "site: http://apg.thialfihar.org\n\n"
+ "This software is provided \"as is\", without warranty of any kind.");
alert.setView(layout);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
BaseActivity.this.removeDialog(Id.dialog.about);
}
});
return alert.create();
}
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(R.string.error);
alert.setMessage(R.string.passPhrasesDoNotMatch);
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(R.string.error);
alert.setMessage(R.string.passPhraseMustNotBeEmpty);
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();
}
case Id.dialog.delete_file: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning);
alert.setMessage(this.getString(R.string.fileDeleteConfirmation, getDeleteFile()));
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.delete_file);
final File file = new File(getDeleteFile());
showDialog(Id.dialog.deleting);
mDeletingThread = new Thread(new Runnable() {
public void run() {
Bundle data = new Bundle();
data.putInt(Constants.extras.status, Id.message.delete_done);
try {
Apg.deleteFileSecurely(BaseActivity.this, file, BaseActivity.this);
} catch (FileNotFoundException e) {
data.putString(Apg.EXTRA_ERROR, BaseActivity.this.getString(
R.string.error_fileNotFound, file));
} catch (IOException e) {
data.putString(Apg.EXTRA_ERROR, BaseActivity.this.getString(
R.string.error_fileDeleteFailed, file));
}
Message msg = new Message();
msg.setData(data);
sendMessage(msg);
}
});
mDeletingThread.start();
}
});
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.delete_file);
}
});
alert.setCancelable(true);
return alert.create();
}
default: {
break;
}
}
return super.onCreateDialog(id);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.secret_keys: {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
setSecretKeyId(bundle.getLong(Apg.EXTRA_KEY_ID));
} else {
setSecretKeyId(Id.key.none);
}
break;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
public void setProgress(int resourceId, int progress, int max) {
setProgress(getString(resourceId), progress, max);
}
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt(Constants.extras.status, Id.message.progress_update);
data.putInt(Constants.extras.progress, progress);
data.putInt(Constants.extras.progress_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(Constants.extras.status, Id.message.progress_update);
data.putString(Constants.extras.message, message);
data.putInt(Constants.extras.progress, progress);
data.putInt(Constants.extras.progress_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(Constants.extras.status);
switch (type) {
case Id.message.progress_update: {
String message = data.getString(Constants.extras.message);
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt(Constants.extras.progress_max));
mProgressDialog.setProgress(data.getInt(Constants.extras.progress));
}
break;
}
case Id.message.delete_done: {
mProgressDialog = null;
deleteDoneCallback(msg);
break;
}
case Id.message.import_done: // intentionally no break
case Id.message.export_done: // intentionally no break
case Id.message.query_done: // intentionally no break
case Id.message.done: {
mProgressDialog = null;
doneCallback(msg);
break;
}
default: {
break;
}
}
}
public void doneCallback(Message msg) {
}
public void deleteDoneCallback(Message msg) {
removeDialog(Id.dialog.deleting);
mDeletingThread = null;
Bundle data = msg.getData();
String error = data.getString(Apg.EXTRA_ERROR);
String message;
if (error != null) {
message = getString(R.string.errorMessage, error);
} else {
message = getString(R.string.fileDeleteSuccessful);
}
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
public void passPhraseCallback(long keyId, String passPhrase) {
Apg.setCachedPassPhrase(keyId, passPhrase);
}
public void sendMessage(Message msg) {
mHandler.sendMessage(msg);
}
public PausableThread getRunningThread() {
return mRunningThread;
}
public void startThread() {
mRunningThread = new PausableThread(this);
mRunningThread.start();
}
public void run() {
}
public void setSecretKeyId(long id) {
mSecretKeyId = id;
}
public long getSecretKeyId() {
return mSecretKeyId;
}
protected void setDeleteFile(String deleteFile) {
mDeleteFile = deleteFile;
}
protected String getDeleteFile() {
return mDeleteFile;
}
public static void setLanguage(Context context, String language) {
Locale locale;
if (language == null || language.equals("")) {
locale = Locale.getDefault();
} else {
locale = new Locale(language);
}
Configuration config = new Configuration();
config.locale = locale;
context.getResources().updateConfiguration(config,
context.getResources().getDisplayMetrics());
}
}

View File

@ -14,13 +14,22 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.DataDestination;
import org.apg.DataSource;
import org.apg.FileDialog;
import org.apg.Id;
import org.apg.InputData;
import org.apg.PausableThread;
import org.apg.provider.DataProvider;
import org.apg.util.Compatibility;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.thialfihar.android.apg.provider.DataProvider;
import org.thialfihar.android.apg.utils.Compatibility;
import org.apg.R;
import android.app.AlertDialog;
import android.app.Dialog;

View File

@ -14,15 +14,19 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.Id;
import org.apg.provider.Database;
import org.apg.ui.widget.KeyEditor;
import org.apg.ui.widget.SectionView;
import org.apg.util.IterableIterator;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.provider.Database;
import org.thialfihar.android.apg.ui.widget.KeyEditor;
import org.thialfihar.android.apg.ui.widget.SectionView;
import org.thialfihar.android.apg.utils.IterableIterator;
import org.apg.R;
import android.app.AlertDialog;
import android.app.Dialog;
@ -104,8 +108,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
mSaveButton.setOnClickListener(this);
mDiscardButton.setOnClickListener(this);
LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout container = (LinearLayout) findViewById(R.id.container);
mUserIds = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
@ -124,8 +127,9 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
updatePassPhraseButtonText();
Toast.makeText(this, getString(R.string.warningMessage, getString(R.string.keyEditingIsBeta)),
Toast.LENGTH_LONG).show();
Toast.makeText(this,
getString(R.string.warningMessage, getString(R.string.keyEditingIsBeta)),
Toast.LENGTH_LONG).show();
}
private long getMasterKeyId() {
@ -136,75 +140,72 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
}
public boolean havePassPhrase() {
return (!mCurrentPassPhrase.equals("")) ||
(mNewPassPhrase != null && !mNewPassPhrase.equals(""));
return (!mCurrentPassPhrase.equals(""))
|| (mNewPassPhrase != null && !mNewPassPhrase.equals(""));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences)
.setIcon(android.R.drawable.ic_menu_preferences);
menu.add(0, Id.menu.option.about, 1, R.string.menu_about)
.setIcon(android.R.drawable.ic_menu_info_details);
menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences).setIcon(
android.R.drawable.ic_menu_preferences);
menu.add(0, Id.menu.option.about, 1, R.string.menu_about).setIcon(
android.R.drawable.ic_menu_info_details);
return true;
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case Id.dialog.new_pass_phrase: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
case Id.dialog.new_pass_phrase: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
if (havePassPhrase()) {
alert.setTitle(R.string.title_changePassPhrase);
} else {
alert.setTitle(R.string.title_setPassPhrase);
if (havePassPhrase()) {
alert.setTitle(R.string.title_changePassPhrase);
} else {
alert.setTitle(R.string.title_setPassPhrase);
}
alert.setMessage(R.string.enterPassPhraseTwice);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.pass_phrase, null);
final EditText input1 = (EditText) view.findViewById(R.id.passPhrase);
final EditText input2 = (EditText) view.findViewById(R.id.passPhraseAgain);
alert.setView(view);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.new_pass_phrase);
String passPhrase1 = "" + input1.getText();
String passPhrase2 = "" + input2.getText();
if (!passPhrase1.equals(passPhrase2)) {
showDialog(Id.dialog.pass_phrases_do_not_match);
return;
}
if (passPhrase1.equals("")) {
showDialog(Id.dialog.no_pass_phrase);
return;
}
mNewPassPhrase = passPhrase1;
updatePassPhraseButtonText();
}
alert.setMessage(R.string.enterPassPhraseTwice);
});
LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.pass_phrase, null);
final EditText input1 = (EditText) view.findViewById(R.id.passPhrase);
final EditText input2 = (EditText) view.findViewById(R.id.passPhraseAgain);
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.new_pass_phrase);
}
});
alert.setView(view);
return alert.create();
}
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.new_pass_phrase);
String passPhrase1 = "" + input1.getText();
String passPhrase2 = "" + input2.getText();
if (!passPhrase1.equals(passPhrase2)) {
showDialog(Id.dialog.pass_phrases_do_not_match);
return;
}
if (passPhrase1.equals("")) {
showDialog(Id.dialog.no_pass_phrase);
return;
}
mNewPassPhrase = passPhrase1;
updatePassPhraseButtonText();
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.new_pass_phrase);
}
});
return alert.create();
}
default: {
return super.onCreateDialog(id);
}
default: {
return super.onCreateDialog(id);
}
}
}
@ -275,8 +276,8 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) {
Toast.makeText(EditKeyActivity.this,
getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show();
Toast.makeText(EditKeyActivity.this, getString(R.string.errorMessage, error),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(EditKeyActivity.this, R.string.keySaved, Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
@ -285,7 +286,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
}
private void updatePassPhraseButtonText() {
mChangePassPhrase.setText(
havePassPhrase() ? R.string.btn_changePassPhrase : R.string.btn_setPassPhrase);
mChangePassPhrase.setText(havePassPhrase() ? R.string.btn_changePassPhrase
: R.string.btn_setPassPhrase);
}
}

View File

@ -14,16 +14,24 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.DataDestination;
import org.apg.DataSource;
import org.apg.FileDialog;
import org.apg.Id;
import org.apg.InputData;
import org.apg.provider.DataProvider;
import org.apg.util.Choice;
import org.apg.util.Compatibility;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.provider.DataProvider;
import org.thialfihar.android.apg.utils.Choice;
import org.thialfihar.android.apg.utils.Compatibility;
import org.apg.R;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
@ -121,9 +129,9 @@ public class EncryptActivity extends BaseActivity {
mSourcePrevious.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mSource.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_right_in));
R.anim.push_right_in));
mSource.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_right_out));
R.anim.push_right_out));
mSource.showPrevious();
updateSource();
}
@ -133,9 +141,9 @@ public class EncryptActivity extends BaseActivity {
OnClickListener nextSourceClickListener = new OnClickListener() {
public void onClick(View v) {
mSource.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_left_in));
R.anim.push_left_in));
mSource.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_left_out));
R.anim.push_left_out));
mSource.showNext();
updateSource();
}
@ -154,9 +162,9 @@ public class EncryptActivity extends BaseActivity {
mModePrevious.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mMode.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_right_in));
R.anim.push_right_in));
mMode.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_right_out));
R.anim.push_right_out));
mMode.showPrevious();
updateMode();
}
@ -165,9 +173,9 @@ public class EncryptActivity extends BaseActivity {
OnClickListener nextModeClickListener = new OnClickListener() {
public void onClick(View v) {
mMode.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_left_in));
R.anim.push_left_in));
mMode.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
R.anim.push_left_out));
R.anim.push_left_out));
mMode.showNext();
updateMode();
}
@ -205,14 +213,14 @@ public class EncryptActivity extends BaseActivity {
mFileCompression = (Spinner) findViewById(R.id.fileCompression);
Choice[] choices = new Choice[] {
new Choice(Id.choice.compression.none, getString(R.string.choice_none) +
" (" + getString(R.string.fast) + ")"),
new Choice(Id.choice.compression.none, getString(R.string.choice_none) + " ("
+ getString(R.string.fast) + ")"),
new Choice(Id.choice.compression.zip, "ZIP (" + getString(R.string.fast) + ")"),
new Choice(Id.choice.compression.zlib, "ZLIB (" + getString(R.string.fast) + ")"),
new Choice(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.very_slow) + ")"),
};
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(this, android.R.layout.simple_spinner_item, choices);
new Choice(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.very_slow)
+ ")"), };
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(this,
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mFileCompression.setAdapter(adapter);
@ -265,18 +273,18 @@ public class EncryptActivity extends BaseActivity {
});
mIntent = getIntent();
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction()) ||
Apg.Intent.ENCRYPT_FILE.equals(mIntent.getAction()) ||
Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction()) ||
Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction())
|| Apg.Intent.ENCRYPT_FILE.equals(mIntent.getAction())
|| Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())
|| Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
mContentUri = mIntent.getData();
Bundle extras = mIntent.getExtras();
if (extras == null) {
extras = new Bundle();
}
if (Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction()) ||
Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
if (Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())
|| Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
mReturnResult = true;
}
@ -341,9 +349,9 @@ public class EncryptActivity extends BaseActivity {
}
}
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction()) ||
Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction()) ||
Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction())
|| Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())
|| Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
if (textData != null) {
mMessage.setText(textData);
}
@ -385,11 +393,9 @@ public class EncryptActivity extends BaseActivity {
updateButtons();
if (mReturnResult &&
(mMessage.getText().length() > 0 || mData != null || mContentUri != null) &&
((mEncryptionKeyIds != null &&
mEncryptionKeyIds.length > 0) ||
getSecretKeyId() != 0)) {
if (mReturnResult
&& (mMessage.getText().length() > 0 || mData != null || mContentUri != null)
&& ((mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) || getSecretKeyId() != 0)) {
encryptClicked();
}
}
@ -420,39 +426,69 @@ public class EncryptActivity extends BaseActivity {
private void updateSource() {
switch (mSource.getCurrentView().getId()) {
case R.id.sourceFile: {
mSourceLabel.setText(R.string.label_file);
break;
}
case R.id.sourceFile: {
mSourceLabel.setText(R.string.label_file);
break;
}
case R.id.sourceMessage: {
mSourceLabel.setText(R.string.label_message);
break;
}
case R.id.sourceMessage: {
mSourceLabel.setText(R.string.label_message);
break;
}
default: {
break;
}
default: {
break;
}
}
updateButtons();
}
private void updateButtons() {
switch (mSource.getCurrentView().getId()) {
case R.id.sourceFile: {
mEncryptToClipboardButton.setVisibility(View.INVISIBLE);
mEncryptButton.setText(R.string.btn_encrypt);
break;
}
case R.id.sourceFile: {
mEncryptToClipboardButton.setVisibility(View.INVISIBLE);
mEncryptButton.setText(R.string.btn_encrypt);
break;
}
case R.id.sourceMessage: {
mSourceLabel.setText(R.string.label_message);
case R.id.sourceMessage: {
mSourceLabel.setText(R.string.label_message);
if (mReturnResult) {
mEncryptToClipboardButton.setVisibility(View.INVISIBLE);
} else {
mEncryptToClipboardButton.setVisibility(View.VISIBLE);
}
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
if (mReturnResult) {
mEncryptToClipboardButton.setVisibility(View.INVISIBLE);
mEncryptButton.setText(R.string.btn_encrypt);
} else {
mEncryptToClipboardButton.setVisibility(View.VISIBLE);
mEncryptButton.setText(R.string.btn_encryptAndEmail);
}
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
mEncryptButton.setEnabled(true);
mEncryptToClipboardButton.setText(R.string.btn_encryptToClipboard);
mEncryptToClipboardButton.setEnabled(true);
} else {
if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) {
if (getSecretKeyId() == 0) {
if (mReturnResult) {
mEncryptButton.setText(R.string.btn_encrypt);
} else {
mEncryptButton.setText(R.string.btn_encryptAndEmail);
}
mEncryptButton.setEnabled(false);
mEncryptToClipboardButton.setText(R.string.btn_encryptToClipboard);
mEncryptToClipboardButton.setEnabled(false);
} else {
if (mReturnResult) {
mEncryptButton.setText(R.string.btn_sign);
} else {
mEncryptButton.setText(R.string.btn_signAndEmail);
}
mEncryptButton.setEnabled(true);
mEncryptToClipboardButton.setText(R.string.btn_signToClipboard);
mEncryptToClipboardButton.setEnabled(true);
}
} else {
if (mReturnResult) {
mEncryptButton.setText(R.string.btn_encrypt);
} else {
@ -461,62 +497,32 @@ public class EncryptActivity extends BaseActivity {
mEncryptButton.setEnabled(true);
mEncryptToClipboardButton.setText(R.string.btn_encryptToClipboard);
mEncryptToClipboardButton.setEnabled(true);
} else {
if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) {
if (getSecretKeyId() == 0) {
if (mReturnResult) {
mEncryptButton.setText(R.string.btn_encrypt);
} else {
mEncryptButton.setText(R.string.btn_encryptAndEmail);
}
mEncryptButton.setEnabled(false);
mEncryptToClipboardButton.setText(R.string.btn_encryptToClipboard);
mEncryptToClipboardButton.setEnabled(false);
} else {
if (mReturnResult) {
mEncryptButton.setText(R.string.btn_sign);
} else {
mEncryptButton.setText(R.string.btn_signAndEmail);
}
mEncryptButton.setEnabled(true);
mEncryptToClipboardButton.setText(R.string.btn_signToClipboard);
mEncryptToClipboardButton.setEnabled(true);
}
} else {
if (mReturnResult) {
mEncryptButton.setText(R.string.btn_encrypt);
} else {
mEncryptButton.setText(R.string.btn_encryptAndEmail);
}
mEncryptButton.setEnabled(true);
mEncryptToClipboardButton.setText(R.string.btn_encryptToClipboard);
mEncryptToClipboardButton.setEnabled(true);
}
}
break;
}
break;
}
default: {
break;
}
default: {
break;
}
}
}
private void updateMode() {
switch (mMode.getCurrentView().getId()) {
case R.id.modeAsymmetric: {
mModeLabel.setText(R.string.label_asymmetric);
break;
}
case R.id.modeAsymmetric: {
mModeLabel.setText(R.string.label_asymmetric);
break;
}
case R.id.modeSymmetric: {
mModeLabel.setText(R.string.label_symmetric);
break;
}
case R.id.modeSymmetric: {
mModeLabel.setText(R.string.label_symmetric);
break;
}
default: {
break;
}
default: {
break;
}
}
updateButtons();
}
@ -550,9 +556,10 @@ public class EncryptActivity extends BaseActivity {
if (!mInputFilename.startsWith("content")) {
File file = new File(mInputFilename);
if (!file.exists() || !file.isFile()) {
Toast.makeText(this, getString(R.string.errorMessage,
getString(R.string.error_fileNotFound)),
Toast.LENGTH_SHORT).show();
Toast.makeText(
this,
getString(R.string.errorMessage, getString(R.string.error_fileNotFound)),
Toast.LENGTH_SHORT).show();
return;
}
}
@ -582,8 +589,8 @@ public class EncryptActivity extends BaseActivity {
}
if (!encryptIt && getSecretKeyId() == 0) {
Toast.makeText(this, R.string.selectEncryptionOrSignatureKey,
Toast.LENGTH_SHORT).show();
Toast.makeText(this, R.string.selectEncryptionOrSignatureKey, Toast.LENGTH_SHORT)
.show();
return;
}
@ -666,55 +673,49 @@ public class EncryptActivity extends BaseActivity {
}
if (mGenerateSignature) {
Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(),
getSecretKeyId(),
Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(),
mPreferences.getForceV3Signatures(),
this);
Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(),
getSecretKeyId(), Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(),
mPreferences.getForceV3Signatures(), this);
} else if (signOnly) {
Apg.signText(this, in, out, getSecretKeyId(),
Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(),
mPreferences.getForceV3Signatures(),
this);
Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(),
mPreferences.getForceV3Signatures(), this);
} else {
Apg.encrypt(this, in, out, useAsciiArmour,
encryptionKeyIds, signatureKeyId,
Apg.getCachedPassPhrase(signatureKeyId), this,
mPreferences.getDefaultEncryptionAlgorithm(),
mPreferences.getDefaultHashAlgorithm(),
compressionId,
mPreferences.getForceV3Signatures(),
passPhrase);
Apg.encrypt(this, in, out, useAsciiArmour, encryptionKeyIds, signatureKeyId,
Apg.getCachedPassPhrase(signatureKeyId), this,
mPreferences.getDefaultEncryptionAlgorithm(),
mPreferences.getDefaultHashAlgorithm(), compressionId,
mPreferences.getForceV3Signatures(), passPhrase);
}
out.close();
if (mEncryptTarget != Id.target.file) {
if(out instanceof ByteArrayOutputStream) {
if (useAsciiArmour) {
String extraData = new String(((ByteArrayOutputStream)out).toByteArray());
if (mGenerateSignature) {
data.putString(Apg.EXTRA_SIGNATURE_TEXT, extraData);
} else {
data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE, extraData);
}
} else {
byte extraData[] = ((ByteArrayOutputStream)out).toByteArray();
if (mGenerateSignature) {
data.putByteArray(Apg.EXTRA_SIGNATURE_DATA, extraData);
} else {
data.putByteArray(Apg.EXTRA_ENCRYPTED_DATA, extraData);
}
}
} else if(out instanceof FileOutputStream) {
String fileName = mDataDestination.getStreamFilename();
String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName;
data.putString(Apg.EXTRA_RESULT_URI, uri);
} else {
throw new Apg.GeneralException("No output-data found.");
}
if (out instanceof ByteArrayOutputStream) {
if (useAsciiArmour) {
String extraData = new String(((ByteArrayOutputStream) out).toByteArray());
if (mGenerateSignature) {
data.putString(Apg.EXTRA_SIGNATURE_TEXT, extraData);
} else {
data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE, extraData);
}
} else {
byte extraData[] = ((ByteArrayOutputStream) out).toByteArray();
if (mGenerateSignature) {
data.putByteArray(Apg.EXTRA_SIGNATURE_DATA, extraData);
} else {
data.putByteArray(Apg.EXTRA_ENCRYPTED_DATA, extraData);
}
}
} else if (out instanceof FileOutputStream) {
String fileName = mDataDestination.getStreamFilename();
String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName;
data.putString(Apg.EXTRA_RESULT_URI, uri);
} else {
throw new Apg.GeneralException("No output-data found.");
}
}
} catch (IOException e) {
error = "" + e;
@ -746,8 +747,8 @@ public class EncryptActivity extends BaseActivity {
} else if (mEncryptionKeyIds.length == 1) {
mSelectKeysButton.setText(R.string.oneKeySelected);
} else {
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " " +
getResources().getString(R.string.nKeysSelected));
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " "
+ getResources().getString(R.string.nKeysSelected));
}
if (getSecretKeyId() == 0) {
@ -788,7 +789,7 @@ public class EncryptActivity extends BaseActivity {
keyIds.add(mEncryptionKeyIds[i]);
}
}
long [] initialKeyIds = null;
long[] initialKeyIds = null;
if (keyIds.size() > 0) {
initialKeyIds = new long[keyIds.size()];
for (int i = 0; i < keyIds.size(); ++i) {
@ -807,60 +808,60 @@ public class EncryptActivity extends BaseActivity {
@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);
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;
}
return;
}
case Id.request.output_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);
FileDialog.setFilename(filename);
case Id.request.output_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);
}
}
return;
}
// replace %20 and so on
filename = Uri.decode(filename);
case Id.request.secret_keys: {
if (resultCode == RESULT_OK) {
super.onActivityResult(requestCode, resultCode, data);
FileDialog.setFilename(filename);
}
updateView();
break;
}
return;
}
case Id.request.public_keys: {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
mEncryptionKeyIds = bundle.getLongArray(Apg.EXTRA_SELECTION);
}
updateView();
break;
case Id.request.secret_keys: {
if (resultCode == RESULT_OK) {
super.onActivityResult(requestCode, resultCode, data);
}
updateView();
break;
}
default: {
break;
case Id.request.public_keys: {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
mEncryptionKeyIds = bundle.getLongArray(Apg.EXTRA_SELECTION);
}
updateView();
break;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
@ -875,88 +876,82 @@ public class EncryptActivity extends BaseActivity {
Bundle data = msg.getData();
String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) {
Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show();
Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT)
.show();
return;
}
switch (mEncryptTarget) {
case Id.target.clipboard: {
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
Compatibility.copyToClipboard(this, message);
Toast.makeText(this, R.string.encryptionToClipboardSuccessful,
Toast.LENGTH_SHORT).show();
break;
case Id.target.clipboard: {
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
Compatibility.copyToClipboard(this, message);
Toast.makeText(this, R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT)
.show();
break;
}
case Id.target.email: {
if (mReturnResult) {
Intent intent = new Intent();
intent.putExtras(data);
setResult(RESULT_OK, intent);
finish();
return;
}
case Id.target.email: {
if (mReturnResult) {
Intent intent = new Intent();
intent.putExtras(data);
setResult(RESULT_OK, intent);
finish();
return;
}
String message = data.getString(Apg.EXTRA_ENCRYPTED_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 });
}
EncryptActivity.this.
startActivity(Intent.createChooser(emailIntent,
getString(R.string.title_sendEmail)));
break;
String message = data.getString(Apg.EXTRA_ENCRYPTED_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);
}
case Id.target.file: {
Toast.makeText(this, R.string.encryptionSuccessful, Toast.LENGTH_SHORT).show();
if (mDeleteAfter.isChecked()) {
setDeleteFile(mInputFilename);
showDialog(Id.dialog.delete_file);
}
break;
if (mSendTo != null) {
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { mSendTo });
}
EncryptActivity.this.startActivity(Intent.createChooser(emailIntent,
getString(R.string.title_sendEmail)));
break;
}
default: {
// shouldn't happen
break;
case Id.target.file: {
Toast.makeText(this, R.string.encryptionSuccessful, Toast.LENGTH_SHORT).show();
if (mDeleteAfter.isChecked()) {
setDeleteFile(mInputFilename);
showDialog(Id.dialog.delete_file);
}
break;
}
default: {
// shouldn't happen
break;
}
}
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case Id.dialog.output_filename: {
return FileDialog.build(this, getString(R.string.title_encryptToFile),
getString(R.string.specifyFileToEncryptTo),
mOutputFilename,
new FileDialog.OnClickListener() {
public void onOkClick(String filename, boolean checked) {
removeDialog(Id.dialog.output_filename);
mOutputFilename = filename;
encryptStart();
}
case Id.dialog.output_filename: {
return FileDialog.build(this, getString(R.string.title_encryptToFile),
getString(R.string.specifyFileToEncryptTo), mOutputFilename,
new FileDialog.OnClickListener() {
public void onOkClick(String filename, boolean checked) {
removeDialog(Id.dialog.output_filename);
mOutputFilename = filename;
encryptStart();
}
public void onCancelClick() {
removeDialog(Id.dialog.output_filename);
}
},
getString(R.string.filemanager_titleSave),
getString(R.string.filemanager_btnSave),
null,
Id.request.output_filename);
}
public void onCancelClick() {
removeDialog(Id.dialog.output_filename);
}
}, getString(R.string.filemanager_titleSave),
getString(R.string.filemanager_btnSave), null, Id.request.output_filename);
}
default: {
break;
}
default: {
break;
}
}
return super.onCreateDialog(id);

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg.ui;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
@ -6,7 +6,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import org.thialfihar.android.apg.utils.Choice;
import org.apg.Apg;
import org.apg.Id;
import org.apg.util.Choice;
import org.apg.R;
import android.content.Intent;
import android.net.Uri;

View File

@ -1,11 +1,16 @@
package org.thialfihar.android.apg;
package org.apg.ui;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.HkpKeyServer;
import org.apg.Id;
import org.apg.KeyServer.QueryException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.thialfihar.android.apg.KeyServer.QueryException;
import org.apg.R;
import android.content.Intent;
import android.os.Bundle;

View File

@ -14,14 +14,20 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.FileDialog;
import org.apg.Id;
import org.apg.InputData;
import org.apg.provider.KeyRings;
import org.apg.provider.Keys;
import org.apg.provider.UserIds;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.apg.R;
import android.app.AlertDialog;
import android.app.Dialog;

View File

@ -14,13 +14,15 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import java.util.Vector;
import org.thialfihar.android.apg.ui.widget.Editor;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.ui.widget.KeyServerEditor;
import org.apg.Apg;
import org.apg.ui.widget.Editor;
import org.apg.ui.widget.KeyServerEditor;
import org.apg.ui.widget.Editor.EditorListener;
import org.apg.R;
import android.content.Context;
import android.content.Intent;

View File

@ -1,12 +1,17 @@
package org.thialfihar.android.apg;
package org.apg.ui;
import java.util.List;
import java.util.Vector;
import org.thialfihar.android.apg.KeyServer.InsufficientQuery;
import org.thialfihar.android.apg.KeyServer.KeyInfo;
import org.thialfihar.android.apg.KeyServer.QueryException;
import org.thialfihar.android.apg.KeyServer.TooManyResponses;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.HkpKeyServer;
import org.apg.Id;
import org.apg.KeyServer.InsufficientQuery;
import org.apg.KeyServer.KeyInfo;
import org.apg.KeyServer.QueryException;
import org.apg.KeyServer.TooManyResponses;
import org.apg.R;
import android.app.Activity;
import android.app.Dialog;

View File

@ -14,11 +14,15 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import java.util.Vector;
import java.util.regex.Matcher;
import org.apg.Apg;
import org.apg.Preferences;
import org.apg.R;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;

View File

@ -14,14 +14,20 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import java.security.Security;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apg.Apg;
import org.apg.Id;
import org.apg.Id.dialog;
import org.apg.Id.menu;
import org.apg.Id.menu.option;
import org.apg.provider.Accounts;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.thialfihar.android.apg.provider.Accounts;
import org.apg.R;
import android.app.AlertDialog;
import android.app.Dialog;

View File

@ -14,11 +14,20 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.Id;
import org.apg.Preferences;
import org.apg.Constants.pref;
import org.apg.Id.choice;
import org.apg.Id.request;
import org.apg.Id.choice.compression;
import org.apg.ui.widget.IntegerListPreference;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.thialfihar.android.apg.ui.widget.IntegerListPreference;
import org.apg.R;
import android.content.Intent;
import android.os.Bundle;

View File

@ -14,9 +14,18 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.Id;
import org.apg.Constants.path;
import org.apg.Id.menu;
import org.apg.Id.request;
import org.apg.Id.type;
import org.apg.Id.menu.option;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.apg.R;
import android.content.Intent;
import android.os.Bundle;

View File

@ -14,7 +14,19 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.AskForSecretKeyPassPhrase;
import org.apg.Constants;
import org.apg.Id;
import org.apg.Constants.path;
import org.apg.Id.dialog;
import org.apg.Id.menu;
import org.apg.Id.message;
import org.apg.Id.type;
import org.apg.Id.menu.option;
import org.apg.R;
import android.app.Dialog;
import android.content.Intent;

View File

@ -14,10 +14,16 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import java.util.Vector;
import org.apg.Apg;
import org.apg.Id;
import org.apg.Id.menu;
import org.apg.Id.menu.option;
import org.apg.R;
import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;

View File

@ -14,13 +14,17 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import java.util.Date;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.apg.Apg;
import org.apg.Id;
import org.apg.Id.database;
import org.apg.provider.KeyRings;
import org.apg.provider.Keys;
import org.apg.provider.UserIds;
import org.apg.R;
import android.app.Activity;
import android.content.Context;

View File

@ -14,7 +14,13 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Id;
import org.apg.Id.menu;
import org.apg.Id.menu.option;
import org.apg.R;
import android.app.SearchManager;
import android.content.Intent;

View File

@ -1,10 +1,14 @@
package org.thialfihar.android.apg;
package org.apg.ui;
import java.util.Date;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.apg.Apg;
import org.apg.Id;
import org.apg.Id.database;
import org.apg.provider.KeyRings;
import org.apg.provider.Keys;
import org.apg.provider.UserIds;
import org.apg.R;
import android.app.Activity;
import android.content.Context;

View File

@ -1,7 +1,14 @@
package org.thialfihar.android.apg;
package org.apg.ui;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.HkpKeyServer;
import org.apg.Id;
import org.apg.Constants.extras;
import org.apg.Id.message;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.apg.R;
import android.os.Bundle;
import android.os.Message;

View File

@ -1,10 +1,19 @@
package org.thialfihar.android.apg;
package org.apg.ui;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.util.Iterator;
import org.apg.Apg;
import org.apg.Constants;
import org.apg.HkpKeyServer;
import org.apg.Id;
import org.apg.Constants.extras;
import org.apg.Id.dialog;
import org.apg.Id.message;
import org.apg.Id.request;
import org.apg.Id.return_value;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
@ -16,6 +25,7 @@ import org.spongycastle.openpgp.PGPSignatureGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.PGPUtil;
import org.apg.R;
import android.content.Intent;
import android.os.Bundle;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
package org.apg.ui.widget;
public interface Editor {
public interface EditorListener {

View File

@ -14,7 +14,7 @@
* the License.
*/
package org.thialfihar.android.apg.ui.widget;
package org.apg.ui.widget;
import android.content.Context;
import android.preference.ListPreference;

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
package org.apg.ui.widget;
import org.apg.Apg;
import org.apg.Id;
import org.apg.util.Choice;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.utils.Choice;
import org.apg.R;
import android.app.DatePickerDialog;
import android.app.Dialog;

View File

@ -14,9 +14,9 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
package org.apg.ui.widget;
import org.thialfihar.android.apg.R;
import org.apg.R;
import android.content.Context;
import android.util.AttributeSet;

View File

@ -14,15 +14,15 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
package org.apg.ui.widget;
import org.apg.Apg;
import org.apg.Id;
import org.apg.ui.widget.Editor.EditorListener;
import org.apg.util.Choice;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.utils.Choice;
import org.apg.R;
import android.app.AlertDialog;
import android.app.ProgressDialog;

View File

@ -14,12 +14,12 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
package org.apg.ui.widget;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.thialfihar.android.apg.R;
import org.apg.R;
import android.content.Context;
import android.util.AttributeSet;

View File

@ -14,10 +14,10 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.utils;
package org.apg.util;
import org.thialfihar.android.apg.IApgService;
import org.thialfihar.android.apg.utils.ApgConInterface.OnCallFinishListener;
import org.apg.util.ApgConInterface.OnCallFinishListener;
import org.apg.IApgService;
import android.content.ComponentName;
import android.content.ContentResolver;

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg.utils;
package org.apg.util;
public interface ApgConInterface {
public static interface OnCallFinishListener {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.utils;
package org.apg.util;
public class Choice {
private String mName;

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg.utils;
package org.apg.util;
import java.lang.reflect.Method;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.thialfihar.android.apg.utils;
package org.apg.util;
import java.util.Iterator;

View File

@ -1,464 +0,0 @@
/*
* 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.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class BaseActivity extends Activity
implements Runnable, ProgressDialogUpdater,
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
private ProgressDialog mProgressDialog = null;
private PausableThread mRunningThread = null;
private Thread mDeletingThread = null;
private long mSecretKeyId = 0;
private String mDeleteFile = null;
protected Preferences mPreferences;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
handlerCallback(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreferences = Preferences.getPreferences(this);
setLanguage(this, mPreferences.getLanguage());
Apg.initialize(this);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File dir = new File(Constants.path.app_dir);
if (!dir.exists() && !dir.mkdirs()) {
// ignore this for now, it's not crucial
// that the directory doesn't exist at this point
}
}
startCacheService(this, mPreferences);
}
public static void startCacheService(Activity activity, Preferences preferences) {
Intent intent = new Intent(activity, Service.class);
intent.putExtra(Service.EXTRA_TTL, preferences.getPassPhraseCacheTtl());
activity.startService(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences)
.setIcon(android.R.drawable.ic_menu_preferences);
menu.add(0, Id.menu.option.about, 1, R.string.menu_about)
.setIcon(android.R.drawable.ic_menu_info_details);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case Id.menu.option.about: {
showDialog(Id.dialog.about);
return true;
}
case Id.menu.option.preferences: {
startActivity(new Intent(this, PreferencesActivity.class));
return true;
}
case Id.menu.option.search: {
startSearch("", false, null, false);
return true;
}
default: {
break;
}
}
return false;
}
@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(this.getString(R.string.progress_initializing));
return mProgressDialog;
}
case Id.dialog.decrypting: {
mProgressDialog.setMessage(this.getString(R.string.progress_initializing));
return mProgressDialog;
}
case Id.dialog.saving: {
mProgressDialog.setMessage(this.getString(R.string.progress_saving));
return mProgressDialog;
}
case Id.dialog.importing: {
mProgressDialog.setMessage(this.getString(R.string.progress_importing));
return mProgressDialog;
}
case Id.dialog.exporting: {
mProgressDialog.setMessage(this.getString(R.string.progress_exporting));
return mProgressDialog;
}
case Id.dialog.deleting: {
mProgressDialog.setMessage(this.getString(R.string.progress_initializing));
return mProgressDialog;
}
case Id.dialog.querying: {
mProgressDialog.setMessage(this.getString(R.string.progress_querying));
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
case Id.dialog.signing: {
mProgressDialog.setMessage(this.getString(R.string.progress_signing));
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
default: {
break;
}
}
mProgressDialog = null;
switch (id) {
case Id.dialog.about: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("About " + Apg.getFullVersion(this));
LayoutInflater inflater =
(LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.info, null);
TextView message = (TextView) layout.findViewById(R.id.message);
message.setText("This is an attempt to bring OpenPGP to Android. " +
"It is far from complete, but more features are planned (see website).\n\n" +
"Feel free to send bug reports, suggestions, feature requests, feedback, " +
"photographs.\n\n" +
"mail: thi@thialfihar.org\n" +
"site: http://apg.thialfihar.org\n\n" +
"This software is provided \"as is\", without warranty of any kind.");
alert.setView(layout);
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
BaseActivity.this.removeDialog(Id.dialog.about);
}
});
return alert.create();
}
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(R.string.error);
alert.setMessage(R.string.passPhrasesDoNotMatch);
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(R.string.error);
alert.setMessage(R.string.passPhraseMustNotBeEmpty);
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();
}
case Id.dialog.delete_file: {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning);
alert.setMessage(this.getString(R.string.fileDeleteConfirmation, getDeleteFile()));
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.delete_file);
final File file = new File(getDeleteFile());
showDialog(Id.dialog.deleting);
mDeletingThread = new Thread(new Runnable() {
public void run() {
Bundle data = new Bundle();
data.putInt(Constants.extras.status, Id.message.delete_done);
try {
Apg.deleteFileSecurely(BaseActivity.this, file, BaseActivity.this);
} catch (FileNotFoundException e) {
data.putString(Apg.EXTRA_ERROR,
BaseActivity.this.getString(
R.string.error_fileNotFound, file));
} catch (IOException e) {
data.putString(Apg.EXTRA_ERROR,
BaseActivity.this.getString(
R.string.error_fileDeleteFailed, file));
}
Message msg = new Message();
msg.setData(data);
sendMessage(msg);
}
});
mDeletingThread.start();
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.delete_file);
}
});
alert.setCancelable(true);
return alert.create();
}
default: {
break;
}
}
return super.onCreateDialog(id);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.secret_keys: {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
setSecretKeyId(bundle.getLong(Apg.EXTRA_KEY_ID));
} else {
setSecretKeyId(Id.key.none);
}
break;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
public void setProgress(int resourceId, int progress, int max) {
setProgress(getString(resourceId), progress, max);
}
public void setProgress(int progress, int max) {
Message msg = new Message();
Bundle data = new Bundle();
data.putInt(Constants.extras.status, Id.message.progress_update);
data.putInt(Constants.extras.progress, progress);
data.putInt(Constants.extras.progress_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(Constants.extras.status, Id.message.progress_update);
data.putString(Constants.extras.message, message);
data.putInt(Constants.extras.progress, progress);
data.putInt(Constants.extras.progress_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(Constants.extras.status);
switch (type) {
case Id.message.progress_update: {
String message = data.getString(Constants.extras.message);
if (mProgressDialog != null) {
if (message != null) {
mProgressDialog.setMessage(message);
}
mProgressDialog.setMax(data.getInt(Constants.extras.progress_max));
mProgressDialog.setProgress(data.getInt(Constants.extras.progress));
}
break;
}
case Id.message.delete_done: {
mProgressDialog = null;
deleteDoneCallback(msg);
break;
}
case Id.message.import_done: // intentionally no break
case Id.message.export_done: // intentionally no break
case Id.message.query_done: // intentionally no break
case Id.message.done: {
mProgressDialog = null;
doneCallback(msg);
break;
}
default: {
break;
}
}
}
public void doneCallback(Message msg) {
}
public void deleteDoneCallback(Message msg) {
removeDialog(Id.dialog.deleting);
mDeletingThread = null;
Bundle data = msg.getData();
String error = data.getString(Apg.EXTRA_ERROR);
String message;
if (error != null) {
message = getString(R.string.errorMessage, error);
} else {
message = getString(R.string.fileDeleteSuccessful);
}
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
public void passPhraseCallback(long keyId, String passPhrase) {
Apg.setCachedPassPhrase(keyId, passPhrase);
}
public void sendMessage(Message msg) {
mHandler.sendMessage(msg);
}
public PausableThread getRunningThread() {
return mRunningThread;
}
public void startThread() {
mRunningThread = new PausableThread(this);
mRunningThread.start();
}
public void run() {
}
public void setSecretKeyId(long id) {
mSecretKeyId = id;
}
public long getSecretKeyId() {
return mSecretKeyId;
}
protected void setDeleteFile(String deleteFile) {
mDeleteFile = deleteFile;
}
protected String getDeleteFile() {
return mDeleteFile;
}
public static void setLanguage(Context context, String language)
{
Locale locale;
if (language == null || language.equals(""))
{
locale = Locale.getDefault();
}
else
{
locale = new Locale(language);
}
Configuration config = new Configuration();
config.locale = locale;
context.getResources().updateConfiguration(config,
context.getResources().getDisplayMetrics());
}
}

View File

@ -1,79 +0,0 @@
package org.thialfihar.android.apg;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.thialfihar.android.apg.Apg.GeneralException;
import android.content.Context;
import android.os.Environment;
public class DataDestination {
private String mStreamFilename;
private String mFilename;
private int mMode = Id.mode.undefined;
public DataDestination() {
}
public void setMode(int mode) {
mMode = mode;
}
public void setFilename(String filename) {
mFilename = filename;
}
public String getStreamFilename() {
return mStreamFilename;
}
protected OutputStream getOutputStream(Context context)
throws Apg.GeneralException, FileNotFoundException, IOException {
OutputStream out = null;
mStreamFilename = null;
switch (mMode) {
case Id.mode.stream: {
try {
while (true) {
mStreamFilename = Apg.generateRandomString(32);
if (mStreamFilename == null) {
throw new Apg.GeneralException("couldn't generate random file name");
}
context.openFileInput(mStreamFilename).close();
}
} catch (FileNotFoundException e) {
// found a name that isn't used yet
}
out = context.openFileOutput(mStreamFilename, Context.MODE_PRIVATE);
break;
}
case Id.mode.byte_array: {
out = new ByteArrayOutputStream();
break;
}
case Id.mode.file: {
if (mFilename.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new GeneralException(context.getString(R.string.error_externalStorageNotReady));
}
}
out = new FileOutputStream(mFilename);
break;
}
default: {
break;
}
}
return out;
}
}