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>
|
File diff suppressed because it is too large
Load Diff
@ -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());
|
||||
}
|
||||
@ -152,29 +152,31 @@ public class ApgService extends Service {
|
||||
private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException {
|
||||
byte[] buffer = new byte[8];
|
||||
int len = 0;
|
||||
while( (len = is.read(buffer)) != -1) {
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static Cursor getKeyEntries(HashMap<String, Object> pParams) {
|
||||
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME
|
||||
+ "." + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME
|
||||
+ " ON " + "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "."
|
||||
+ UserIds.RANK + " = '0') ");
|
||||
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
|
||||
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
|
||||
+ Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
|
||||
+ " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
|
||||
+ Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
|
||||
+ UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') ");
|
||||
|
||||
String orderBy = pParams.containsKey("order_by") ? (String) pParams.get("order_by") : UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC";
|
||||
String orderBy = pParams.containsKey("order_by") ? (String) pParams.get("order_by")
|
||||
: UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC";
|
||||
|
||||
String typeVal[] = null;
|
||||
String typeWhere = null;
|
||||
if (pParams.containsKey("key_type")) {
|
||||
typeWhere = KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?";
|
||||
typeVal = new String[] {
|
||||
"" + pParams.get("key_type")
|
||||
};
|
||||
typeVal = new String[] { "" + pParams.get("key_type") };
|
||||
}
|
||||
return qb.query(Apg.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere, typeVal, null, null, orderBy);
|
||||
return qb.query(Apg.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere,
|
||||
typeVal, null, null, orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -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");
|
||||
if (!pArgs.containsKey(arg.MESSAGE.name()) && !pArgs.containsKey(arg.BLOB.name())) {
|
||||
pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||
"Arguments missing: Neither MESSAGE nor BLOG found");
|
||||
}
|
||||
|
||||
}
|
||||
@ -363,7 +381,8 @@ public class ApgService extends Service {
|
||||
try {
|
||||
arg curArg = arg.valueOf(curKey);
|
||||
if (!allArgs.contains(curArg)) {
|
||||
pReturn.getStringArrayList(ret.WARNINGS.name()).add("Unknown argument: " + curKey);
|
||||
pReturn.getStringArrayList(ret.WARNINGS.name()).add(
|
||||
"Unknown argument: " + curKey);
|
||||
unknownArgs.add(curKey);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -386,23 +405,28 @@ public class ApgService extends Service {
|
||||
|
||||
/* add default arguments if missing */
|
||||
addDefaultArguments(pCall, pArgs);
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "add_default_arguments");
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "add_default_arguments");
|
||||
|
||||
/* check for required arguments */
|
||||
checkForRequiredArgs(pCall, pArgs, pReturn);
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "check_required_args");
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "check_required_args");
|
||||
|
||||
/* check for unknown arguments and add to warning if found */
|
||||
checkForUnknownArgs(pCall, pArgs, pReturn);
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "check_unknown_args");
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "check_unknown_args");
|
||||
|
||||
/* return if errors happened */
|
||||
if (pReturn.getStringArrayList(ret.ERRORS.name()).size() != 0) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "Errors after preparing, not executing "+pCall);
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "Errors after preparing, not executing " + pCall);
|
||||
pReturn.putInt(ret.ERROR.name(), error.ARGUMENTS_MISSING.shiftedOrdinal());
|
||||
return false;
|
||||
}
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "error return");
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "error return");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -414,7 +438,8 @@ public class ApgService extends Service {
|
||||
if (pArgs.containsKey(arg.PUBLIC_KEYS.name())) {
|
||||
ArrayList<String> list = pArgs.getStringArrayList(arg.PUBLIC_KEYS.name());
|
||||
ArrayList<String> pubKeys = new ArrayList<String>();
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "Long size: " + list.size());
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "Long size: " + list.size());
|
||||
Iterator<String> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
pubKeys.add(iter.next());
|
||||
@ -423,7 +448,7 @@ public class ApgService extends Service {
|
||||
}
|
||||
|
||||
InputStream inStream = null;
|
||||
if(isBlob) {
|
||||
if (isBlob) {
|
||||
ContentResolver cr = getContentResolver();
|
||||
try {
|
||||
inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
||||
@ -436,14 +461,16 @@ public class ApgService extends Service {
|
||||
InputData in = new InputData(inStream, 0); // XXX Size second param?
|
||||
|
||||
OutputStream out = new ByteArrayOutputStream();
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "About to encrypt");
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "About to encrypt");
|
||||
try {
|
||||
Apg.encrypt(getBaseContext(), // context
|
||||
in, // input stream
|
||||
out, // output stream
|
||||
pArgs.getBoolean(arg.ARMORED_OUTPUT.name()), // ARMORED_OUTPUT
|
||||
pubMasterKeys, // encryption keys
|
||||
getMasterKey(pArgs.getString(arg.SIGNATURE_KEY.name()), pReturn), // signature key
|
||||
getMasterKey(pArgs.getString(arg.SIGNATURE_KEY.name()), pReturn), // signature
|
||||
// key
|
||||
pArgs.getString(arg.PRIVATE_KEY_PASSPHRASE.name()), // signature passphrase
|
||||
null, // progress
|
||||
pArgs.getInt(arg.ENCRYPTION_ALGORYTHM.name()), // encryption
|
||||
@ -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(isBlob) {
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "Encrypted");
|
||||
if (isBlob) {
|
||||
ContentResolver cr = getContentResolver();
|
||||
try {
|
||||
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
||||
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
|
||||
.name())));
|
||||
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
|
||||
outStream.close();
|
||||
} catch (Exception e) {
|
||||
@ -501,7 +539,8 @@ public class ApgService extends Service {
|
||||
ArrayList<String> fPrints = new ArrayList<String>();
|
||||
ArrayList<String> ids = new ArrayList<String>();
|
||||
while (cursor.moveToNext()) {
|
||||
if( LOCAL_LOGV ) Log.v(TAG, "adding key "+Apg.getSmallFingerPrint(cursor.getLong(0)));
|
||||
if (LOCAL_LOGV)
|
||||
Log.v(TAG, "adding key " + Apg.getSmallFingerPrint(cursor.getLong(0)));
|
||||
fPrints.add(Apg.getSmallFingerPrint(cursor.getLong(0)));
|
||||
ids.add(cursor.getString(1));
|
||||
}
|
||||
@ -536,11 +575,12 @@ 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;
|
||||
if(isBlob) {
|
||||
if (isBlob) {
|
||||
ContentResolver cr = getContentResolver();
|
||||
try {
|
||||
inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
||||
@ -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) {
|
||||
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;
|
||||
@ -12,7 +12,7 @@ public class CachedPassPhrase {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hc1 = (int)(this.timestamp & 0xffffffff);
|
||||
int hc1 = (int) (this.timestamp & 0xffffffff);
|
||||
int hc2 = (this.passPhrase == null ? 0 : this.passPhrase.hashCode());
|
||||
return (hc1 + hc2) * hc2 + hc1;
|
||||
}
|
@ -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,48 +674,42 @@ 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();
|
||||
if (mEncryptTarget != Id.target.file) {
|
||||
|
||||
if(out instanceof ByteArrayOutputStream) {
|
||||
if (out instanceof ByteArrayOutputStream) {
|
||||
if (useAsciiArmour) {
|
||||
String extraData = new String(((ByteArrayOutputStream)out).toByteArray());
|
||||
String extraData = new String(((ByteArrayOutputStream) out).toByteArray());
|
||||
if (mGenerateSignature) {
|
||||
data.putString(Apg.EXTRA_SIGNATURE_TEXT, extraData);
|
||||
} else {
|
||||
data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE, extraData);
|
||||
}
|
||||
} else {
|
||||
byte extraData[] = ((ByteArrayOutputStream)out).toByteArray();
|
||||
byte extraData[] = ((ByteArrayOutputStream) out).toByteArray();
|
||||
if (mGenerateSignature) {
|
||||
data.putByteArray(Apg.EXTRA_SIGNATURE_DATA, extraData);
|
||||
} else {
|
||||
data.putByteArray(Apg.EXTRA_ENCRYPTED_DATA, extraData);
|
||||
}
|
||||
}
|
||||
} else if(out instanceof FileOutputStream) {
|
||||
} else if (out instanceof FileOutputStream) {
|
||||
String fileName = mDataDestination.getStreamFilename();
|
||||
String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName;
|
||||
data.putString(Apg.EXTRA_RESULT_URI, uri);
|
||||
@ -746,8 +747,8 @@ public class EncryptActivity extends BaseActivity {
|
||||
} else if (mEncryptionKeyIds.length == 1) {
|
||||
mSelectKeysButton.setText(R.string.oneKeySelected);
|
||||
} else {
|
||||
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " " +
|
||||
getResources().getString(R.string.nKeysSelected));
|
||||
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " "
|
||||
+ getResources().getString(R.string.nKeysSelected));
|
||||
}
|
||||
|
||||
if (getSecretKeyId() == 0) {
|
||||
@ -788,7 +789,7 @@ public class EncryptActivity extends BaseActivity {
|
||||
keyIds.add(mEncryptionKeyIds[i]);
|
||||
}
|
||||
}
|
||||
long [] initialKeyIds = null;
|
||||
long[] initialKeyIds = null;
|
||||
if (keyIds.size() > 0) {
|
||||
initialKeyIds = new long[keyIds.size()];
|
||||
for (int i = 0; i < keyIds.size(); ++i) {
|
||||
@ -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