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>

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>

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 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 xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/hint_secretKeys"
android:label="@string/app_name" >
</searchable>

View File

@ -14,8 +14,19 @@
* limitations under the License.
*/
package org.thialfihar.android.apg;
package org.apg;
import org.apg.KeyServer.AddKeyException;
import org.apg.provider.DataProvider;
import org.apg.provider.Database;
import org.apg.provider.KeyRings;
import org.apg.provider.Keys;
import org.apg.provider.UserIds;
import org.apg.ui.BaseActivity;
import org.apg.ui.widget.KeyEditor;
import org.apg.ui.widget.SectionView;
import org.apg.ui.widget.UserIdEditor;
import org.apg.util.IterableIterator;
import org.spongycastle.bcpg.ArmoredInputStream;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.BCPGOutputStream;
@ -53,16 +64,7 @@ import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.openpgp.PGPV3SignatureGenerator;
import org.thialfihar.android.apg.KeyServer.AddKeyException;
import org.thialfihar.android.apg.provider.DataProvider;
import org.thialfihar.android.apg.provider.Database;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.thialfihar.android.apg.ui.widget.KeyEditor;
import org.thialfihar.android.apg.ui.widget.SectionView;
import org.thialfihar.android.apg.ui.widget.UserIdEditor;
import org.thialfihar.android.apg.utils.IterableIterator;
import org.apg.R;
import android.app.Activity;
import android.content.Context;
@ -155,54 +157,45 @@ public class Apg {
public static final String AUTHORITY = DataProvider.AUTHORITY;
public static final Uri CONTENT_URI_SECRET_KEY_RINGS =
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/");
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID =
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/key_id/");
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS =
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/emails/");
public static final Uri CONTENT_URI_SECRET_KEY_RINGS = Uri.parse("content://" + AUTHORITY
+ "/key_rings/secret/");
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://"
+ AUTHORITY + "/key_rings/secret/key_id/");
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://"
+ AUTHORITY + "/key_rings/secret/emails/");
public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS =
Uri.parse("content://" + AUTHORITY + "/key_rings/public/");
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID =
Uri.parse("content://" + AUTHORITY + "/key_rings/public/key_id/");
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS =
Uri.parse("content://" + AUTHORITY + "/key_rings/public/emails/");
public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS = Uri.parse("content://" + AUTHORITY
+ "/key_rings/public/");
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://"
+ AUTHORITY + "/key_rings/public/key_id/");
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://"
+ AUTHORITY + "/key_rings/public/emails/");
private static String VERSION = null;
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS =
new int[] {
SymmetricKeyAlgorithmTags.AES_256,
SymmetricKeyAlgorithmTags.AES_192,
SymmetricKeyAlgorithmTags.AES_128,
SymmetricKeyAlgorithmTags.CAST5,
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[] {
SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192,
SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5,
SymmetricKeyAlgorithmTags.TRIPLE_DES };
private static final int[] PREFERRED_HASH_ALGORITHMS =
new int[] {
HashAlgorithmTags.SHA1,
HashAlgorithmTags.SHA256,
HashAlgorithmTags.RIPEMD160 };
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS =
new int[] {
CompressionAlgorithmTags.ZLIB,
CompressionAlgorithmTags.BZIP2,
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[] { HashAlgorithmTags.SHA1,
HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160 };
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[] {
CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2,
CompressionAlgorithmTags.ZIP };
public static Pattern PGP_MESSAGE =
Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
public static Pattern PGP_MESSAGE = Pattern.compile(
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
public static Pattern PGP_SIGNED_MESSAGE = Pattern
.compile(
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
Pattern.DOTALL);
public static Pattern PGP_SIGNED_MESSAGE =
Pattern.compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
public static Pattern PGP_PUBLIC_KEY = Pattern.compile(
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
Pattern.DOTALL);
public static Pattern PGP_PUBLIC_KEY =
Pattern.compile(".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
Pattern.DOTALL);
private static HashMap<Long, CachedPassPhrase> mPassPhraseCache =
new HashMap<Long, CachedPassPhrase>();
private static HashMap<Long, CachedPassPhrase> mPassPhraseCache = new HashMap<Long, CachedPassPhrase>();
private static String mEditPassPhrase = null;
private static Database mDatabase = null;
@ -293,11 +286,10 @@ public class Apg {
return delay;
}
public static PGPSecretKey createKey(Context context,
int algorithmChoice, int keySize, String passPhrase,
PGPSecretKey masterKey)
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
GeneralException, InvalidAlgorithmParameterException {
public static PGPSecretKey createKey(Context context, int algorithmChoice, int keySize,
String passPhrase, PGPSecretKey masterKey) throws NoSuchAlgorithmException,
PGPException, NoSuchProviderException, GeneralException,
InvalidAlgorithmParameterException {
if (keySize < 512) {
throw new GeneralException(context.getString(R.string.error_keySizeMinimum512bit));
@ -322,7 +314,8 @@ public class Apg {
case Id.choice.algorithm.elgamal: {
if (masterKey == null) {
throw new GeneralException(context.getString(R.string.error_masterKeyMustNotBeElGamal));
throw new GeneralException(
context.getString(R.string.error_masterKeyMustNotBeElGamal));
}
keyGen = KeyPairGenerator.getInstance("ELGAMAL", new BouncyCastleProvider());
BigInteger p = Primes.getBestPrime(keySize);
@ -354,27 +347,21 @@ public class Apg {
if (masterKey == null) {
// enough for now, as we assemble the key again later anyway
secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, "",
PGPEncryptedData.CAST5, passPhrase.toCharArray(),
null, null,
PGPEncryptedData.CAST5, passPhrase.toCharArray(), null, null,
new SecureRandom(), new BouncyCastleProvider().getName());
} else {
PGPPublicKey tmpKey = masterKey.getPublicKey();
PGPPublicKey masterPublicKey =
new PGPPublicKey(tmpKey.getAlgorithm(),
tmpKey.getKey(new BouncyCastleProvider()),
tmpKey.getCreationTime());
PGPPrivateKey masterPrivateKey =
masterKey.extractPrivateKey(passPhrase.toCharArray(),
PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(passPhrase.toCharArray(),
new BouncyCastleProvider());
PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
PGPKeyRingGenerator ringGen =
new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
masterKeyPair, "",
PGPEncryptedData.CAST5, passPhrase.toCharArray(),
null, null,
new SecureRandom(), new BouncyCastleProvider().getName());
PGPKeyRingGenerator ringGen = new PGPKeyRingGenerator(
PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair, "", PGPEncryptedData.CAST5,
passPhrase.toCharArray(), null, null, new SecureRandom(),
new BouncyCastleProvider().getName());
ringGen.addSubKey(keyPair);
PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing();
Iterator<PGPSecretKey> it = secKeyRing.getSecretKeys();
@ -398,12 +385,11 @@ public class Apg {
return numDays;
}
public static void buildSecretKey(Activity context,
SectionView userIdsView, SectionView keysView,
String oldPassPhrase, String newPassPhrase,
ProgressDialogUpdater progress)
throws Apg.GeneralException, NoSuchProviderException, PGPException,
NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException {
public static void buildSecretKey(Activity context, SectionView userIdsView,
SectionView keysView, String oldPassPhrase, String newPassPhrase,
ProgressDialogUpdater progress) throws Apg.GeneralException, NoSuchProviderException,
PGPException, NoSuchAlgorithmException, SignatureException, IOException,
Database.GeneralException {
if (progress != null)
progress.setProgress(R.string.progress_buildingKey, 0, 100);
@ -433,7 +419,8 @@ public class Apg {
} catch (UserIdEditor.NoNameException e) {
throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName));
} catch (UserIdEditor.NoEmailException e) {
throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAnEmailAddress));
throw new Apg.GeneralException(
context.getString(R.string.error_userIdNeedsAnEmailAddress));
} catch (UserIdEditor.InvalidEmailException e) {
throw new Apg.GeneralException("" + e);
}
@ -455,7 +442,8 @@ public class Apg {
}
if (!gotMainUserId) {
throw new Apg.GeneralException(context.getString(R.string.error_mainUserIdMustNotBeEmpty));
throw new Apg.GeneralException(
context.getString(R.string.error_mainUserIdMustNotBeEmpty));
}
if (keyEditors.getChildCount() == 0) {
@ -471,21 +459,16 @@ public class Apg {
progress.setProgress(R.string.progress_preparingMasterKey, 10, 100);
KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0);
int usageId = keyEditor.getUsage();
boolean canSign = (usageId == Id.choice.usage.sign_only ||
usageId == Id.choice.usage.sign_and_encrypt);
boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only ||
usageId == Id.choice.usage.sign_and_encrypt);
boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
String mainUserId = userIds.get(0);
PGPSecretKey masterKey = keys.get(0);
PGPPublicKey tmpKey = masterKey.getPublicKey();
PGPPublicKey masterPublicKey =
new PGPPublicKey(tmpKey.getAlgorithm(),
tmpKey.getKey(new BouncyCastleProvider()),
tmpKey.getCreationTime());
PGPPrivateKey masterPrivateKey =
masterKey.extractPrivateKey(oldPassPhrase.toCharArray(),
PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(oldPassPhrase.toCharArray(),
new BouncyCastleProvider());
if (progress != null)
@ -493,8 +476,7 @@ public class Apg {
for (int i = 0; i < userIds.size(); ++i) {
String userId = userIds.get(i);
PGPSignatureGenerator sGen =
new PGPSignatureGenerator(masterPublicKey.getAlgorithm(),
PGPSignatureGenerator sGen = new PGPSignatureGenerator(masterPublicKey.getAlgorithm(),
HashAlgorithmTags.SHA1, new BouncyCastleProvider());
sGen.initSign(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
@ -528,19 +510,18 @@ public class Apg {
GregorianCalendar expiryDate = keyEditor.getExpiryDate();
long numDays = getNumDaysBetween(creationDate, expiryDate);
if (numDays <= 0) {
throw new GeneralException(context.getString(R.string.error_expiryMustComeAfterCreation));
throw new GeneralException(
context.getString(R.string.error_expiryMustComeAfterCreation));
}
hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
}
if (progress != null)
progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100);
PGPKeyRingGenerator keyGen =
new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
masterKeyPair, mainUserId,
PGPEncryptedData.CAST5, newPassPhrase.toCharArray(),
hashedPacketsGen.generate(), unhashedPacketsGen.generate(),
new SecureRandom(), new BouncyCastleProvider().getName());
PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
masterKeyPair, mainUserId, PGPEncryptedData.CAST5, newPassPhrase.toCharArray(),
hashedPacketsGen.generate(), unhashedPacketsGen.generate(), new SecureRandom(),
new BouncyCastleProvider().getName());
if (progress != null)
progress.setProgress(R.string.progress_addingSubKeys, 40, 100);
@ -550,13 +531,10 @@ public class Apg {
PGPSecretKey subKey = keys.get(i);
keyEditor = (KeyEditor) keyEditors.getChildAt(i);
PGPPublicKey subPublicKey = subKey.getPublicKey();
PGPPrivateKey subPrivateKey =
subKey.extractPrivateKey(oldPassPhrase.toCharArray(),
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(oldPassPhrase.toCharArray(),
new BouncyCastleProvider());
PGPKeyPair subKeyPair =
new PGPKeyPair(subPublicKey.getAlgorithm(),
subPublicKey.getKey(new BouncyCastleProvider()),
subPrivateKey.getKey(),
PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey.getAlgorithm(),
subPublicKey.getKey(new BouncyCastleProvider()), subPrivateKey.getKey(),
subPublicKey.getCreationTime());
hashedPacketsGen = new PGPSignatureSubpacketGenerator();
@ -564,10 +542,8 @@ public class Apg {
keyFlags = 0;
usageId = keyEditor.getUsage();
canSign = (usageId == Id.choice.usage.sign_only ||
usageId == Id.choice.usage.sign_and_encrypt);
canEncrypt = (usageId == Id.choice.usage.encrypt_only ||
usageId == Id.choice.usage.sign_and_encrypt);
canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
if (canSign) {
keyFlags |= KeyFlags.SIGN_DATA;
}
@ -583,13 +559,13 @@ public class Apg {
GregorianCalendar expiryDate = keyEditor.getExpiryDate();
long numDays = getNumDaysBetween(creationDate, expiryDate);
if (numDays <= 0) {
throw new GeneralException(context.getString(R.string.error_expiryMustComeAfterCreation));
throw new GeneralException(
context.getString(R.string.error_expiryMustComeAfterCreation));
}
hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
}
keyGen.addSubKey(subKeyPair,
hashedPacketsGen.generate(), unhashedPacketsGen.generate());
keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
}
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
@ -623,9 +599,11 @@ public class Apg {
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
boolean save = true;
try {
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(new char[] {}, new BouncyCastleProvider());
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(
new char[] {}, new BouncyCastleProvider());
if (testKey == null) {
// this is bad, something is very wrong... likely a --export-secret-subkeys export
// this is bad, something is very wrong... likely a --export-secret-subkeys
// export
save = false;
status = Id.return_value.bad;
}
@ -673,10 +651,9 @@ public class Apg {
}
}
public static Bundle importKeyRings(Activity context, int type,
InputData data,
ProgressDialogUpdater progress)
throws GeneralException, FileNotFoundException, PGPException, IOException {
public static Bundle importKeyRings(Activity context, int type, InputData data,
ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException,
PGPException, IOException {
Bundle returnData = new Bundle();
if (type == Id.type.secret_key) {
@ -705,8 +682,8 @@ public class Apg {
int status = Integer.MIN_VALUE; // out of bounds value
// if this key is what we expect it to be, save it
if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing) ||
(type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) {
if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing)
|| (type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) {
status = storeKeyRingInCache(keyring);
}
@ -746,9 +723,8 @@ public class Apg {
}
public static Bundle exportKeyRings(Activity context, Vector<Integer> keyRingIds,
OutputStream outStream,
ProgressDialogUpdater progress)
throws GeneralException, FileNotFoundException, PGPException, IOException {
OutputStream outStream, ProgressDialogUpdater progress) throws GeneralException,
FileNotFoundException, PGPException, IOException {
Bundle returnData = new Bundle();
if (keyRingIds.size() == 1) {
@ -878,8 +854,8 @@ public class Apg {
Date creationDate = getCreationDate(key);
Date expiryDate = getExpiryDate(key);
Date now = new Date();
if (now.compareTo(creationDate) >= 0 &&
(expiryDate == null || now.compareTo(expiryDate) <= 0)) {
if (now.compareTo(creationDate) >= 0
&& (expiryDate == null || now.compareTo(expiryDate) <= 0)) {
return false;
}
return true;
@ -1007,15 +983,15 @@ public class Apg {
}
PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
if (hashed != null &&(hashed.getKeyFlags() &
(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
if (hashed != null
&& (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
return true;
}
PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
if (unhashed != null &&(unhashed.getKeyFlags() &
(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
if (unhashed != null
&& (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
return true;
}
}
@ -1209,10 +1185,8 @@ public class Apg {
public static Vector<Integer> getKeyRingIds(int type) {
SQLiteDatabase db = mDatabase.db();
Vector<Integer> keyIds = new Vector<Integer>();
Cursor c = db.query(KeyRings.TABLE_NAME,
new String[] { KeyRings._ID },
KeyRings.TYPE + " = ?", new String[] { "" + type },
null, null, null);
Cursor c = db.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, KeyRings.TYPE
+ " = ?", new String[] { "" + type }, null, null, null);
if (c != null && c.moveToFirst()) {
do {
keyIds.add(c.getInt(0));
@ -1228,25 +1202,16 @@ public class Apg {
public static String getMainUserId(long keyId, int type) {
SQLiteDatabase db = mDatabase.db();
Cursor c = db.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON (" +
KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " +
Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + ") " +
" INNER JOIN " + Keys.TABLE_NAME + " AS masterKey ON (" +
KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " +
"masterKey." + Keys.KEY_RING_ID + " AND " +
"masterKey." + Keys.IS_MASTER_KEY + " = '1') " +
" INNER JOIN " + UserIds.TABLE_NAME + " ON (" +
UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " = " +
"masterKey." + Keys._ID + " AND " +
UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0')",
new String[] { UserIds.USER_ID },
Keys.TABLE_NAME + "." + Keys.KEY_ID + " = ? AND " +
KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?",
new String[] {
"" + keyId,
"" + type,
},
null, null, null);
Cursor c = db.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON ("
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
+ Keys.KEY_RING_ID + ") " + " INNER JOIN " + Keys.TABLE_NAME + " AS masterKey ON ("
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + "masterKey."
+ Keys.KEY_RING_ID + " AND " + "masterKey." + Keys.IS_MASTER_KEY + " = '1') "
+ " INNER JOIN " + UserIds.TABLE_NAME + " ON (" + UserIds.TABLE_NAME + "."
+ UserIds.KEY_ID + " = " + "masterKey." + Keys._ID + " AND " + UserIds.TABLE_NAME
+ "." + UserIds.RANK + " = '0')", new String[] { UserIds.USER_ID }, Keys.TABLE_NAME
+ "." + Keys.KEY_ID + " = ? AND " + KeyRings.TABLE_NAME + "." + KeyRings.TYPE
+ " = ?", new String[] { "" + keyId, "" + type, }, null, null, null);
String userId = "";
if (c != null && c.moveToFirst()) {
do {
@ -1261,15 +1226,10 @@ public class Apg {
return userId;
}
public static void encrypt(Context context,
InputData data, OutputStream outStream,
boolean armored,
long encryptionKeyIds[], long signatureKeyId,
String signaturePassPhrase,
ProgressDialogUpdater progress,
int symmetricAlgorithm, int hashAlgorithm, int compression,
boolean forceV3Signature,
String passPhrase)
public static void encrypt(Context context, InputData data, OutputStream outStream,
boolean armored, long encryptionKeyIds[], long signatureKeyId,
String signaturePassPhrase, ProgressDialogUpdater progress, int symmetricAlgorithm,
int hashAlgorithm, int compression, boolean forceV3Signature, String passPhrase)
throws IOException, GeneralException, PGPException, NoSuchProviderException,
NoSuchAlgorithmException, SignatureException {
Security.addProvider(new BouncyCastleProvider());
@ -1293,7 +1253,8 @@ public class Apg {
PGPPrivateKey signaturePrivateKey = null;
if (encryptionKeyIds.length == 0 && passPhrase == null) {
throw new GeneralException(context.getString(R.string.error_noEncryptionKeysOrPassPhrase));
throw new GeneralException(
context.getString(R.string.error_noEncryptionKeysOrPassPhrase));
}
if (signatureKeyId != 0) {
@ -1311,16 +1272,16 @@ public class Apg {
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
new BouncyCastleProvider());
if (signaturePrivateKey == null) {
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
throw new GeneralException(
context.getString(R.string.error_couldNotExtractPrivateKey));
}
}
if (progress != null)
progress.setProgress(R.string.progress_preparingStreams, 5, 100);
// encrypt and compress input file content
PGPEncryptedDataGenerator cPk =
new PGPEncryptedDataGenerator(symmetricAlgorithm, true, new SecureRandom(),
new BouncyCastleProvider());
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(symmetricAlgorithm, true,
new SecureRandom(), new BouncyCastleProvider());
if (encryptionKeyIds.length == 0) {
// symmetric encryption
@ -1341,16 +1302,12 @@ public class Apg {
if (progress != null)
progress.setProgress(R.string.progress_preparingSignature, 10, 100);
if (forceV3Signature) {
signatureV3Generator =
new PGPV3SignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
hashAlgorithm,
new BouncyCastleProvider());
signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey()
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
signatureV3Generator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
} else {
signatureGenerator =
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
hashAlgorithm,
new BouncyCastleProvider());
signatureGenerator = new PGPSignatureGenerator(signingKey.getPublicKey()
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
signatureGenerator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
String userId = getMainUserId(getMasterKey(signingKeyRing));
@ -1378,8 +1335,8 @@ public class Apg {
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
// file name not needed, so empty string
OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "",
new Date(), new byte[1 << 16]);
OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
new byte[1 << 16]);
if (progress != null)
progress.setProgress(R.string.progress_encrypting, 20, 100);
@ -1426,14 +1383,10 @@ public class Apg {
progress.setProgress(R.string.progress_done, 100, 100);
}
public static void signText(Context context,
InputData data, OutputStream outStream,
long signatureKeyId, String signaturePassPhrase,
int hashAlgorithm,
boolean forceV3Signature,
ProgressDialogUpdater progress)
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
SignatureException {
public static void signText(Context context, InputData data, OutputStream outStream,
long signatureKeyId, String signaturePassPhrase, int hashAlgorithm,
boolean forceV3Signature, ProgressDialogUpdater progress) throws GeneralException,
PGPException, IOException, NoSuchAlgorithmException, SignatureException {
Security.addProvider(new BouncyCastleProvider());
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
@ -1456,8 +1409,7 @@ public class Apg {
if (signaturePassPhrase == null) {
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
}
signaturePrivateKey =
signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
new BouncyCastleProvider());
if (signaturePrivateKey == null) {
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
@ -1472,15 +1424,13 @@ public class Apg {
PGPV3SignatureGenerator signatureV3Generator = null;
if (forceV3Signature) {
signatureV3Generator =
new PGPV3SignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
hashAlgorithm,
new BouncyCastleProvider());
signatureV3Generator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey()
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
signatureV3Generator
.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
} else {
signatureGenerator =
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
hashAlgorithm,
signatureGenerator = new PGPSignatureGenerator(
signingKey.getPublicKey().getAlgorithm(), hashAlgorithm,
new BouncyCastleProvider());
signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
@ -1538,13 +1488,9 @@ public class Apg {
progress.setProgress(R.string.progress_done, 100, 100);
}
public static void generateSignature(Context context,
InputData data, OutputStream outStream,
boolean armored, boolean binary,
long signatureKeyId, String signaturePassPhrase,
int hashAlgorithm,
boolean forceV3Signature,
ProgressDialogUpdater progress)
public static void generateSignature(Context context, InputData data, OutputStream outStream,
boolean armored, boolean binary, long signatureKeyId, String signaturePassPhrase,
int hashAlgorithm, boolean forceV3Signature, ProgressDialogUpdater progress)
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
SignatureException {
Security.addProvider(new BouncyCastleProvider());
@ -1576,8 +1522,7 @@ public class Apg {
if (signaturePassPhrase == null) {
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
}
signaturePrivateKey =
signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
new BouncyCastleProvider());
if (signaturePrivateKey == null) {
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
@ -1597,15 +1542,12 @@ public class Apg {
}
if (forceV3Signature) {
signatureV3Generator =
new PGPV3SignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
hashAlgorithm,
new BouncyCastleProvider());
signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey()
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
signatureV3Generator.initSign(type, signaturePrivateKey);
} else {
signatureGenerator =
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
hashAlgorithm,
signatureGenerator = new PGPSignatureGenerator(
signingKey.getPublicKey().getAlgorithm(), hashAlgorithm,
new BouncyCastleProvider());
signatureGenerator.initSign(type, signaturePrivateKey);
@ -1663,8 +1605,8 @@ public class Apg {
progress.setProgress(R.string.progress_done, 100, 100);
}
public static long getDecryptionKeyId(Context context, InputData data)
throws GeneralException, NoAsymmetricEncryptionException, IOException {
public static long getDecryptionKeyId(Context context, InputData data) throws GeneralException,
NoAsymmetricEncryptionException, IOException {
InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
@ -1738,10 +1680,8 @@ public class Apg {
return false;
}
public static Bundle decrypt(Context context,
InputData data, OutputStream outStream,
String passPhrase, ProgressDialogUpdater progress,
boolean assumeSymmetric)
public static Bundle decrypt(Context context, InputData data, OutputStream outStream,
String passPhrase, ProgressDialogUpdater progress, boolean assumeSymmetric)
throws IOException, GeneralException, PGPException, SignatureException {
if (passPhrase == null) {
passPhrase = "";
@ -1787,7 +1727,8 @@ public class Apg {
}
if (pbe == null) {
throw new GeneralException(context.getString(R.string.error_noSymmetricEncryptionPacket));
throw new GeneralException(
context.getString(R.string.error_noSymmetricEncryptionPacket));
}
if (progress != null)
@ -1829,7 +1770,8 @@ public class Apg {
throw new PGPException(context.getString(R.string.error_wrongPassPhrase));
}
if (privateKey == null) {
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
throw new GeneralException(
context.getString(R.string.error_couldNotExtractPrivateKey));
}
currentProgress += 5;
if (progress != null)
@ -1848,8 +1790,8 @@ public class Apg {
if (dataChunk instanceof PGPCompressedData) {
if (progress != null)
progress.setProgress(R.string.progress_decompressingData, currentProgress, 100);
PGPObjectFactory fact =
new PGPObjectFactory(((PGPCompressedData) dataChunk).getDataStream());
PGPObjectFactory fact = new PGPObjectFactory(
((PGPCompressedData) dataChunk).getDataStream());
dataChunk = fact.nextObject();
plainFact = fact;
currentProgress += 10;
@ -1928,12 +1870,13 @@ public class Apg {
}
}
// unknown size, but try to at least have a moving, slowing down progress bar
currentProgress = startProgress + (endProgress - startProgress) * done / (done + 100000);
currentProgress = startProgress + (endProgress - startProgress) * done
/ (done + 100000);
if (data.getSize() - startPos == 0) {
currentProgress = endProgress;
} else {
currentProgress = (int)(startProgress + (endProgress - startProgress) *
(data.getStreamPosition() - startPos) / (data.getSize() - startPos));
currentProgress = (int) (startProgress + (endProgress - startProgress)
* (data.getStreamPosition() - startPos) / (data.getSize() - startPos));
}
if (progress != null)
progress.setProgress(currentProgress, 100);
@ -1970,10 +1913,9 @@ public class Apg {
return returnData;
}
public static Bundle verifyText(BaseActivity context,
InputData data, OutputStream outStream,
ProgressDialogUpdater progress)
throws IOException, GeneralException, PGPException, SignatureException {
public static Bundle verifyText(BaseActivity context, InputData data, OutputStream outStream,
ProgressDialogUpdater progress) throws IOException, GeneralException, PGPException,
SignatureException {
Bundle returnData = new Bundle();
ByteArrayOutputStream out = new ByteArrayOutputStream();
@ -2074,8 +2016,7 @@ public class Apg {
signature.update((byte) '\n');
processLine(signature, lineOut.toByteArray());
}
while (lookAhead != -1);
} while (lookAhead != -1);
}
returnData.putBoolean(EXTRA_SIGNATURE_SUCCESS, signature.verify());
@ -2085,14 +2026,12 @@ public class Apg {
return returnData;
}
public static int getStreamContent(Context context, InputStream inStream)
throws IOException {
public static int getStreamContent(Context context, InputStream inStream) throws IOException {
InputStream in = PGPUtil.getDecoderStream(inStream);
PGPObjectFactory pgpF = new PGPObjectFactory(in);
Object object = pgpF.nextObject();
while (object != null) {
if (object instanceof PGPPublicKeyRing ||
object instanceof PGPSecretKeyRing) {
if (object instanceof PGPPublicKeyRing || object instanceof PGPSecretKeyRing) {
return Id.content.keys;
} else if (object instanceof PGPEncryptedDataList) {
return Id.content.encrypted_data;
@ -2103,10 +2042,8 @@ public class Apg {
return Id.content.unknown;
}
private static void processLine(final String pLine,
final ArmoredOutputStream pArmoredOutput,
final PGPSignatureGenerator pSignatureGenerator)
throws IOException, SignatureException {
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException {
if (pLine == null) {
return;
@ -2130,10 +2067,9 @@ public class Apg {
pSignatureGenerator.update(data);
}
private static void processLine(final String pLine,
final ArmoredOutputStream pArmoredOutput,
final PGPV3SignatureGenerator pSignatureGenerator)
throws IOException, SignatureException {
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
final PGPV3SignatureGenerator pSignatureGenerator) throws IOException,
SignatureException {
if (pLine == null) {
return;
@ -2158,8 +2094,8 @@ public class Apg {
}
// taken from ClearSignedFileProcessor in BC
private static void processLine(PGPSignature sig, byte[] line)
throws SignatureException, IOException {
private static void processLine(PGPSignature sig, byte[] line) throws SignatureException,
IOException {
int length = getLengthWithoutWhiteSpace(line);
if (length > 0) {
sig.update(line, 0, length);
@ -2196,8 +2132,7 @@ public class Apg {
lookAhead = readPassedEOL(bOut, ch, fIn);
break;
}
}
while ((ch = fIn.read()) >= 0);
} while ((ch = fIn.read()) >= 0);
if (ch < 0) {
lookAhead = -1;
@ -2292,12 +2227,9 @@ public class Apg {
public static String generateRandomString(int length) {
SecureRandom random = new SecureRandom();
/*
try {
random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider());
} catch (NoSuchAlgorithmException e) {
// TODO: need to handle this case somehow
return null;
}*/
* try { random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider()); } catch
* (NoSuchAlgorithmException e) { // TODO: need to handle this case somehow return null; }
*/
byte bytes[] = new byte[length];
random.nextBytes(bytes);
String result = "";
@ -2328,7 +2260,7 @@ public class Apg {
return size;
}
static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress)
public static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress)
throws FileNotFoundException, IOException {
long length = file.length();
SecureRandom random = new SecureRandom();

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,17 +32,14 @@ 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;
@ -49,10 +47,7 @@ public class ApgService extends Service {
}
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,11 +134,16 @@ 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());
}
@ -159,22 +159,24 @@ public class ApgService extends Service {
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);
}
/**
@ -202,35 +204,38 @@ public class ApgService extends Service {
* 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,17 +336,19 @@ 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");
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());
@ -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
@ -456,22 +483,33 @@ public class ApgService extends Service {
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 (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));
}
@ -536,7 +575,8 @@ public class ApgService extends Service {
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;
@ -553,7 +593,8 @@ public class ApgService extends Service {
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
@ -565,21 +606,29 @@ 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) {
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);

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;
@ -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,26 +77,23 @@ public class AskForSecretKeyPassPhrase {
alert.setView(view);
final PassPhraseCallbackInterface cb = callback;
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(Id.dialog.pass_phrase);
String passPhrase = "" + input.getText();
long keyId;
if (secretKey != null) {
try {
PGPPrivateKey testKey = secretKey.extractPrivateKey(passPhrase.toCharArray(),
new BouncyCastleProvider());
PGPPrivateKey testKey = secretKey.extractPrivateKey(
passPhrase.toCharArray(), new BouncyCastleProvider());
if (testKey == null) {
Toast.makeText(activity,
R.string.error_couldNotExtractPrivateKey,
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();
Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
.show();
return;
}
keyId = secretKey.getKeyID();
@ -106,8 +104,7 @@ public class AskForSecretKeyPassPhrase {
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
activity.removeDialog(Id.dialog.pass_phrase);
}

View File

@ -1,4 +1,4 @@
package org.thialfihar.android.apg;
package org.apg;
public class CachedPassPhrase {
public final long timestamp;

View File

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

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);
@ -92,13 +93,11 @@ public class FileDialog {
if (mCheckBox.isEnabled()) {
checked = mCheckBox.isChecked();
}
clickListener.onOkClick(mFilename.getText().toString(),
checked);
clickListener.onOkClick(mFilename.getText().toString(), checked);
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
clickListener.onCancelClick();
}

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,10 +192,11 @@ 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) {

View File

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

View File

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

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,6 +8,7 @@ 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);
}
@ -27,16 +28,19 @@ public abstract class KeyServer {
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;

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;
@ -16,16 +16,14 @@ public class Preferences {
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);
}
@ -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) {

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,7 +127,8 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
updatePassPhraseButtonText();
Toast.makeText(this, getString(R.string.warningMessage, getString(R.string.keyEditingIsBeta)),
Toast.makeText(this,
getString(R.string.warningMessage, getString(R.string.keyEditingIsBeta)),
Toast.LENGTH_LONG).show();
}
@ -136,16 +140,16 @@ 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;
}
@ -162,16 +166,14 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
}
alert.setMessage(R.string.enterPassPhraseTwice);
LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
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() {
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.new_pass_phrase);
@ -192,8 +194,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
}
});
alert.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.new_pass_phrase);
}
@ -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;
@ -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();
}
}
@ -550,8 +556,9 @@ 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.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;
}
@ -667,26 +674,20 @@ public class EncryptActivity extends BaseActivity {
if (mGenerateSignature) {
Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(),
getSecretKeyId(),
Apg.getCachedPassPhrase(getSecretKeyId()),
getSecretKeyId(), Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(),
mPreferences.getForceV3Signatures(),
this);
mPreferences.getForceV3Signatures(), this);
} else if (signOnly) {
Apg.signText(this, in, out, getSecretKeyId(),
Apg.getCachedPassPhrase(getSecretKeyId()),
mPreferences.getDefaultHashAlgorithm(),
mPreferences.getForceV3Signatures(),
this);
mPreferences.getForceV3Signatures(), this);
} else {
Apg.encrypt(this, in, out, useAsciiArmour,
encryptionKeyIds, signatureKeyId,
Apg.encrypt(this, in, out, useAsciiArmour, encryptionKeyIds, signatureKeyId,
Apg.getCachedPassPhrase(signatureKeyId), this,
mPreferences.getDefaultEncryptionAlgorithm(),
mPreferences.getDefaultHashAlgorithm(),
compressionId,
mPreferences.getForceV3Signatures(),
passPhrase);
mPreferences.getDefaultHashAlgorithm(), compressionId,
mPreferences.getForceV3Signatures(), passPhrase);
}
out.close();
@ -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) {
@ -875,15 +876,16 @@ 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();
Toast.makeText(this, R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT)
.show();
break;
}
@ -901,15 +903,12 @@ public class EncryptActivity extends BaseActivity {
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);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mSubject);
}
if (mSendTo != null) {
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
new String[] { mSendTo });
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { mSendTo });
}
EncryptActivity.this.
startActivity(Intent.createChooser(emailIntent,
EncryptActivity.this.startActivity(Intent.createChooser(emailIntent,
getString(R.string.title_sendEmail)));
break;
}
@ -935,8 +934,7 @@ public class EncryptActivity extends BaseActivity {
switch (id) {
case Id.dialog.output_filename: {
return FileDialog.build(this, getString(R.string.title_encryptToFile),
getString(R.string.specifyFileToEncryptTo),
mOutputFilename,
getString(R.string.specifyFileToEncryptTo), mOutputFilename,
new FileDialog.OnClickListener() {
public void onOkClick(String filename, boolean checked) {
removeDialog(Id.dialog.output_filename);
@ -947,11 +945,8 @@ public class EncryptActivity extends BaseActivity {
public void onCancelClick() {
removeDialog(Id.dialog.output_filename);
}
},
getString(R.string.filemanager_titleSave),
getString(R.string.filemanager_btnSave),
null,
Id.request.output_filename);
}, getString(R.string.filemanager_titleSave),
getString(R.string.filemanager_btnSave), null, Id.request.output_filename);
}
default: {

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;
}
}