mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
renaming whole package to org.apg to simplifiy name
This commit is contained in:
parent
df6933bfb8
commit
8452fb62b7
@ -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
202
COPYING
Normal 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.
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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();
|
@ -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);
|
@ -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);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
public class CachedPassPhrase {
|
||||
public final long timestamp;
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
import android.os.Environment;
|
||||
|
81
src/org/apg/DataDestination.java
Normal file
81
src/org/apg/DataDestination.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
@ -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();
|
||||
}
|
@ -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 <joerg@joergrunge.de></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
|
||||
// <joerg@joergrunge.de></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) {
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
interface IApgService {
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
public class PausableThread extends Thread {
|
||||
private boolean mPaused = false;
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
@ -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) {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
@ -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);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg;
|
||||
package org.apg;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.provider;
|
||||
package org.apg.provider;
|
||||
|
||||
import android.provider.BaseColumns;
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.provider;
|
||||
package org.apg.provider;
|
||||
|
||||
import android.provider.BaseColumns;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.provider;
|
||||
package org.apg.provider;
|
||||
|
||||
import android.provider.BaseColumns;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.provider;
|
||||
package org.apg.provider;
|
||||
|
||||
import android.provider.BaseColumns;
|
||||
|
461
src/org/apg/ui/BaseActivity.java
Normal file
461
src/org/apg/ui/BaseActivity.java
Normal 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());
|
||||
}
|
||||
}
|
@ -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;
|
@ -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);
|
||||
}
|
||||
}
|
@ -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: {
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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 {
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg.utils;
|
||||
package org.apg.util;
|
||||
|
||||
public interface ApgConInterface {
|
||||
public static interface OnCallFinishListener {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.utils;
|
||||
package org.apg.util;
|
||||
|
||||
public class Choice {
|
||||
private String mName;
|
@ -1,4 +1,4 @@
|
||||
package org.thialfihar.android.apg.utils;
|
||||
package org.apg.util;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.utils;
|
||||
package org.apg.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user