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"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
package="org.thialfihar.android.apg"
|
package="org.apg"
|
||||||
android:versionCode="11000"
|
android:versionCode="11000"
|
||||||
android:versionName="1.1" >
|
android:versionName="1.1" >
|
||||||
|
|
||||||
@ -33,7 +33,7 @@
|
|||||||
android:icon="@drawable/icon"
|
android:icon="@drawable/icon"
|
||||||
android:label="@string/app_name" >
|
android:label="@string/app_name" >
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".ui.MainActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/app_name" >
|
android:label="@string/app_name" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -43,7 +43,7 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".PublicKeyListActivity"
|
android:name=".ui.PublicKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_managePublicKeys"
|
android:label="@string/title_managePublicKeys"
|
||||||
android:launchMode="singleTop" >
|
android:launchMode="singleTop" >
|
||||||
@ -56,7 +56,7 @@
|
|||||||
android:resource="@xml/searchable_public_keys" />
|
android:resource="@xml/searchable_public_keys" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".SecretKeyListActivity"
|
android:name=".ui.SecretKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_manageSecretKeys"
|
android:label="@string/title_manageSecretKeys"
|
||||||
android:launchMode="singleTop" >
|
android:launchMode="singleTop" >
|
||||||
@ -69,11 +69,11 @@
|
|||||||
android:resource="@xml/searchable_secret_keys" />
|
android:resource="@xml/searchable_secret_keys" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".EditKeyActivity"
|
android:name=".ui.EditKeyActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_editKey" />
|
android:label="@string/title_editKey" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SelectPublicKeyListActivity"
|
android:name=".ui.SelectPublicKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_selectRecipients"
|
android:label="@string/title_selectRecipients"
|
||||||
android:launchMode="singleTop" >
|
android:launchMode="singleTop" >
|
||||||
@ -91,7 +91,7 @@
|
|||||||
android:resource="@xml/searchable_public_keys" />
|
android:resource="@xml/searchable_public_keys" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".SelectSecretKeyListActivity"
|
android:name=".ui.SelectSecretKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_selectSignature"
|
android:label="@string/title_selectSignature"
|
||||||
android:launchMode="singleTop" >
|
android:launchMode="singleTop" >
|
||||||
@ -109,7 +109,7 @@
|
|||||||
android:resource="@xml/searchable_secret_keys" />
|
android:resource="@xml/searchable_secret_keys" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".EncryptActivity"
|
android:name=".ui.EncryptActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_encrypt" >
|
android:label="@string/title_encrypt" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -124,7 +124,7 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".DecryptActivity"
|
android:name=".ui.DecryptActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_decrypt" >
|
android:label="@string/title_decrypt" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -138,7 +138,7 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".GeneralActivity"
|
android:name=".ui.GeneralActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@android:style/Theme.Dialog" >
|
android:theme="@android:style/Theme.Dialog" >
|
||||||
@ -170,31 +170,31 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".MailListActivity"
|
android:name=".ui.MailListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_mailInbox" />
|
android:label="@string/title_mailInbox" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".KeyServerQueryActivity"
|
android:name=".ui.KeyServerQueryActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_keyServerQuery" />
|
android:label="@string/title_keyServerQuery" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SendKeyActivity"
|
android:name=".ui.SendKeyActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_sendKey" />
|
android:label="@string/title_sendKey" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".PreferencesActivity"
|
android:name=".ui.PreferencesActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_preferences" />
|
android:label="@string/title_preferences" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".KeyServerPreferenceActivity"
|
android:name=".ui.KeyServerPreferenceActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_keyServerPreference" />
|
android:label="@string/title_keyServerPreference" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SignKeyActivity"
|
android:name=".ui.SignKeyActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_signKey" />
|
android:label="@string/title_signKey" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ImportFromQRCodeActivity"
|
android:name=".ui.ImportFromQRCodeActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||||
android:label="@string/title_importFromQRCode" />
|
android:label="@string/title_importFromQRCode" />
|
||||||
|
|
||||||
@ -215,11 +215,11 @@
|
|||||||
</service>
|
</service>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="org.thialfihar.android.apg.provider.DataProvider"
|
android:name=".provider.DataProvider"
|
||||||
android:authorities="org.thialfihar.android.apg.provider"
|
android:authorities="org.thialfihar.android.apg.provider"
|
||||||
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
|
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
|
||||||
<provider
|
<provider
|
||||||
android:name="org.thialfihar.android.apg.provider.ApgServiceBlobProvider"
|
android:name=".provider.ApgServiceBlobProvider"
|
||||||
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider"
|
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider"
|
||||||
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" />
|
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" />
|
||||||
</application>
|
</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.
|
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"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -63,4 +63,4 @@
|
|||||||
android:paddingBottom="6dip"
|
android:paddingBottom="6dip"
|
||||||
android:orientation="vertical"/>
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
</org.thialfihar.android.apg.ui.widget.SectionView>
|
</org.apg.ui.widget.SectionView>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
limitations under the License.
|
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"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -112,4 +112,4 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</org.thialfihar.android.apg.ui.widget.UserIdEditor>
|
</org.apg.ui.widget.UserIdEditor>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
limitations under the License.
|
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"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -49,4 +49,4 @@
|
|||||||
android:layout_height="1dip"
|
android:layout_height="1dip"
|
||||||
android:background="?android:attr/listDivider"/>
|
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"?>
|
<?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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -15,6 +16,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="MinusButton">
|
<style name="MinusButton">
|
||||||
<item name="android:background">@drawable/btn_circle</item>
|
<item name="android:background">@drawable/btn_circle</item>
|
||||||
<item name="android:src">@drawable/ic_btn_round_minus</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:background">@drawable/btn_circle</item>
|
||||||
<item name="android:src">@drawable/ic_btn_round_plus</item>
|
<item name="android:src">@drawable/ic_btn_round_plus</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,71 +15,56 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<PreferenceCategory
|
|
||||||
android:title="@string/section_general">
|
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/section_general" >
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:key="language"
|
android:dialogTitle="@string/label_language"
|
||||||
android:title="@string/label_language"
|
|
||||||
android:entries="@array/language_entries"
|
android:entries="@array/language_entries"
|
||||||
android:entryValues="@array/language_values"
|
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
|
<org.apg.ui.widget.IntegerListPreference
|
||||||
android:persistent="false"
|
|
||||||
android:key="passPhraseCacheTtl"
|
|
||||||
android:entries="@array/pass_phrase_cache_ttl_entries"
|
android:entries="@array/pass_phrase_cache_ttl_entries"
|
||||||
android:entryValues="@array/pass_phrase_cache_ttl_values"
|
android:entryValues="@array/pass_phrase_cache_ttl_values"
|
||||||
|
android:key="passPhraseCacheTtl"
|
||||||
|
android:persistent="false"
|
||||||
android:title="@string/label_passPhraseCacheTtl" />
|
android:title="@string/label_passPhraseCacheTtl" />
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:persistent="false"
|
|
||||||
android:key="keyServers"
|
android:key="keyServers"
|
||||||
|
android:persistent="false"
|
||||||
android:title="@string/label_keyServers" />
|
android:title="@string/label_keyServers" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory android:title="@string/section_defaults" >
|
||||||
<PreferenceCategory
|
<org.apg.ui.widget.IntegerListPreference
|
||||||
android:title="@string/section_defaults">
|
|
||||||
|
|
||||||
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
|
|
||||||
android:persistent="false"
|
|
||||||
android:key="defaultEncryptionAlgorithm"
|
android:key="defaultEncryptionAlgorithm"
|
||||||
|
android:persistent="false"
|
||||||
android:title="@string/label_encryptionAlgorithm" />
|
android:title="@string/label_encryptionAlgorithm" />
|
||||||
|
<org.apg.ui.widget.IntegerListPreference
|
||||||
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
|
|
||||||
android:persistent="false"
|
|
||||||
android:key="defaultHashAlgorithm"
|
android:key="defaultHashAlgorithm"
|
||||||
|
android:persistent="false"
|
||||||
android:title="@string/label_hashAlgorithm" />
|
android:title="@string/label_hashAlgorithm" />
|
||||||
|
<org.apg.ui.widget.IntegerListPreference
|
||||||
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
|
|
||||||
android:persistent="false"
|
|
||||||
android:key="defaultMessageCompression"
|
android:key="defaultMessageCompression"
|
||||||
android:title="@string/label_messageCompression" />
|
|
||||||
|
|
||||||
<org.thialfihar.android.apg.ui.widget.IntegerListPreference
|
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
|
android:title="@string/label_messageCompression" />
|
||||||
|
<org.apg.ui.widget.IntegerListPreference
|
||||||
android:key="defaultFileCompression"
|
android:key="defaultFileCompression"
|
||||||
|
android:persistent="false"
|
||||||
android:title="@string/label_fileCompression" />
|
android:title="@string/label_fileCompression" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:persistent="false"
|
|
||||||
android:key="defaultAsciiArmour"
|
android:key="defaultAsciiArmour"
|
||||||
android:title="@string/label_asciiArmour" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
<PreferenceCategory
|
|
||||||
android:title="@string/section_advanced">
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
|
android:title="@string/label_asciiArmour" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory android:title="@string/section_advanced" >
|
||||||
|
<CheckBoxPreference
|
||||||
android:key="forceV3Signatures"
|
android:key="forceV3Signatures"
|
||||||
|
android:persistent="false"
|
||||||
android:title="@string/label_forceV3Signature" />
|
android:title="@string/label_forceV3Signature" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,8 +15,8 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<searchable
|
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:hint="@string/hint_publicKeys"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name" >
|
||||||
android:hint="@string/hint_publicKeys">
|
|
||||||
</searchable>
|
</searchable>
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,8 +15,8 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<searchable
|
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:hint="@string/hint_secretKeys"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name" >
|
||||||
android:hint="@string/hint_secretKeys">
|
|
||||||
</searchable>
|
</searchable>
|
@ -14,8 +14,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
|
import org.apg.KeyServer.AddKeyException;
|
||||||
|
import org.apg.provider.DataProvider;
|
||||||
|
import org.apg.provider.Database;
|
||||||
|
import org.apg.provider.KeyRings;
|
||||||
|
import org.apg.provider.Keys;
|
||||||
|
import org.apg.provider.UserIds;
|
||||||
|
import org.apg.ui.BaseActivity;
|
||||||
|
import org.apg.ui.widget.KeyEditor;
|
||||||
|
import org.apg.ui.widget.SectionView;
|
||||||
|
import org.apg.ui.widget.UserIdEditor;
|
||||||
|
import org.apg.util.IterableIterator;
|
||||||
import org.spongycastle.bcpg.ArmoredInputStream;
|
import org.spongycastle.bcpg.ArmoredInputStream;
|
||||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.spongycastle.bcpg.BCPGOutputStream;
|
import org.spongycastle.bcpg.BCPGOutputStream;
|
||||||
@ -53,16 +64,7 @@ import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
|||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.PGPV3SignatureGenerator;
|
import org.spongycastle.openpgp.PGPV3SignatureGenerator;
|
||||||
import org.thialfihar.android.apg.KeyServer.AddKeyException;
|
import org.apg.R;
|
||||||
import org.thialfihar.android.apg.provider.DataProvider;
|
|
||||||
import org.thialfihar.android.apg.provider.Database;
|
|
||||||
import org.thialfihar.android.apg.provider.KeyRings;
|
|
||||||
import org.thialfihar.android.apg.provider.Keys;
|
|
||||||
import org.thialfihar.android.apg.provider.UserIds;
|
|
||||||
import org.thialfihar.android.apg.ui.widget.KeyEditor;
|
|
||||||
import org.thialfihar.android.apg.ui.widget.SectionView;
|
|
||||||
import org.thialfihar.android.apg.ui.widget.UserIdEditor;
|
|
||||||
import org.thialfihar.android.apg.utils.IterableIterator;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -155,54 +157,45 @@ public class Apg {
|
|||||||
|
|
||||||
public static final String AUTHORITY = DataProvider.AUTHORITY;
|
public static final String AUTHORITY = DataProvider.AUTHORITY;
|
||||||
|
|
||||||
public static final Uri CONTENT_URI_SECRET_KEY_RINGS =
|
public static final Uri CONTENT_URI_SECRET_KEY_RINGS = Uri.parse("content://" + AUTHORITY
|
||||||
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/");
|
+ "/key_rings/secret/");
|
||||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID =
|
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://"
|
||||||
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/key_id/");
|
+ AUTHORITY + "/key_rings/secret/key_id/");
|
||||||
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS =
|
public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://"
|
||||||
Uri.parse("content://" + AUTHORITY + "/key_rings/secret/emails/");
|
+ AUTHORITY + "/key_rings/secret/emails/");
|
||||||
|
|
||||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS =
|
public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS = Uri.parse("content://" + AUTHORITY
|
||||||
Uri.parse("content://" + AUTHORITY + "/key_rings/public/");
|
+ "/key_rings/public/");
|
||||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID =
|
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://"
|
||||||
Uri.parse("content://" + AUTHORITY + "/key_rings/public/key_id/");
|
+ AUTHORITY + "/key_rings/public/key_id/");
|
||||||
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS =
|
public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://"
|
||||||
Uri.parse("content://" + AUTHORITY + "/key_rings/public/emails/");
|
+ AUTHORITY + "/key_rings/public/emails/");
|
||||||
|
|
||||||
private static String VERSION = null;
|
private static String VERSION = null;
|
||||||
|
|
||||||
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS =
|
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[] {
|
||||||
new int[] {
|
SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192,
|
||||||
SymmetricKeyAlgorithmTags.AES_256,
|
SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5,
|
||||||
SymmetricKeyAlgorithmTags.AES_192,
|
|
||||||
SymmetricKeyAlgorithmTags.AES_128,
|
|
||||||
SymmetricKeyAlgorithmTags.CAST5,
|
|
||||||
SymmetricKeyAlgorithmTags.TRIPLE_DES };
|
SymmetricKeyAlgorithmTags.TRIPLE_DES };
|
||||||
private static final int[] PREFERRED_HASH_ALGORITHMS =
|
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[] { HashAlgorithmTags.SHA1,
|
||||||
new int[] {
|
HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160 };
|
||||||
HashAlgorithmTags.SHA1,
|
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[] {
|
||||||
HashAlgorithmTags.SHA256,
|
CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2,
|
||||||
HashAlgorithmTags.RIPEMD160 };
|
|
||||||
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS =
|
|
||||||
new int[] {
|
|
||||||
CompressionAlgorithmTags.ZLIB,
|
|
||||||
CompressionAlgorithmTags.BZIP2,
|
|
||||||
CompressionAlgorithmTags.ZIP };
|
CompressionAlgorithmTags.ZIP };
|
||||||
|
|
||||||
public static Pattern PGP_MESSAGE =
|
public static Pattern PGP_MESSAGE = Pattern.compile(
|
||||||
Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
|
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
|
||||||
|
|
||||||
|
public static Pattern PGP_SIGNED_MESSAGE = Pattern
|
||||||
|
.compile(
|
||||||
|
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
||||||
Pattern.DOTALL);
|
Pattern.DOTALL);
|
||||||
|
|
||||||
public static Pattern PGP_SIGNED_MESSAGE =
|
public static Pattern PGP_PUBLIC_KEY = Pattern.compile(
|
||||||
Pattern.compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
|
||||||
Pattern.DOTALL);
|
Pattern.DOTALL);
|
||||||
|
|
||||||
public static Pattern PGP_PUBLIC_KEY =
|
private static HashMap<Long, CachedPassPhrase> mPassPhraseCache = new HashMap<Long, CachedPassPhrase>();
|
||||||
Pattern.compile(".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
|
|
||||||
Pattern.DOTALL);
|
|
||||||
|
|
||||||
private static HashMap<Long, CachedPassPhrase> mPassPhraseCache =
|
|
||||||
new HashMap<Long, CachedPassPhrase>();
|
|
||||||
private static String mEditPassPhrase = null;
|
private static String mEditPassPhrase = null;
|
||||||
|
|
||||||
private static Database mDatabase = null;
|
private static Database mDatabase = null;
|
||||||
@ -293,11 +286,10 @@ public class Apg {
|
|||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PGPSecretKey createKey(Context context,
|
public static PGPSecretKey createKey(Context context, int algorithmChoice, int keySize,
|
||||||
int algorithmChoice, int keySize, String passPhrase,
|
String passPhrase, PGPSecretKey masterKey) throws NoSuchAlgorithmException,
|
||||||
PGPSecretKey masterKey)
|
PGPException, NoSuchProviderException, GeneralException,
|
||||||
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
InvalidAlgorithmParameterException {
|
||||||
GeneralException, InvalidAlgorithmParameterException {
|
|
||||||
|
|
||||||
if (keySize < 512) {
|
if (keySize < 512) {
|
||||||
throw new GeneralException(context.getString(R.string.error_keySizeMinimum512bit));
|
throw new GeneralException(context.getString(R.string.error_keySizeMinimum512bit));
|
||||||
@ -322,7 +314,8 @@ public class Apg {
|
|||||||
|
|
||||||
case Id.choice.algorithm.elgamal: {
|
case Id.choice.algorithm.elgamal: {
|
||||||
if (masterKey == null) {
|
if (masterKey == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_masterKeyMustNotBeElGamal));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_masterKeyMustNotBeElGamal));
|
||||||
}
|
}
|
||||||
keyGen = KeyPairGenerator.getInstance("ELGAMAL", new BouncyCastleProvider());
|
keyGen = KeyPairGenerator.getInstance("ELGAMAL", new BouncyCastleProvider());
|
||||||
BigInteger p = Primes.getBestPrime(keySize);
|
BigInteger p = Primes.getBestPrime(keySize);
|
||||||
@ -354,27 +347,21 @@ public class Apg {
|
|||||||
if (masterKey == null) {
|
if (masterKey == null) {
|
||||||
// enough for now, as we assemble the key again later anyway
|
// enough for now, as we assemble the key again later anyway
|
||||||
secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, "",
|
secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, "",
|
||||||
PGPEncryptedData.CAST5, passPhrase.toCharArray(),
|
PGPEncryptedData.CAST5, passPhrase.toCharArray(), null, null,
|
||||||
null, null,
|
|
||||||
new SecureRandom(), new BouncyCastleProvider().getName());
|
new SecureRandom(), new BouncyCastleProvider().getName());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PGPPublicKey tmpKey = masterKey.getPublicKey();
|
PGPPublicKey tmpKey = masterKey.getPublicKey();
|
||||||
PGPPublicKey masterPublicKey =
|
PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
|
||||||
new PGPPublicKey(tmpKey.getAlgorithm(),
|
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
|
||||||
tmpKey.getKey(new BouncyCastleProvider()),
|
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(passPhrase.toCharArray(),
|
||||||
tmpKey.getCreationTime());
|
|
||||||
PGPPrivateKey masterPrivateKey =
|
|
||||||
masterKey.extractPrivateKey(passPhrase.toCharArray(),
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
|
|
||||||
PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
|
PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
|
||||||
PGPKeyRingGenerator ringGen =
|
PGPKeyRingGenerator ringGen = new PGPKeyRingGenerator(
|
||||||
new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
|
PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair, "", PGPEncryptedData.CAST5,
|
||||||
masterKeyPair, "",
|
passPhrase.toCharArray(), null, null, new SecureRandom(),
|
||||||
PGPEncryptedData.CAST5, passPhrase.toCharArray(),
|
new BouncyCastleProvider().getName());
|
||||||
null, null,
|
|
||||||
new SecureRandom(), new BouncyCastleProvider().getName());
|
|
||||||
ringGen.addSubKey(keyPair);
|
ringGen.addSubKey(keyPair);
|
||||||
PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing();
|
PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing();
|
||||||
Iterator<PGPSecretKey> it = secKeyRing.getSecretKeys();
|
Iterator<PGPSecretKey> it = secKeyRing.getSecretKeys();
|
||||||
@ -398,12 +385,11 @@ public class Apg {
|
|||||||
return numDays;
|
return numDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void buildSecretKey(Activity context,
|
public static void buildSecretKey(Activity context, SectionView userIdsView,
|
||||||
SectionView userIdsView, SectionView keysView,
|
SectionView keysView, String oldPassPhrase, String newPassPhrase,
|
||||||
String oldPassPhrase, String newPassPhrase,
|
ProgressDialogUpdater progress) throws Apg.GeneralException, NoSuchProviderException,
|
||||||
ProgressDialogUpdater progress)
|
PGPException, NoSuchAlgorithmException, SignatureException, IOException,
|
||||||
throws Apg.GeneralException, NoSuchProviderException, PGPException,
|
Database.GeneralException {
|
||||||
NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException {
|
|
||||||
|
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_buildingKey, 0, 100);
|
progress.setProgress(R.string.progress_buildingKey, 0, 100);
|
||||||
@ -433,7 +419,8 @@ public class Apg {
|
|||||||
} catch (UserIdEditor.NoNameException e) {
|
} catch (UserIdEditor.NoNameException e) {
|
||||||
throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName));
|
throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName));
|
||||||
} catch (UserIdEditor.NoEmailException e) {
|
} catch (UserIdEditor.NoEmailException e) {
|
||||||
throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAnEmailAddress));
|
throw new Apg.GeneralException(
|
||||||
|
context.getString(R.string.error_userIdNeedsAnEmailAddress));
|
||||||
} catch (UserIdEditor.InvalidEmailException e) {
|
} catch (UserIdEditor.InvalidEmailException e) {
|
||||||
throw new Apg.GeneralException("" + e);
|
throw new Apg.GeneralException("" + e);
|
||||||
}
|
}
|
||||||
@ -455,7 +442,8 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!gotMainUserId) {
|
if (!gotMainUserId) {
|
||||||
throw new Apg.GeneralException(context.getString(R.string.error_mainUserIdMustNotBeEmpty));
|
throw new Apg.GeneralException(
|
||||||
|
context.getString(R.string.error_mainUserIdMustNotBeEmpty));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyEditors.getChildCount() == 0) {
|
if (keyEditors.getChildCount() == 0) {
|
||||||
@ -471,21 +459,16 @@ public class Apg {
|
|||||||
progress.setProgress(R.string.progress_preparingMasterKey, 10, 100);
|
progress.setProgress(R.string.progress_preparingMasterKey, 10, 100);
|
||||||
KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0);
|
KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0);
|
||||||
int usageId = keyEditor.getUsage();
|
int usageId = keyEditor.getUsage();
|
||||||
boolean canSign = (usageId == Id.choice.usage.sign_only ||
|
boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||||
usageId == Id.choice.usage.sign_and_encrypt);
|
boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||||
boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only ||
|
|
||||||
usageId == Id.choice.usage.sign_and_encrypt);
|
|
||||||
|
|
||||||
String mainUserId = userIds.get(0);
|
String mainUserId = userIds.get(0);
|
||||||
|
|
||||||
PGPSecretKey masterKey = keys.get(0);
|
PGPSecretKey masterKey = keys.get(0);
|
||||||
PGPPublicKey tmpKey = masterKey.getPublicKey();
|
PGPPublicKey tmpKey = masterKey.getPublicKey();
|
||||||
PGPPublicKey masterPublicKey =
|
PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
|
||||||
new PGPPublicKey(tmpKey.getAlgorithm(),
|
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
|
||||||
tmpKey.getKey(new BouncyCastleProvider()),
|
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(oldPassPhrase.toCharArray(),
|
||||||
tmpKey.getCreationTime());
|
|
||||||
PGPPrivateKey masterPrivateKey =
|
|
||||||
masterKey.extractPrivateKey(oldPassPhrase.toCharArray(),
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
|
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
@ -493,8 +476,7 @@ public class Apg {
|
|||||||
for (int i = 0; i < userIds.size(); ++i) {
|
for (int i = 0; i < userIds.size(); ++i) {
|
||||||
String userId = userIds.get(i);
|
String userId = userIds.get(i);
|
||||||
|
|
||||||
PGPSignatureGenerator sGen =
|
PGPSignatureGenerator sGen = new PGPSignatureGenerator(masterPublicKey.getAlgorithm(),
|
||||||
new PGPSignatureGenerator(masterPublicKey.getAlgorithm(),
|
|
||||||
HashAlgorithmTags.SHA1, new BouncyCastleProvider());
|
HashAlgorithmTags.SHA1, new BouncyCastleProvider());
|
||||||
|
|
||||||
sGen.initSign(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
|
sGen.initSign(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
|
||||||
@ -528,19 +510,18 @@ public class Apg {
|
|||||||
GregorianCalendar expiryDate = keyEditor.getExpiryDate();
|
GregorianCalendar expiryDate = keyEditor.getExpiryDate();
|
||||||
long numDays = getNumDaysBetween(creationDate, expiryDate);
|
long numDays = getNumDaysBetween(creationDate, expiryDate);
|
||||||
if (numDays <= 0) {
|
if (numDays <= 0) {
|
||||||
throw new GeneralException(context.getString(R.string.error_expiryMustComeAfterCreation));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_expiryMustComeAfterCreation));
|
||||||
}
|
}
|
||||||
hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
|
hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100);
|
progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100);
|
||||||
PGPKeyRingGenerator keyGen =
|
PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
|
||||||
new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
|
masterKeyPair, mainUserId, PGPEncryptedData.CAST5, newPassPhrase.toCharArray(),
|
||||||
masterKeyPair, mainUserId,
|
hashedPacketsGen.generate(), unhashedPacketsGen.generate(), new SecureRandom(),
|
||||||
PGPEncryptedData.CAST5, newPassPhrase.toCharArray(),
|
new BouncyCastleProvider().getName());
|
||||||
hashedPacketsGen.generate(), unhashedPacketsGen.generate(),
|
|
||||||
new SecureRandom(), new BouncyCastleProvider().getName());
|
|
||||||
|
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_addingSubKeys, 40, 100);
|
progress.setProgress(R.string.progress_addingSubKeys, 40, 100);
|
||||||
@ -550,13 +531,10 @@ public class Apg {
|
|||||||
PGPSecretKey subKey = keys.get(i);
|
PGPSecretKey subKey = keys.get(i);
|
||||||
keyEditor = (KeyEditor) keyEditors.getChildAt(i);
|
keyEditor = (KeyEditor) keyEditors.getChildAt(i);
|
||||||
PGPPublicKey subPublicKey = subKey.getPublicKey();
|
PGPPublicKey subPublicKey = subKey.getPublicKey();
|
||||||
PGPPrivateKey subPrivateKey =
|
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(oldPassPhrase.toCharArray(),
|
||||||
subKey.extractPrivateKey(oldPassPhrase.toCharArray(),
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
PGPKeyPair subKeyPair =
|
PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey.getAlgorithm(),
|
||||||
new PGPKeyPair(subPublicKey.getAlgorithm(),
|
subPublicKey.getKey(new BouncyCastleProvider()), subPrivateKey.getKey(),
|
||||||
subPublicKey.getKey(new BouncyCastleProvider()),
|
|
||||||
subPrivateKey.getKey(),
|
|
||||||
subPublicKey.getCreationTime());
|
subPublicKey.getCreationTime());
|
||||||
|
|
||||||
hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||||
@ -564,10 +542,8 @@ public class Apg {
|
|||||||
|
|
||||||
keyFlags = 0;
|
keyFlags = 0;
|
||||||
usageId = keyEditor.getUsage();
|
usageId = keyEditor.getUsage();
|
||||||
canSign = (usageId == Id.choice.usage.sign_only ||
|
canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||||
usageId == Id.choice.usage.sign_and_encrypt);
|
canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||||
canEncrypt = (usageId == Id.choice.usage.encrypt_only ||
|
|
||||||
usageId == Id.choice.usage.sign_and_encrypt);
|
|
||||||
if (canSign) {
|
if (canSign) {
|
||||||
keyFlags |= KeyFlags.SIGN_DATA;
|
keyFlags |= KeyFlags.SIGN_DATA;
|
||||||
}
|
}
|
||||||
@ -583,13 +559,13 @@ public class Apg {
|
|||||||
GregorianCalendar expiryDate = keyEditor.getExpiryDate();
|
GregorianCalendar expiryDate = keyEditor.getExpiryDate();
|
||||||
long numDays = getNumDaysBetween(creationDate, expiryDate);
|
long numDays = getNumDaysBetween(creationDate, expiryDate);
|
||||||
if (numDays <= 0) {
|
if (numDays <= 0) {
|
||||||
throw new GeneralException(context.getString(R.string.error_expiryMustComeAfterCreation));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_expiryMustComeAfterCreation));
|
||||||
}
|
}
|
||||||
hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
|
hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
|
||||||
}
|
}
|
||||||
|
|
||||||
keyGen.addSubKey(subKeyPair,
|
keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
|
||||||
hashedPacketsGen.generate(), unhashedPacketsGen.generate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
|
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
|
||||||
@ -623,9 +599,11 @@ public class Apg {
|
|||||||
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
|
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
|
||||||
boolean save = true;
|
boolean save = true;
|
||||||
try {
|
try {
|
||||||
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(new char[] {}, new BouncyCastleProvider());
|
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(
|
||||||
|
new char[] {}, new BouncyCastleProvider());
|
||||||
if (testKey == null) {
|
if (testKey == null) {
|
||||||
// this is bad, something is very wrong... likely a --export-secret-subkeys export
|
// this is bad, something is very wrong... likely a --export-secret-subkeys
|
||||||
|
// export
|
||||||
save = false;
|
save = false;
|
||||||
status = Id.return_value.bad;
|
status = Id.return_value.bad;
|
||||||
}
|
}
|
||||||
@ -673,10 +651,9 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bundle importKeyRings(Activity context, int type,
|
public static Bundle importKeyRings(Activity context, int type, InputData data,
|
||||||
InputData data,
|
ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException,
|
||||||
ProgressDialogUpdater progress)
|
PGPException, IOException {
|
||||||
throws GeneralException, FileNotFoundException, PGPException, IOException {
|
|
||||||
Bundle returnData = new Bundle();
|
Bundle returnData = new Bundle();
|
||||||
|
|
||||||
if (type == Id.type.secret_key) {
|
if (type == Id.type.secret_key) {
|
||||||
@ -705,8 +682,8 @@ public class Apg {
|
|||||||
int status = Integer.MIN_VALUE; // out of bounds value
|
int status = Integer.MIN_VALUE; // out of bounds value
|
||||||
|
|
||||||
// if this key is what we expect it to be, save it
|
// if this key is what we expect it to be, save it
|
||||||
if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing) ||
|
if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing)
|
||||||
(type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) {
|
|| (type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) {
|
||||||
status = storeKeyRingInCache(keyring);
|
status = storeKeyRingInCache(keyring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,9 +723,8 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Bundle exportKeyRings(Activity context, Vector<Integer> keyRingIds,
|
public static Bundle exportKeyRings(Activity context, Vector<Integer> keyRingIds,
|
||||||
OutputStream outStream,
|
OutputStream outStream, ProgressDialogUpdater progress) throws GeneralException,
|
||||||
ProgressDialogUpdater progress)
|
FileNotFoundException, PGPException, IOException {
|
||||||
throws GeneralException, FileNotFoundException, PGPException, IOException {
|
|
||||||
Bundle returnData = new Bundle();
|
Bundle returnData = new Bundle();
|
||||||
|
|
||||||
if (keyRingIds.size() == 1) {
|
if (keyRingIds.size() == 1) {
|
||||||
@ -878,8 +854,8 @@ public class Apg {
|
|||||||
Date creationDate = getCreationDate(key);
|
Date creationDate = getCreationDate(key);
|
||||||
Date expiryDate = getExpiryDate(key);
|
Date expiryDate = getExpiryDate(key);
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
if (now.compareTo(creationDate) >= 0 &&
|
if (now.compareTo(creationDate) >= 0
|
||||||
(expiryDate == null || now.compareTo(expiryDate) <= 0)) {
|
&& (expiryDate == null || now.compareTo(expiryDate) <= 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1007,15 +983,15 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
|
PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
|
||||||
|
|
||||||
if (hashed != null &&(hashed.getKeyFlags() &
|
if (hashed != null
|
||||||
(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
|
&& (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
|
PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
|
||||||
|
|
||||||
if (unhashed != null &&(unhashed.getKeyFlags() &
|
if (unhashed != null
|
||||||
(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
|
&& (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1209,10 +1185,8 @@ public class Apg {
|
|||||||
public static Vector<Integer> getKeyRingIds(int type) {
|
public static Vector<Integer> getKeyRingIds(int type) {
|
||||||
SQLiteDatabase db = mDatabase.db();
|
SQLiteDatabase db = mDatabase.db();
|
||||||
Vector<Integer> keyIds = new Vector<Integer>();
|
Vector<Integer> keyIds = new Vector<Integer>();
|
||||||
Cursor c = db.query(KeyRings.TABLE_NAME,
|
Cursor c = db.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, KeyRings.TYPE
|
||||||
new String[] { KeyRings._ID },
|
+ " = ?", new String[] { "" + type }, null, null, null);
|
||||||
KeyRings.TYPE + " = ?", new String[] { "" + type },
|
|
||||||
null, null, null);
|
|
||||||
if (c != null && c.moveToFirst()) {
|
if (c != null && c.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
keyIds.add(c.getInt(0));
|
keyIds.add(c.getInt(0));
|
||||||
@ -1228,25 +1202,16 @@ public class Apg {
|
|||||||
|
|
||||||
public static String getMainUserId(long keyId, int type) {
|
public static String getMainUserId(long keyId, int type) {
|
||||||
SQLiteDatabase db = mDatabase.db();
|
SQLiteDatabase db = mDatabase.db();
|
||||||
Cursor c = db.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON (" +
|
Cursor c = db.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON ("
|
||||||
KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " +
|
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
|
||||||
Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + ") " +
|
+ Keys.KEY_RING_ID + ") " + " INNER JOIN " + Keys.TABLE_NAME + " AS masterKey ON ("
|
||||||
" INNER JOIN " + Keys.TABLE_NAME + " AS masterKey ON (" +
|
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + "masterKey."
|
||||||
KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " +
|
+ Keys.KEY_RING_ID + " AND " + "masterKey." + Keys.IS_MASTER_KEY + " = '1') "
|
||||||
"masterKey." + Keys.KEY_RING_ID + " AND " +
|
+ " INNER JOIN " + UserIds.TABLE_NAME + " ON (" + UserIds.TABLE_NAME + "."
|
||||||
"masterKey." + Keys.IS_MASTER_KEY + " = '1') " +
|
+ UserIds.KEY_ID + " = " + "masterKey." + Keys._ID + " AND " + UserIds.TABLE_NAME
|
||||||
" INNER JOIN " + UserIds.TABLE_NAME + " ON (" +
|
+ "." + UserIds.RANK + " = '0')", new String[] { UserIds.USER_ID }, Keys.TABLE_NAME
|
||||||
UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " = " +
|
+ "." + Keys.KEY_ID + " = ? AND " + KeyRings.TABLE_NAME + "." + KeyRings.TYPE
|
||||||
"masterKey." + Keys._ID + " AND " +
|
+ " = ?", new String[] { "" + keyId, "" + type, }, null, null, null);
|
||||||
UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0')",
|
|
||||||
new String[] { UserIds.USER_ID },
|
|
||||||
Keys.TABLE_NAME + "." + Keys.KEY_ID + " = ? AND " +
|
|
||||||
KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?",
|
|
||||||
new String[] {
|
|
||||||
"" + keyId,
|
|
||||||
"" + type,
|
|
||||||
},
|
|
||||||
null, null, null);
|
|
||||||
String userId = "";
|
String userId = "";
|
||||||
if (c != null && c.moveToFirst()) {
|
if (c != null && c.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
@ -1261,15 +1226,10 @@ public class Apg {
|
|||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void encrypt(Context context,
|
public static void encrypt(Context context, InputData data, OutputStream outStream,
|
||||||
InputData data, OutputStream outStream,
|
boolean armored, long encryptionKeyIds[], long signatureKeyId,
|
||||||
boolean armored,
|
String signaturePassPhrase, ProgressDialogUpdater progress, int symmetricAlgorithm,
|
||||||
long encryptionKeyIds[], long signatureKeyId,
|
int hashAlgorithm, int compression, boolean forceV3Signature, String passPhrase)
|
||||||
String signaturePassPhrase,
|
|
||||||
ProgressDialogUpdater progress,
|
|
||||||
int symmetricAlgorithm, int hashAlgorithm, int compression,
|
|
||||||
boolean forceV3Signature,
|
|
||||||
String passPhrase)
|
|
||||||
throws IOException, GeneralException, PGPException, NoSuchProviderException,
|
throws IOException, GeneralException, PGPException, NoSuchProviderException,
|
||||||
NoSuchAlgorithmException, SignatureException {
|
NoSuchAlgorithmException, SignatureException {
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
@ -1293,7 +1253,8 @@ public class Apg {
|
|||||||
PGPPrivateKey signaturePrivateKey = null;
|
PGPPrivateKey signaturePrivateKey = null;
|
||||||
|
|
||||||
if (encryptionKeyIds.length == 0 && passPhrase == null) {
|
if (encryptionKeyIds.length == 0 && passPhrase == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_noEncryptionKeysOrPassPhrase));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_noEncryptionKeysOrPassPhrase));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signatureKeyId != 0) {
|
if (signatureKeyId != 0) {
|
||||||
@ -1311,16 +1272,16 @@ public class Apg {
|
|||||||
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
|
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
if (signaturePrivateKey == null) {
|
if (signaturePrivateKey == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_couldNotExtractPrivateKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_preparingStreams, 5, 100);
|
progress.setProgress(R.string.progress_preparingStreams, 5, 100);
|
||||||
|
|
||||||
// encrypt and compress input file content
|
// encrypt and compress input file content
|
||||||
PGPEncryptedDataGenerator cPk =
|
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(symmetricAlgorithm, true,
|
||||||
new PGPEncryptedDataGenerator(symmetricAlgorithm, true, new SecureRandom(),
|
new SecureRandom(), new BouncyCastleProvider());
|
||||||
new BouncyCastleProvider());
|
|
||||||
|
|
||||||
if (encryptionKeyIds.length == 0) {
|
if (encryptionKeyIds.length == 0) {
|
||||||
// symmetric encryption
|
// symmetric encryption
|
||||||
@ -1341,16 +1302,12 @@ public class Apg {
|
|||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_preparingSignature, 10, 100);
|
progress.setProgress(R.string.progress_preparingSignature, 10, 100);
|
||||||
if (forceV3Signature) {
|
if (forceV3Signature) {
|
||||||
signatureV3Generator =
|
signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey()
|
||||||
new PGPV3SignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
|
||||||
hashAlgorithm,
|
|
||||||
new BouncyCastleProvider());
|
|
||||||
signatureV3Generator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
|
signatureV3Generator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator =
|
signatureGenerator = new PGPSignatureGenerator(signingKey.getPublicKey()
|
||||||
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
|
||||||
hashAlgorithm,
|
|
||||||
new BouncyCastleProvider());
|
|
||||||
signatureGenerator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
|
signatureGenerator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
|
||||||
|
|
||||||
String userId = getMainUserId(getMasterKey(signingKeyRing));
|
String userId = getMainUserId(getMasterKey(signingKeyRing));
|
||||||
@ -1378,8 +1335,8 @@ public class Apg {
|
|||||||
|
|
||||||
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
|
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
|
||||||
// file name not needed, so empty string
|
// file name not needed, so empty string
|
||||||
OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "",
|
OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
|
||||||
new Date(), new byte[1 << 16]);
|
new byte[1 << 16]);
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_encrypting, 20, 100);
|
progress.setProgress(R.string.progress_encrypting, 20, 100);
|
||||||
|
|
||||||
@ -1426,14 +1383,10 @@ public class Apg {
|
|||||||
progress.setProgress(R.string.progress_done, 100, 100);
|
progress.setProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void signText(Context context,
|
public static void signText(Context context, InputData data, OutputStream outStream,
|
||||||
InputData data, OutputStream outStream,
|
long signatureKeyId, String signaturePassPhrase, int hashAlgorithm,
|
||||||
long signatureKeyId, String signaturePassPhrase,
|
boolean forceV3Signature, ProgressDialogUpdater progress) throws GeneralException,
|
||||||
int hashAlgorithm,
|
PGPException, IOException, NoSuchAlgorithmException, SignatureException {
|
||||||
boolean forceV3Signature,
|
|
||||||
ProgressDialogUpdater progress)
|
|
||||||
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
|
|
||||||
SignatureException {
|
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
|
||||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
|
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
|
||||||
@ -1456,8 +1409,7 @@ public class Apg {
|
|||||||
if (signaturePassPhrase == null) {
|
if (signaturePassPhrase == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
|
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
|
||||||
}
|
}
|
||||||
signaturePrivateKey =
|
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
|
||||||
signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
if (signaturePrivateKey == null) {
|
if (signaturePrivateKey == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
|
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
|
||||||
@ -1472,15 +1424,13 @@ public class Apg {
|
|||||||
PGPV3SignatureGenerator signatureV3Generator = null;
|
PGPV3SignatureGenerator signatureV3Generator = null;
|
||||||
|
|
||||||
if (forceV3Signature) {
|
if (forceV3Signature) {
|
||||||
signatureV3Generator =
|
signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey()
|
||||||
new PGPV3SignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
|
||||||
hashAlgorithm,
|
signatureV3Generator
|
||||||
new BouncyCastleProvider());
|
.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
|
||||||
signatureV3Generator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
|
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator =
|
signatureGenerator = new PGPSignatureGenerator(
|
||||||
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
signingKey.getPublicKey().getAlgorithm(), hashAlgorithm,
|
||||||
hashAlgorithm,
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
|
signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
|
||||||
|
|
||||||
@ -1538,13 +1488,9 @@ public class Apg {
|
|||||||
progress.setProgress(R.string.progress_done, 100, 100);
|
progress.setProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateSignature(Context context,
|
public static void generateSignature(Context context, InputData data, OutputStream outStream,
|
||||||
InputData data, OutputStream outStream,
|
boolean armored, boolean binary, long signatureKeyId, String signaturePassPhrase,
|
||||||
boolean armored, boolean binary,
|
int hashAlgorithm, boolean forceV3Signature, ProgressDialogUpdater progress)
|
||||||
long signatureKeyId, String signaturePassPhrase,
|
|
||||||
int hashAlgorithm,
|
|
||||||
boolean forceV3Signature,
|
|
||||||
ProgressDialogUpdater progress)
|
|
||||||
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
|
throws GeneralException, PGPException, IOException, NoSuchAlgorithmException,
|
||||||
SignatureException {
|
SignatureException {
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
@ -1576,8 +1522,7 @@ public class Apg {
|
|||||||
if (signaturePassPhrase == null) {
|
if (signaturePassPhrase == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
|
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
|
||||||
}
|
}
|
||||||
signaturePrivateKey =
|
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
|
||||||
signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(),
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
if (signaturePrivateKey == null) {
|
if (signaturePrivateKey == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
|
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
|
||||||
@ -1597,15 +1542,12 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (forceV3Signature) {
|
if (forceV3Signature) {
|
||||||
signatureV3Generator =
|
signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey()
|
||||||
new PGPV3SignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
.getAlgorithm(), hashAlgorithm, new BouncyCastleProvider());
|
||||||
hashAlgorithm,
|
|
||||||
new BouncyCastleProvider());
|
|
||||||
signatureV3Generator.initSign(type, signaturePrivateKey);
|
signatureV3Generator.initSign(type, signaturePrivateKey);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator =
|
signatureGenerator = new PGPSignatureGenerator(
|
||||||
new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(),
|
signingKey.getPublicKey().getAlgorithm(), hashAlgorithm,
|
||||||
hashAlgorithm,
|
|
||||||
new BouncyCastleProvider());
|
new BouncyCastleProvider());
|
||||||
signatureGenerator.initSign(type, signaturePrivateKey);
|
signatureGenerator.initSign(type, signaturePrivateKey);
|
||||||
|
|
||||||
@ -1663,8 +1605,8 @@ public class Apg {
|
|||||||
progress.setProgress(R.string.progress_done, 100, 100);
|
progress.setProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getDecryptionKeyId(Context context, InputData data)
|
public static long getDecryptionKeyId(Context context, InputData data) throws GeneralException,
|
||||||
throws GeneralException, NoAsymmetricEncryptionException, IOException {
|
NoAsymmetricEncryptionException, IOException {
|
||||||
InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
|
InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
|
||||||
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
||||||
PGPEncryptedDataList enc;
|
PGPEncryptedDataList enc;
|
||||||
@ -1738,10 +1680,8 @@ public class Apg {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bundle decrypt(Context context,
|
public static Bundle decrypt(Context context, InputData data, OutputStream outStream,
|
||||||
InputData data, OutputStream outStream,
|
String passPhrase, ProgressDialogUpdater progress, boolean assumeSymmetric)
|
||||||
String passPhrase, ProgressDialogUpdater progress,
|
|
||||||
boolean assumeSymmetric)
|
|
||||||
throws IOException, GeneralException, PGPException, SignatureException {
|
throws IOException, GeneralException, PGPException, SignatureException {
|
||||||
if (passPhrase == null) {
|
if (passPhrase == null) {
|
||||||
passPhrase = "";
|
passPhrase = "";
|
||||||
@ -1787,7 +1727,8 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pbe == null) {
|
if (pbe == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_noSymmetricEncryptionPacket));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_noSymmetricEncryptionPacket));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
@ -1829,7 +1770,8 @@ public class Apg {
|
|||||||
throw new PGPException(context.getString(R.string.error_wrongPassPhrase));
|
throw new PGPException(context.getString(R.string.error_wrongPassPhrase));
|
||||||
}
|
}
|
||||||
if (privateKey == null) {
|
if (privateKey == null) {
|
||||||
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
|
throw new GeneralException(
|
||||||
|
context.getString(R.string.error_couldNotExtractPrivateKey));
|
||||||
}
|
}
|
||||||
currentProgress += 5;
|
currentProgress += 5;
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
@ -1848,8 +1790,8 @@ public class Apg {
|
|||||||
if (dataChunk instanceof PGPCompressedData) {
|
if (dataChunk instanceof PGPCompressedData) {
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(R.string.progress_decompressingData, currentProgress, 100);
|
progress.setProgress(R.string.progress_decompressingData, currentProgress, 100);
|
||||||
PGPObjectFactory fact =
|
PGPObjectFactory fact = new PGPObjectFactory(
|
||||||
new PGPObjectFactory(((PGPCompressedData) dataChunk).getDataStream());
|
((PGPCompressedData) dataChunk).getDataStream());
|
||||||
dataChunk = fact.nextObject();
|
dataChunk = fact.nextObject();
|
||||||
plainFact = fact;
|
plainFact = fact;
|
||||||
currentProgress += 10;
|
currentProgress += 10;
|
||||||
@ -1928,12 +1870,13 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// unknown size, but try to at least have a moving, slowing down progress bar
|
// unknown size, but try to at least have a moving, slowing down progress bar
|
||||||
currentProgress = startProgress + (endProgress - startProgress) * done / (done + 100000);
|
currentProgress = startProgress + (endProgress - startProgress) * done
|
||||||
|
/ (done + 100000);
|
||||||
if (data.getSize() - startPos == 0) {
|
if (data.getSize() - startPos == 0) {
|
||||||
currentProgress = endProgress;
|
currentProgress = endProgress;
|
||||||
} else {
|
} else {
|
||||||
currentProgress = (int)(startProgress + (endProgress - startProgress) *
|
currentProgress = (int) (startProgress + (endProgress - startProgress)
|
||||||
(data.getStreamPosition() - startPos) / (data.getSize() - startPos));
|
* (data.getStreamPosition() - startPos) / (data.getSize() - startPos));
|
||||||
}
|
}
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
progress.setProgress(currentProgress, 100);
|
progress.setProgress(currentProgress, 100);
|
||||||
@ -1970,10 +1913,9 @@ public class Apg {
|
|||||||
return returnData;
|
return returnData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bundle verifyText(BaseActivity context,
|
public static Bundle verifyText(BaseActivity context, InputData data, OutputStream outStream,
|
||||||
InputData data, OutputStream outStream,
|
ProgressDialogUpdater progress) throws IOException, GeneralException, PGPException,
|
||||||
ProgressDialogUpdater progress)
|
SignatureException {
|
||||||
throws IOException, GeneralException, PGPException, SignatureException {
|
|
||||||
Bundle returnData = new Bundle();
|
Bundle returnData = new Bundle();
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
@ -2074,8 +2016,7 @@ public class Apg {
|
|||||||
signature.update((byte) '\n');
|
signature.update((byte) '\n');
|
||||||
|
|
||||||
processLine(signature, lineOut.toByteArray());
|
processLine(signature, lineOut.toByteArray());
|
||||||
}
|
} while (lookAhead != -1);
|
||||||
while (lookAhead != -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
returnData.putBoolean(EXTRA_SIGNATURE_SUCCESS, signature.verify());
|
returnData.putBoolean(EXTRA_SIGNATURE_SUCCESS, signature.verify());
|
||||||
@ -2085,14 +2026,12 @@ public class Apg {
|
|||||||
return returnData;
|
return returnData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getStreamContent(Context context, InputStream inStream)
|
public static int getStreamContent(Context context, InputStream inStream) throws IOException {
|
||||||
throws IOException {
|
|
||||||
InputStream in = PGPUtil.getDecoderStream(inStream);
|
InputStream in = PGPUtil.getDecoderStream(inStream);
|
||||||
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
||||||
Object object = pgpF.nextObject();
|
Object object = pgpF.nextObject();
|
||||||
while (object != null) {
|
while (object != null) {
|
||||||
if (object instanceof PGPPublicKeyRing ||
|
if (object instanceof PGPPublicKeyRing || object instanceof PGPSecretKeyRing) {
|
||||||
object instanceof PGPSecretKeyRing) {
|
|
||||||
return Id.content.keys;
|
return Id.content.keys;
|
||||||
} else if (object instanceof PGPEncryptedDataList) {
|
} else if (object instanceof PGPEncryptedDataList) {
|
||||||
return Id.content.encrypted_data;
|
return Id.content.encrypted_data;
|
||||||
@ -2103,10 +2042,8 @@ public class Apg {
|
|||||||
return Id.content.unknown;
|
return Id.content.unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processLine(final String pLine,
|
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
||||||
final ArmoredOutputStream pArmoredOutput,
|
final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException {
|
||||||
final PGPSignatureGenerator pSignatureGenerator)
|
|
||||||
throws IOException, SignatureException {
|
|
||||||
|
|
||||||
if (pLine == null) {
|
if (pLine == null) {
|
||||||
return;
|
return;
|
||||||
@ -2130,10 +2067,9 @@ public class Apg {
|
|||||||
pSignatureGenerator.update(data);
|
pSignatureGenerator.update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processLine(final String pLine,
|
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
||||||
final ArmoredOutputStream pArmoredOutput,
|
final PGPV3SignatureGenerator pSignatureGenerator) throws IOException,
|
||||||
final PGPV3SignatureGenerator pSignatureGenerator)
|
SignatureException {
|
||||||
throws IOException, SignatureException {
|
|
||||||
|
|
||||||
if (pLine == null) {
|
if (pLine == null) {
|
||||||
return;
|
return;
|
||||||
@ -2158,8 +2094,8 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// taken from ClearSignedFileProcessor in BC
|
// taken from ClearSignedFileProcessor in BC
|
||||||
private static void processLine(PGPSignature sig, byte[] line)
|
private static void processLine(PGPSignature sig, byte[] line) throws SignatureException,
|
||||||
throws SignatureException, IOException {
|
IOException {
|
||||||
int length = getLengthWithoutWhiteSpace(line);
|
int length = getLengthWithoutWhiteSpace(line);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
sig.update(line, 0, length);
|
sig.update(line, 0, length);
|
||||||
@ -2196,8 +2132,7 @@ public class Apg {
|
|||||||
lookAhead = readPassedEOL(bOut, ch, fIn);
|
lookAhead = readPassedEOL(bOut, ch, fIn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} while ((ch = fIn.read()) >= 0);
|
||||||
while ((ch = fIn.read()) >= 0);
|
|
||||||
|
|
||||||
if (ch < 0) {
|
if (ch < 0) {
|
||||||
lookAhead = -1;
|
lookAhead = -1;
|
||||||
@ -2292,12 +2227,9 @@ public class Apg {
|
|||||||
public static String generateRandomString(int length) {
|
public static String generateRandomString(int length) {
|
||||||
SecureRandom random = new SecureRandom();
|
SecureRandom random = new SecureRandom();
|
||||||
/*
|
/*
|
||||||
try {
|
* try { random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider()); } catch
|
||||||
random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider());
|
* (NoSuchAlgorithmException e) { // TODO: need to handle this case somehow return null; }
|
||||||
} catch (NoSuchAlgorithmException e) {
|
*/
|
||||||
// TODO: need to handle this case somehow
|
|
||||||
return null;
|
|
||||||
}*/
|
|
||||||
byte bytes[] = new byte[length];
|
byte bytes[] = new byte[length];
|
||||||
random.nextBytes(bytes);
|
random.nextBytes(bytes);
|
||||||
String result = "";
|
String result = "";
|
||||||
@ -2328,7 +2260,7 @@ public class Apg {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress)
|
public static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress)
|
||||||
throws FileNotFoundException, IOException {
|
throws FileNotFoundException, IOException {
|
||||||
long length = file.length();
|
long length = file.length();
|
||||||
SecureRandom random = new SecureRandom();
|
SecureRandom random = new SecureRandom();
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -11,9 +11,10 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.provider.KeyRings;
|
import org.apg.provider.KeyRings;
|
||||||
import org.thialfihar.android.apg.provider.Keys;
|
import org.apg.provider.Keys;
|
||||||
import org.thialfihar.android.apg.provider.UserIds;
|
import org.apg.provider.UserIds;
|
||||||
|
import org.apg.IApgService;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -31,17 +32,14 @@ public class ApgService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
if( LOCAL_LOGD ) Log.d(TAG, "bound");
|
if (LOCAL_LOGD)
|
||||||
|
Log.d(TAG, "bound");
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** error status */
|
/** error status */
|
||||||
private static enum error {
|
private static enum error {
|
||||||
ARGUMENTS_MISSING,
|
ARGUMENTS_MISSING, APG_FAILURE, NO_MATCHING_SECRET_KEY, PRIVATE_KEY_PASSPHRASE_WRONG, PRIVATE_KEY_PASSPHRASE_MISSING;
|
||||||
APG_FAILURE,
|
|
||||||
NO_MATCHING_SECRET_KEY,
|
|
||||||
PRIVATE_KEY_PASSPHRASE_WRONG,
|
|
||||||
PRIVATE_KEY_PASSPHRASE_MISSING;
|
|
||||||
|
|
||||||
public int shiftedOrdinal() {
|
public int shiftedOrdinal() {
|
||||||
return ordinal() + 100;
|
return ordinal() + 100;
|
||||||
@ -49,10 +47,7 @@ public class ApgService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static enum call {
|
private static enum call {
|
||||||
encrypt_with_passphrase,
|
encrypt_with_passphrase, encrypt_with_public_key, decrypt, get_keys
|
||||||
encrypt_with_public_key,
|
|
||||||
decrypt,
|
|
||||||
get_keys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** all arguments that can be passed by calling application */
|
/** 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>();
|
private static final HashMap<String, Method> FUNCTIONS_DEFAULTS_METHODS = new HashMap<String, Method>();
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm", Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
|
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultEncryptionAlgorithm",
|
||||||
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultHashAlgorithm", Preferences.class.getMethod("getDefaultHashAlgorithm"));
|
Preferences.class.getMethod("getDefaultEncryptionAlgorithm"));
|
||||||
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultAsciiArmour", Preferences.class.getMethod("getDefaultAsciiArmour"));
|
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultHashAlgorithm",
|
||||||
FUNCTIONS_DEFAULTS_METHODS.put("getForceV3Signatures", Preferences.class.getMethod("getForceV3Signatures"));
|
Preferences.class.getMethod("getDefaultHashAlgorithm"));
|
||||||
FUNCTIONS_DEFAULTS_METHODS.put("getDefaultMessageCompression", Preferences.class.getMethod("getDefaultMessageCompression"));
|
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) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Function method exception: " + e.getMessage());
|
Log.e(TAG, "Function method exception: " + e.getMessage());
|
||||||
}
|
}
|
||||||
@ -159,22 +159,24 @@ public class ApgService extends Service {
|
|||||||
|
|
||||||
private static Cursor getKeyEntries(HashMap<String, Object> pParams) {
|
private static Cursor getKeyEntries(HashMap<String, Object> pParams) {
|
||||||
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||||
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME
|
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
|
||||||
+ "." + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME
|
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
|
||||||
+ " ON " + "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "."
|
+ Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
|
||||||
+ UserIds.RANK + " = '0') ");
|
+ " = '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 typeVal[] = null;
|
||||||
String typeWhere = null;
|
String typeWhere = null;
|
||||||
if (pParams.containsKey("key_type")) {
|
if (pParams.containsKey("key_type")) {
|
||||||
typeWhere = KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?";
|
typeWhere = KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?";
|
||||||
typeVal = new String[] {
|
typeVal = new String[] { "" + pParams.get("key_type") };
|
||||||
"" + 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
|
* maps fingerprints or user ids of keys to master keys in database
|
||||||
*
|
*
|
||||||
* @param search_keys
|
* @param search_keys
|
||||||
* a list of keys (fingerprints or user ids) to look for in
|
* a list of keys (fingerprints or user ids) to look for in database
|
||||||
* database
|
|
||||||
* @return an array of master keys
|
* @return an array of master keys
|
||||||
*/
|
*/
|
||||||
private static long[] getMasterKey(ArrayList<String> pSearchKeys, Bundle pReturn) {
|
private static long[] getMasterKey(ArrayList<String> pSearchKeys, Bundle pReturn) {
|
||||||
|
|
||||||
HashMap<String, Object> qParams = new HashMap<String, Object>();
|
HashMap<String, Object> qParams = new HashMap<String, Object>();
|
||||||
qParams.put("columns", new String[] {
|
qParams.put("columns", new String[] { KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 0
|
||||||
KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 0
|
|
||||||
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 1
|
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 1
|
||||||
});
|
});
|
||||||
qParams.put("key_type", Id.database.type_public);
|
qParams.put("key_type", Id.database.type_public);
|
||||||
|
|
||||||
Cursor mCursor = getKeyEntries(qParams);
|
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>();
|
ArrayList<Long> masterKeys = new ArrayList<Long>();
|
||||||
while (mCursor.moveToNext()) {
|
while (mCursor.moveToNext()) {
|
||||||
long curMkey = mCursor.getLong(0);
|
long curMkey = mCursor.getLong(0);
|
||||||
String curUser = mCursor.getString(1);
|
String curUser = mCursor.getString(1);
|
||||||
|
|
||||||
String curFprint = Apg.getSmallFingerPrint(curMkey);
|
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 (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);
|
masterKeys.add(curMkey);
|
||||||
pSearchKeys.remove(curFprint);
|
pSearchKeys.remove(curFprint);
|
||||||
} else {
|
} 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();
|
mCursor.close();
|
||||||
@ -243,12 +248,14 @@ public class ApgService extends Service {
|
|||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
Log.w(TAG, "Found not one public key");
|
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) {
|
for (String key : pSearchKeys) {
|
||||||
Log.w(TAG, "Searched for key " + key + " but cannot find it in APG");
|
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;
|
return masterKeyLongs;
|
||||||
@ -269,18 +276,27 @@ public class ApgService extends Service {
|
|||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
arg currentArg = iter.next();
|
arg currentArg = iter.next();
|
||||||
String currentKey = currentArg.name();
|
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);
|
String currentFunctionName = FUNCTIONS_DEFAULTS.get(currentArg);
|
||||||
try {
|
try {
|
||||||
Class<?> returnType = FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName).getReturnType();
|
Class<?> returnType = FUNCTIONS_DEFAULTS_METHODS.get(currentFunctionName)
|
||||||
|
.getReturnType();
|
||||||
if (returnType == String.class) {
|
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) {
|
} 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) {
|
} 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 {
|
} 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) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Exception in add_default_arguments " + e.getMessage());
|
Log.e(TAG, "Exception in add_default_arguments " + e.getMessage());
|
||||||
@ -320,17 +336,19 @@ public class ApgService extends Service {
|
|||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
String curArg = iter.next().name();
|
String curArg = iter.next().name();
|
||||||
if (!pArgs.containsKey(curArg)) {
|
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()) ||
|
if (pFunction.equals(call.encrypt_with_passphrase.name())
|
||||||
pFunction.equals(call.encrypt_with_public_key.name()) ||
|
|| pFunction.equals(call.encrypt_with_public_key.name())
|
||||||
pFunction.equals(call.decrypt.name())) {
|
|| pFunction.equals(call.decrypt.name())) {
|
||||||
// check that either MESSAGE or BLOB are there
|
// check that either MESSAGE or BLOB are there
|
||||||
if (!pArgs.containsKey(arg.MESSAGE.name()) && !pArgs.containsKey(arg.BLOB.name())) {
|
if (!pArgs.containsKey(arg.MESSAGE.name()) && !pArgs.containsKey(arg.BLOB.name())) {
|
||||||
pReturn.getStringArrayList(ret.ERRORS.name()).add("Arguments missing: Neither MESSAGE nor BLOG found");
|
pReturn.getStringArrayList(ret.ERRORS.name()).add(
|
||||||
|
"Arguments missing: Neither MESSAGE nor BLOG found");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -363,7 +381,8 @@ public class ApgService extends Service {
|
|||||||
try {
|
try {
|
||||||
arg curArg = arg.valueOf(curKey);
|
arg curArg = arg.valueOf(curKey);
|
||||||
if (!allArgs.contains(curArg)) {
|
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);
|
unknownArgs.add(curKey);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -386,23 +405,28 @@ public class ApgService extends Service {
|
|||||||
|
|
||||||
/* add default arguments if missing */
|
/* add default arguments if missing */
|
||||||
addDefaultArguments(pCall, pArgs);
|
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 */
|
/* check for required arguments */
|
||||||
checkForRequiredArgs(pCall, pArgs, pReturn);
|
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 */
|
/* check for unknown arguments and add to warning if found */
|
||||||
checkForUnknownArgs(pCall, pArgs, pReturn);
|
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 */
|
/* return if errors happened */
|
||||||
if (pReturn.getStringArrayList(ret.ERRORS.name()).size() != 0) {
|
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());
|
pReturn.putInt(ret.ERROR.name(), error.ARGUMENTS_MISSING.shiftedOrdinal());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if( LOCAL_LOGV ) Log.v(TAG, "error return");
|
if (LOCAL_LOGV)
|
||||||
|
Log.v(TAG, "error return");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -414,7 +438,8 @@ public class ApgService extends Service {
|
|||||||
if (pArgs.containsKey(arg.PUBLIC_KEYS.name())) {
|
if (pArgs.containsKey(arg.PUBLIC_KEYS.name())) {
|
||||||
ArrayList<String> list = pArgs.getStringArrayList(arg.PUBLIC_KEYS.name());
|
ArrayList<String> list = pArgs.getStringArrayList(arg.PUBLIC_KEYS.name());
|
||||||
ArrayList<String> pubKeys = new ArrayList<String>();
|
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();
|
Iterator<String> iter = list.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
pubKeys.add(iter.next());
|
pubKeys.add(iter.next());
|
||||||
@ -436,14 +461,16 @@ public class ApgService extends Service {
|
|||||||
InputData in = new InputData(inStream, 0); // XXX Size second param?
|
InputData in = new InputData(inStream, 0); // XXX Size second param?
|
||||||
|
|
||||||
OutputStream out = new ByteArrayOutputStream();
|
OutputStream out = new ByteArrayOutputStream();
|
||||||
if( LOCAL_LOGV ) Log.v(TAG, "About to encrypt");
|
if (LOCAL_LOGV)
|
||||||
|
Log.v(TAG, "About to encrypt");
|
||||||
try {
|
try {
|
||||||
Apg.encrypt(getBaseContext(), // context
|
Apg.encrypt(getBaseContext(), // context
|
||||||
in, // input stream
|
in, // input stream
|
||||||
out, // output stream
|
out, // output stream
|
||||||
pArgs.getBoolean(arg.ARMORED_OUTPUT.name()), // ARMORED_OUTPUT
|
pArgs.getBoolean(arg.ARMORED_OUTPUT.name()), // ARMORED_OUTPUT
|
||||||
pubMasterKeys, // encryption keys
|
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
|
pArgs.getString(arg.PRIVATE_KEY_PASSPHRASE.name()), // signature passphrase
|
||||||
null, // progress
|
null, // progress
|
||||||
pArgs.getInt(arg.ENCRYPTION_ALGORYTHM.name()), // encryption
|
pArgs.getInt(arg.ENCRYPTION_ALGORYTHM.name()), // encryption
|
||||||
@ -456,22 +483,33 @@ public class ApgService extends Service {
|
|||||||
Log.e(TAG, "Exception in encrypt");
|
Log.e(TAG, "Exception in encrypt");
|
||||||
String msg = e.getMessage();
|
String msg = e.getMessage();
|
||||||
if (msg.equals(getBaseContext().getString(R.string.error_noSignaturePassPhrase))) {
|
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.getStringArrayList(ret.ERRORS.name()).add(
|
||||||
pReturn.putInt(ret.ERROR.name(), error.PRIVATE_KEY_PASSPHRASE_MISSING.shiftedOrdinal());
|
"Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " missing): "
|
||||||
} else if (msg.equals(getBaseContext().getString(R.string.error_couldNotExtractPrivateKey))) {
|
+ msg);
|
||||||
pReturn.getStringArrayList(ret.ERRORS.name()).add("Cannot encrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name() + " probably wrong): " + msg);
|
pReturn.putInt(ret.ERROR.name(),
|
||||||
pReturn.putInt(ret.ERROR.name(), error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
|
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 {
|
} 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());
|
pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.shiftedOrdinal());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if( LOCAL_LOGV ) Log.v(TAG, "Encrypted");
|
if (LOCAL_LOGV)
|
||||||
|
Log.v(TAG, "Encrypted");
|
||||||
if (isBlob) {
|
if (isBlob) {
|
||||||
ContentResolver cr = getContentResolver();
|
ContentResolver cr = getContentResolver();
|
||||||
try {
|
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);
|
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
|
||||||
outStream.close();
|
outStream.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -501,7 +539,8 @@ public class ApgService extends Service {
|
|||||||
ArrayList<String> fPrints = new ArrayList<String>();
|
ArrayList<String> fPrints = new ArrayList<String>();
|
||||||
ArrayList<String> ids = new ArrayList<String>();
|
ArrayList<String> ids = new ArrayList<String>();
|
||||||
while (cursor.moveToNext()) {
|
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)));
|
fPrints.add(Apg.getSmallFingerPrint(cursor.getLong(0)));
|
||||||
ids.add(cursor.getString(1));
|
ids.add(cursor.getString(1));
|
||||||
}
|
}
|
||||||
@ -536,7 +575,8 @@ public class ApgService extends Service {
|
|||||||
|
|
||||||
boolean isBlob = pArgs.containsKey(arg.BLOB.name());
|
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());
|
.getString(arg.PRIVATE_KEY_PASSPHRASE.name());
|
||||||
|
|
||||||
InputStream inStream = null;
|
InputStream inStream = null;
|
||||||
@ -553,7 +593,8 @@ public class ApgService extends Service {
|
|||||||
|
|
||||||
InputData in = new InputData(inStream, 0); // XXX what size in second parameter?
|
InputData in = new InputData(inStream, 0); // XXX what size in second parameter?
|
||||||
OutputStream out = new ByteArrayOutputStream();
|
OutputStream out = new ByteArrayOutputStream();
|
||||||
if( LOCAL_LOGV ) Log.v(TAG, "About to decrypt");
|
if (LOCAL_LOGV)
|
||||||
|
Log.v(TAG, "About to decrypt");
|
||||||
try {
|
try {
|
||||||
Apg.decrypt(getBaseContext(), in, out, passphrase, null, // progress
|
Apg.decrypt(getBaseContext(), in, out, passphrase, null, // progress
|
||||||
pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null // symmetric
|
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.getStringArrayList(ret.ERRORS.name()).add("Cannot decrypt: " + msg);
|
||||||
pReturn.putInt(ret.ERROR.name(), error.NO_MATCHING_SECRET_KEY.shiftedOrdinal());
|
pReturn.putInt(ret.ERROR.name(), error.NO_MATCHING_SECRET_KEY.shiftedOrdinal());
|
||||||
} else if (msg.equals(getBaseContext().getString(R.string.error_wrongPassPhrase))) {
|
} 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.getStringArrayList(ret.ERRORS.name()).add(
|
||||||
pReturn.putInt(ret.ERROR.name(), error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
|
"Cannot decrypt (" + arg.PRIVATE_KEY_PASSPHRASE.name()
|
||||||
|
+ " wrong/missing): " + msg);
|
||||||
|
pReturn.putInt(ret.ERROR.name(),
|
||||||
|
error.PRIVATE_KEY_PASSPHRASE_WRONG.shiftedOrdinal());
|
||||||
} else {
|
} 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());
|
pReturn.putInt(ret.ERROR.name(), error.APG_FAILURE.shiftedOrdinal());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if( LOCAL_LOGV ) Log.v(TAG, "... decrypted");
|
if (LOCAL_LOGV)
|
||||||
|
Log.v(TAG, "... decrypted");
|
||||||
|
|
||||||
if (isBlob) {
|
if (isBlob) {
|
||||||
ContentResolver cr = getContentResolver();
|
ContentResolver cr = getContentResolver();
|
||||||
try {
|
try {
|
||||||
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
|
OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
|
||||||
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
|
.name())));
|
||||||
|
writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()),
|
||||||
|
outStream);
|
||||||
outStream.close();
|
outStream.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "... exception on writing blob", e);
|
Log.e(TAG, "... exception on writing blob", e);
|
@ -14,12 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
@ -66,8 +67,8 @@ public class AskForSecretKeyPassPhrase {
|
|||||||
alert.setMessage(context.getString(R.string.passPhraseFor, userId));
|
alert.setMessage(context.getString(R.string.passPhraseFor, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutInflater inflater =
|
LayoutInflater inflater = (LayoutInflater) context
|
||||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
View view = inflater.inflate(R.layout.pass_phrase, null);
|
View view = inflater.inflate(R.layout.pass_phrase, null);
|
||||||
final EditText input = (EditText) view.findViewById(R.id.passPhrase);
|
final EditText input = (EditText) view.findViewById(R.id.passPhrase);
|
||||||
final EditText inputNotUsed = (EditText) view.findViewById(R.id.passPhraseAgain);
|
final EditText inputNotUsed = (EditText) view.findViewById(R.id.passPhraseAgain);
|
||||||
@ -76,26 +77,23 @@ public class AskForSecretKeyPassPhrase {
|
|||||||
alert.setView(view);
|
alert.setView(view);
|
||||||
|
|
||||||
final PassPhraseCallbackInterface cb = callback;
|
final PassPhraseCallbackInterface cb = callback;
|
||||||
alert.setPositiveButton(android.R.string.ok,
|
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
activity.removeDialog(Id.dialog.pass_phrase);
|
activity.removeDialog(Id.dialog.pass_phrase);
|
||||||
String passPhrase = "" + input.getText();
|
String passPhrase = "" + input.getText();
|
||||||
long keyId;
|
long keyId;
|
||||||
if (secretKey != null) {
|
if (secretKey != null) {
|
||||||
try {
|
try {
|
||||||
PGPPrivateKey testKey = secretKey.extractPrivateKey(passPhrase.toCharArray(),
|
PGPPrivateKey testKey = secretKey.extractPrivateKey(
|
||||||
new BouncyCastleProvider());
|
passPhrase.toCharArray(), new BouncyCastleProvider());
|
||||||
if (testKey == null) {
|
if (testKey == null) {
|
||||||
Toast.makeText(activity,
|
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
|
||||||
R.string.error_couldNotExtractPrivateKey,
|
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
Toast.makeText(activity,
|
Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
|
||||||
R.string.wrongPassPhrase,
|
.show();
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keyId = secretKey.getKeyID();
|
keyId = secretKey.getKeyID();
|
||||||
@ -106,8 +104,7 @@ public class AskForSecretKeyPassPhrase {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel,
|
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
activity.removeDialog(Id.dialog.pass_phrase);
|
activity.removeDialog(Id.dialog.pass_phrase);
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
public class CachedPassPhrase {
|
public class CachedPassPhrase {
|
||||||
public final long timestamp;
|
public final long timestamp;
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import android.os.Environment;
|
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.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -7,7 +7,8 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -56,8 +57,8 @@ public class DataSource {
|
|||||||
return mData != null || mContentUri != null;
|
return mData != null || mContentUri != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputData getInputData(Context context, boolean withSize)
|
public InputData getInputData(Context context, boolean withSize) throws GeneralException,
|
||||||
throws GeneralException, FileNotFoundException, IOException {
|
FileNotFoundException, IOException {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
long size = 0;
|
long size = 0;
|
||||||
|
|
||||||
@ -67,7 +68,8 @@ public class DataSource {
|
|||||||
String path = Uri.decode(mContentUri.toString().substring(7));
|
String path = Uri.decode(mContentUri.toString().substring(7));
|
||||||
if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
|
if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
|
||||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
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);
|
in = new FileInputStream(path);
|
@ -14,7 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
@ -41,18 +43,17 @@ public class FileDialog {
|
|||||||
|
|
||||||
public static interface OnClickListener {
|
public static interface OnClickListener {
|
||||||
public void onCancelClick();
|
public void onCancelClick();
|
||||||
|
|
||||||
public void onOkClick(String filename, boolean checkbox);
|
public void onOkClick(String filename, boolean checkbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AlertDialog build(Activity activity, String title, String message,
|
public static AlertDialog build(Activity activity, String title, String message,
|
||||||
String defaultFile, OnClickListener onClickListener,
|
String defaultFile, OnClickListener onClickListener, String fileManagerTitle,
|
||||||
String fileManagerTitle, String fileManagerButton,
|
String fileManagerButton, String checkboxText, int requestCode) {
|
||||||
String checkboxText,
|
|
||||||
int requestCode) {
|
|
||||||
// TODO: fileManagerTitle and fileManagerButton are deprecated, no use for them right now,
|
// 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
|
// but maybe the Intent now used will someday support them again, so leaving them in
|
||||||
LayoutInflater inflater =
|
LayoutInflater inflater = (LayoutInflater) activity
|
||||||
(LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
||||||
|
|
||||||
alert.setTitle(title);
|
alert.setTitle(title);
|
||||||
@ -92,13 +93,11 @@ public class FileDialog {
|
|||||||
if (mCheckBox.isEnabled()) {
|
if (mCheckBox.isEnabled()) {
|
||||||
checked = mCheckBox.isChecked();
|
checked = mCheckBox.isChecked();
|
||||||
}
|
}
|
||||||
clickListener.onOkClick(mFilename.getText().toString(),
|
clickListener.onOkClick(mFilename.getText().toString(), checked);
|
||||||
checked);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel,
|
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
clickListener.onCancelClick();
|
clickListener.onCancelClick();
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -56,9 +56,15 @@ public class HkpKeyServer extends KeyServer {
|
|||||||
private short mPort = 11371;
|
private short mPort = 11371;
|
||||||
|
|
||||||
// example:
|
// 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>
|
// pub 2048R/<a href="/pks/lookup?op=get&search=0x887DF4BE9F5C9090">9F5C9090</a> 2009-08-17 <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);
|
// href="/pks/lookup?op=vindex&search=0x887DF4BE9F5C9090">Jörg Runge
|
||||||
public static Pattern USER_ID_LINE = Pattern.compile("^ +(.+)$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
|
// <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) {
|
public HkpKeyServer(String host) {
|
||||||
mHost = host;
|
mHost = host;
|
||||||
@ -119,7 +125,8 @@ public class HkpKeyServer extends KeyServer {
|
|||||||
|
|
||||||
// TODO: replace this with httpclient
|
// TODO: replace this with httpclient
|
||||||
@Override
|
@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>();
|
Vector<KeyInfo> results = new Vector<KeyInfo>();
|
||||||
|
|
||||||
if (query.length() < 3) {
|
if (query.length() < 3) {
|
||||||
@ -160,7 +167,8 @@ public class HkpKeyServer extends KeyServer {
|
|||||||
info.keyId = Apg.keyFromHex(matcher.group(3));
|
info.keyId = Apg.keyFromHex(matcher.group(3));
|
||||||
info.fingerPrint = Apg.getSmallFingerPrint(info.keyId);
|
info.fingerPrint = Apg.getSmallFingerPrint(info.keyId);
|
||||||
String chunks[] = matcher.group(4).split("-");
|
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>();
|
info.userIds = new Vector<String>();
|
||||||
if (matcher.group(5).startsWith("*** KEY")) {
|
if (matcher.group(5).startsWith("*** KEY")) {
|
||||||
info.revoked = matcher.group(5);
|
info.revoked = matcher.group(5);
|
||||||
@ -184,10 +192,11 @@ public class HkpKeyServer extends KeyServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String get(long keyId) throws QueryException {
|
public String get(long keyId) throws QueryException {
|
||||||
HttpClient client = new DefaultHttpClient();
|
HttpClient client = new DefaultHttpClient();
|
||||||
try {
|
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);
|
HttpResponse response = client.execute(get);
|
||||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
interface IApgService {
|
interface IApgService {
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ public class InputData {
|
|||||||
private PositionAwareInputStream mInputStream;
|
private PositionAwareInputStream mInputStream;
|
||||||
private long mSize;
|
private long mSize;
|
||||||
|
|
||||||
InputData(InputStream inputStream, long size) {
|
public InputData(InputStream inputStream, long size) {
|
||||||
mInputStream = new PositionAwareInputStream(inputStream);
|
mInputStream = new PositionAwareInputStream(inputStream);
|
||||||
mSize = size;
|
mSize = size;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -8,6 +8,7 @@ import java.util.Vector;
|
|||||||
public abstract class KeyServer {
|
public abstract class KeyServer {
|
||||||
static public class QueryException extends Exception {
|
static public class QueryException extends Exception {
|
||||||
private static final long serialVersionUID = 2703768928624654512L;
|
private static final long serialVersionUID = 2703768928624654512L;
|
||||||
|
|
||||||
public QueryException(String message) {
|
public QueryException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
@ -27,16 +28,19 @@ public abstract class KeyServer {
|
|||||||
|
|
||||||
static public class KeyInfo implements Serializable {
|
static public class KeyInfo implements Serializable {
|
||||||
private static final long serialVersionUID = -7797972113284992662L;
|
private static final long serialVersionUID = -7797972113284992662L;
|
||||||
Vector<String> userIds;
|
public Vector<String> userIds;
|
||||||
String revoked;
|
public String revoked;
|
||||||
Date date;
|
public Date date;
|
||||||
String fingerPrint;
|
public String fingerPrint;
|
||||||
long keyId;
|
public long keyId;
|
||||||
int size;
|
public int size;
|
||||||
String algorithm;
|
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 String get(long keyId) throws QueryException;
|
||||||
|
|
||||||
abstract void add(String armouredText) throws AddKeyException;
|
abstract void add(String armouredText) throws AddKeyException;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
public class PausableThread extends Thread {
|
public class PausableThread extends Thread {
|
||||||
private boolean mPaused = false;
|
private boolean mPaused = false;
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||||
@ -16,16 +16,14 @@ public class Preferences {
|
|||||||
return getPreferences(context, false);
|
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) {
|
if (mPreferences == null || force_new) {
|
||||||
mPreferences = new Preferences(context);
|
mPreferences = new Preferences(context);
|
||||||
}
|
}
|
||||||
return mPreferences;
|
return mPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Preferences(Context context)
|
private Preferences(Context context) {
|
||||||
{
|
|
||||||
mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_PRIVATE);
|
mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,8 +118,7 @@ public class Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSeenChangeLog(String version) {
|
public boolean hasSeenChangeLog(String version) {
|
||||||
return mSharedPreferences.getBoolean(Constants.pref.has_seen_change_log + version,
|
return mSharedPreferences.getBoolean(Constants.pref.has_seen_change_log + version, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHasSeenChangeLog(String version, boolean value) {
|
public void setHasSeenChangeLog(String version, boolean value) {
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
@ -14,10 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg;
|
||||||
|
|
||||||
public interface ProgressDialogUpdater {
|
public interface ProgressDialogUpdater {
|
||||||
void setProgress(String message, int current, int total);
|
void setProgress(String message, int current, int total);
|
||||||
|
|
||||||
void setProgress(int resourceId, int current, int total);
|
void setProgress(int resourceId, int current, int total);
|
||||||
|
|
||||||
void setProgress(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.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.provider;
|
package org.apg.provider;
|
||||||
|
|
||||||
import android.provider.BaseColumns;
|
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.ContentUris;
|
||||||
import android.content.ContentValues;
|
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.apg.ApgService;
|
||||||
import org.thialfihar.android.apg.Constants;
|
import org.apg.Constants;
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
@ -14,13 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.provider;
|
package org.apg.provider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.Id;
|
import org.apg.Id;
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
import android.content.ContentValues;
|
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.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
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.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.provider;
|
package org.apg.provider;
|
||||||
|
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.provider;
|
package org.apg.provider;
|
||||||
|
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.provider;
|
package org.apg.provider;
|
||||||
|
|
||||||
import android.provider.BaseColumns;
|
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.
|
* 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.jce.provider.BouncyCastleProvider;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.thialfihar.android.apg.provider.DataProvider;
|
import org.apg.R;
|
||||||
import org.thialfihar.android.apg.utils.Compatibility;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
@ -14,15 +14,19 @@
|
|||||||
* limitations under the License.
|
* 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.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.thialfihar.android.apg.provider.Database;
|
import org.apg.R;
|
||||||
import org.thialfihar.android.apg.ui.widget.KeyEditor;
|
|
||||||
import org.thialfihar.android.apg.ui.widget.SectionView;
|
|
||||||
import org.thialfihar.android.apg.utils.IterableIterator;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -104,8 +108,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
mSaveButton.setOnClickListener(this);
|
mSaveButton.setOnClickListener(this);
|
||||||
mDiscardButton.setOnClickListener(this);
|
mDiscardButton.setOnClickListener(this);
|
||||||
|
|
||||||
LayoutInflater inflater =
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
|
|
||||||
LinearLayout container = (LinearLayout) findViewById(R.id.container);
|
LinearLayout container = (LinearLayout) findViewById(R.id.container);
|
||||||
mUserIds = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
mUserIds = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||||
@ -124,7 +127,8 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
|
|
||||||
updatePassPhraseButtonText();
|
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();
|
Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,16 +140,16 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean havePassPhrase() {
|
public boolean havePassPhrase() {
|
||||||
return (!mCurrentPassPhrase.equals("")) ||
|
return (!mCurrentPassPhrase.equals(""))
|
||||||
(mNewPassPhrase != null && !mNewPassPhrase.equals(""));
|
|| (mNewPassPhrase != null && !mNewPassPhrase.equals(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences)
|
menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences).setIcon(
|
||||||
.setIcon(android.R.drawable.ic_menu_preferences);
|
android.R.drawable.ic_menu_preferences);
|
||||||
menu.add(0, Id.menu.option.about, 1, R.string.menu_about)
|
menu.add(0, Id.menu.option.about, 1, R.string.menu_about).setIcon(
|
||||||
.setIcon(android.R.drawable.ic_menu_info_details);
|
android.R.drawable.ic_menu_info_details);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,16 +166,14 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
alert.setMessage(R.string.enterPassPhraseTwice);
|
alert.setMessage(R.string.enterPassPhraseTwice);
|
||||||
|
|
||||||
LayoutInflater inflater =
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
View view = inflater.inflate(R.layout.pass_phrase, null);
|
View view = inflater.inflate(R.layout.pass_phrase, null);
|
||||||
final EditText input1 = (EditText) view.findViewById(R.id.passPhrase);
|
final EditText input1 = (EditText) view.findViewById(R.id.passPhrase);
|
||||||
final EditText input2 = (EditText) view.findViewById(R.id.passPhraseAgain);
|
final EditText input2 = (EditText) view.findViewById(R.id.passPhraseAgain);
|
||||||
|
|
||||||
alert.setView(view);
|
alert.setView(view);
|
||||||
|
|
||||||
alert.setPositiveButton(android.R.string.ok,
|
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
removeDialog(Id.dialog.new_pass_phrase);
|
removeDialog(Id.dialog.new_pass_phrase);
|
||||||
|
|
||||||
@ -192,8 +194,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel,
|
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
removeDialog(Id.dialog.new_pass_phrase);
|
removeDialog(Id.dialog.new_pass_phrase);
|
||||||
}
|
}
|
||||||
@ -275,8 +276,8 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
|
|
||||||
String error = data.getString(Apg.EXTRA_ERROR);
|
String error = data.getString(Apg.EXTRA_ERROR);
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
Toast.makeText(EditKeyActivity.this,
|
Toast.makeText(EditKeyActivity.this, getString(R.string.errorMessage, error),
|
||||||
getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(EditKeyActivity.this, R.string.keySaved, Toast.LENGTH_SHORT).show();
|
Toast.makeText(EditKeyActivity.this, R.string.keySaved, Toast.LENGTH_SHORT).show();
|
||||||
setResult(RESULT_OK);
|
setResult(RESULT_OK);
|
||||||
@ -285,7 +286,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updatePassPhraseButtonText() {
|
private void updatePassPhraseButtonText() {
|
||||||
mChangePassPhrase.setText(
|
mChangePassPhrase.setText(havePassPhrase() ? R.string.btn_changePassPhrase
|
||||||
havePassPhrase() ? R.string.btn_changePassPhrase : R.string.btn_setPassPhrase);
|
: R.string.btn_setPassPhrase);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,16 +14,24 @@
|
|||||||
* limitations under the License.
|
* 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.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.thialfihar.android.apg.provider.DataProvider;
|
import org.apg.R;
|
||||||
import org.thialfihar.android.apg.utils.Choice;
|
|
||||||
import org.thialfihar.android.apg.utils.Compatibility;
|
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
@ -205,14 +213,14 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
|
|
||||||
mFileCompression = (Spinner) findViewById(R.id.fileCompression);
|
mFileCompression = (Spinner) findViewById(R.id.fileCompression);
|
||||||
Choice[] choices = new Choice[] {
|
Choice[] choices = new Choice[] {
|
||||||
new Choice(Id.choice.compression.none, getString(R.string.choice_none) +
|
new Choice(Id.choice.compression.none, getString(R.string.choice_none) + " ("
|
||||||
" (" + getString(R.string.fast) + ")"),
|
+ getString(R.string.fast) + ")"),
|
||||||
new Choice(Id.choice.compression.zip, "ZIP (" + 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.zlib, "ZLIB (" + getString(R.string.fast) + ")"),
|
||||||
new Choice(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.very_slow) + ")"),
|
new Choice(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.very_slow)
|
||||||
};
|
+ ")"), };
|
||||||
ArrayAdapter<Choice> adapter =
|
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(this,
|
||||||
new ArrayAdapter<Choice>(this, android.R.layout.simple_spinner_item, choices);
|
android.R.layout.simple_spinner_item, choices);
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
mFileCompression.setAdapter(adapter);
|
mFileCompression.setAdapter(adapter);
|
||||||
|
|
||||||
@ -265,18 +273,18 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
mIntent = getIntent();
|
mIntent = getIntent();
|
||||||
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction()) ||
|
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction())
|
||||||
Apg.Intent.ENCRYPT_FILE.equals(mIntent.getAction()) ||
|
|| Apg.Intent.ENCRYPT_FILE.equals(mIntent.getAction())
|
||||||
Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction()) ||
|
|| Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())
|
||||||
Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
|
|| Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
|
||||||
mContentUri = mIntent.getData();
|
mContentUri = mIntent.getData();
|
||||||
Bundle extras = mIntent.getExtras();
|
Bundle extras = mIntent.getExtras();
|
||||||
if (extras == null) {
|
if (extras == null) {
|
||||||
extras = new Bundle();
|
extras = new Bundle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction()) ||
|
if (Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())
|
||||||
Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
|
|| Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
|
||||||
mReturnResult = true;
|
mReturnResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,9 +349,9 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction()) ||
|
if (Apg.Intent.ENCRYPT.equals(mIntent.getAction())
|
||||||
Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction()) ||
|
|| Apg.Intent.ENCRYPT_AND_RETURN.equals(mIntent.getAction())
|
||||||
Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
|
|| Apg.Intent.GENERATE_SIGNATURE.equals(mIntent.getAction())) {
|
||||||
if (textData != null) {
|
if (textData != null) {
|
||||||
mMessage.setText(textData);
|
mMessage.setText(textData);
|
||||||
}
|
}
|
||||||
@ -385,11 +393,9 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
|
|
||||||
updateButtons();
|
updateButtons();
|
||||||
|
|
||||||
if (mReturnResult &&
|
if (mReturnResult
|
||||||
(mMessage.getText().length() > 0 || mData != null || mContentUri != null) &&
|
&& (mMessage.getText().length() > 0 || mData != null || mContentUri != null)
|
||||||
((mEncryptionKeyIds != null &&
|
&& ((mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) || getSecretKeyId() != 0)) {
|
||||||
mEncryptionKeyIds.length > 0) ||
|
|
||||||
getSecretKeyId() != 0)) {
|
|
||||||
encryptClicked();
|
encryptClicked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,8 +556,9 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
if (!mInputFilename.startsWith("content")) {
|
if (!mInputFilename.startsWith("content")) {
|
||||||
File file = new File(mInputFilename);
|
File file = new File(mInputFilename);
|
||||||
if (!file.exists() || !file.isFile()) {
|
if (!file.exists() || !file.isFile()) {
|
||||||
Toast.makeText(this, getString(R.string.errorMessage,
|
Toast.makeText(
|
||||||
getString(R.string.error_fileNotFound)),
|
this,
|
||||||
|
getString(R.string.errorMessage, getString(R.string.error_fileNotFound)),
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -582,8 +589,8 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!encryptIt && getSecretKeyId() == 0) {
|
if (!encryptIt && getSecretKeyId() == 0) {
|
||||||
Toast.makeText(this, R.string.selectEncryptionOrSignatureKey,
|
Toast.makeText(this, R.string.selectEncryptionOrSignatureKey, Toast.LENGTH_SHORT)
|
||||||
Toast.LENGTH_SHORT).show();
|
.show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,26 +674,20 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
|
|
||||||
if (mGenerateSignature) {
|
if (mGenerateSignature) {
|
||||||
Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(),
|
Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(),
|
||||||
getSecretKeyId(),
|
getSecretKeyId(), Apg.getCachedPassPhrase(getSecretKeyId()),
|
||||||
Apg.getCachedPassPhrase(getSecretKeyId()),
|
|
||||||
mPreferences.getDefaultHashAlgorithm(),
|
mPreferences.getDefaultHashAlgorithm(),
|
||||||
mPreferences.getForceV3Signatures(),
|
mPreferences.getForceV3Signatures(), this);
|
||||||
this);
|
|
||||||
} else if (signOnly) {
|
} else if (signOnly) {
|
||||||
Apg.signText(this, in, out, getSecretKeyId(),
|
Apg.signText(this, in, out, getSecretKeyId(),
|
||||||
Apg.getCachedPassPhrase(getSecretKeyId()),
|
Apg.getCachedPassPhrase(getSecretKeyId()),
|
||||||
mPreferences.getDefaultHashAlgorithm(),
|
mPreferences.getDefaultHashAlgorithm(),
|
||||||
mPreferences.getForceV3Signatures(),
|
mPreferences.getForceV3Signatures(), this);
|
||||||
this);
|
|
||||||
} else {
|
} else {
|
||||||
Apg.encrypt(this, in, out, useAsciiArmour,
|
Apg.encrypt(this, in, out, useAsciiArmour, encryptionKeyIds, signatureKeyId,
|
||||||
encryptionKeyIds, signatureKeyId,
|
|
||||||
Apg.getCachedPassPhrase(signatureKeyId), this,
|
Apg.getCachedPassPhrase(signatureKeyId), this,
|
||||||
mPreferences.getDefaultEncryptionAlgorithm(),
|
mPreferences.getDefaultEncryptionAlgorithm(),
|
||||||
mPreferences.getDefaultHashAlgorithm(),
|
mPreferences.getDefaultHashAlgorithm(), compressionId,
|
||||||
compressionId,
|
mPreferences.getForceV3Signatures(), passPhrase);
|
||||||
mPreferences.getForceV3Signatures(),
|
|
||||||
passPhrase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.close();
|
out.close();
|
||||||
@ -746,8 +747,8 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
} else if (mEncryptionKeyIds.length == 1) {
|
} else if (mEncryptionKeyIds.length == 1) {
|
||||||
mSelectKeysButton.setText(R.string.oneKeySelected);
|
mSelectKeysButton.setText(R.string.oneKeySelected);
|
||||||
} else {
|
} else {
|
||||||
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " " +
|
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " "
|
||||||
getResources().getString(R.string.nKeysSelected));
|
+ getResources().getString(R.string.nKeysSelected));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSecretKeyId() == 0) {
|
if (getSecretKeyId() == 0) {
|
||||||
@ -875,15 +876,16 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
Bundle data = msg.getData();
|
Bundle data = msg.getData();
|
||||||
String error = data.getString(Apg.EXTRA_ERROR);
|
String error = data.getString(Apg.EXTRA_ERROR);
|
||||||
if (error != null) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
switch (mEncryptTarget) {
|
switch (mEncryptTarget) {
|
||||||
case Id.target.clipboard: {
|
case Id.target.clipboard: {
|
||||||
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
|
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
|
||||||
Compatibility.copyToClipboard(this, message);
|
Compatibility.copyToClipboard(this, message);
|
||||||
Toast.makeText(this, R.string.encryptionToClipboardSuccessful,
|
Toast.makeText(this, R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT)
|
||||||
Toast.LENGTH_SHORT).show();
|
.show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,15 +903,12 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
emailIntent.setType("text/plain; charset=utf-8");
|
emailIntent.setType("text/plain; charset=utf-8");
|
||||||
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
|
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
|
||||||
if (mSubject != null) {
|
if (mSubject != null) {
|
||||||
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
|
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mSubject);
|
||||||
mSubject);
|
|
||||||
}
|
}
|
||||||
if (mSendTo != null) {
|
if (mSendTo != null) {
|
||||||
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
|
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { mSendTo });
|
||||||
new String[] { mSendTo });
|
|
||||||
}
|
}
|
||||||
EncryptActivity.this.
|
EncryptActivity.this.startActivity(Intent.createChooser(emailIntent,
|
||||||
startActivity(Intent.createChooser(emailIntent,
|
|
||||||
getString(R.string.title_sendEmail)));
|
getString(R.string.title_sendEmail)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -935,8 +934,7 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
switch (id) {
|
switch (id) {
|
||||||
case Id.dialog.output_filename: {
|
case Id.dialog.output_filename: {
|
||||||
return FileDialog.build(this, getString(R.string.title_encryptToFile),
|
return FileDialog.build(this, getString(R.string.title_encryptToFile),
|
||||||
getString(R.string.specifyFileToEncryptTo),
|
getString(R.string.specifyFileToEncryptTo), mOutputFilename,
|
||||||
mOutputFilename,
|
|
||||||
new FileDialog.OnClickListener() {
|
new FileDialog.OnClickListener() {
|
||||||
public void onOkClick(String filename, boolean checked) {
|
public void onOkClick(String filename, boolean checked) {
|
||||||
removeDialog(Id.dialog.output_filename);
|
removeDialog(Id.dialog.output_filename);
|
||||||
@ -947,11 +945,8 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
public void onCancelClick() {
|
public void onCancelClick() {
|
||||||
removeDialog(Id.dialog.output_filename);
|
removeDialog(Id.dialog.output_filename);
|
||||||
}
|
}
|
||||||
},
|
}, getString(R.string.filemanager_titleSave),
|
||||||
getString(R.string.filemanager_titleSave),
|
getString(R.string.filemanager_btnSave), null, Id.request.output_filename);
|
||||||
getString(R.string.filemanager_btnSave),
|
|
||||||
null,
|
|
||||||
Id.request.output_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -6,7 +6,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Vector;
|
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.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
@ -1,11 +1,16 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
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.PGPKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.thialfihar.android.apg.KeyServer.QueryException;
|
import org.apg.R;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
@ -14,14 +14,20 @@
|
|||||||
* limitations under the License.
|
* 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.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.thialfihar.android.apg.provider.KeyRings;
|
import org.apg.R;
|
||||||
import org.thialfihar.android.apg.provider.Keys;
|
|
||||||
import org.thialfihar.android.apg.provider.UserIds;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
@ -14,13 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.ui.widget.Editor;
|
import org.apg.Apg;
|
||||||
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
|
import org.apg.ui.widget.Editor;
|
||||||
import org.thialfihar.android.apg.ui.widget.KeyServerEditor;
|
import org.apg.ui.widget.KeyServerEditor;
|
||||||
|
import org.apg.ui.widget.Editor.EditorListener;
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
@ -1,12 +1,17 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.KeyServer.InsufficientQuery;
|
import org.apg.Apg;
|
||||||
import org.thialfihar.android.apg.KeyServer.KeyInfo;
|
import org.apg.Constants;
|
||||||
import org.thialfihar.android.apg.KeyServer.QueryException;
|
import org.apg.HkpKeyServer;
|
||||||
import org.thialfihar.android.apg.KeyServer.TooManyResponses;
|
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.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
@ -14,11 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
import org.apg.Apg;
|
||||||
|
import org.apg.Preferences;
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
@ -14,14 +14,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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.spongycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.thialfihar.android.apg.provider.Accounts;
|
import org.apg.R;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
@ -14,11 +14,20 @@
|
|||||||
* limitations under the License.
|
* 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.bcpg.HashAlgorithmTags;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||||
import org.thialfihar.android.apg.ui.widget.IntegerListPreference;
|
import org.apg.R;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
@ -14,9 +14,18 @@
|
|||||||
* limitations under the License.
|
* 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.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
@ -14,7 +14,19 @@
|
|||||||
* limitations under the License.
|
* 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.app.Dialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
@ -14,10 +14,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.util.Vector;
|
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.app.SearchManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
@ -14,13 +14,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.provider.KeyRings;
|
import org.apg.Apg;
|
||||||
import org.thialfihar.android.apg.provider.Keys;
|
import org.apg.Id;
|
||||||
import org.thialfihar.android.apg.provider.UserIds;
|
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.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
@ -14,7 +14,13 @@
|
|||||||
* limitations under the License.
|
* 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.app.SearchManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
@ -1,10 +1,14 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.provider.KeyRings;
|
import org.apg.Apg;
|
||||||
import org.thialfihar.android.apg.provider.Keys;
|
import org.apg.Id;
|
||||||
import org.thialfihar.android.apg.provider.UserIds;
|
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.app.Activity;
|
||||||
import android.content.Context;
|
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.PGPKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
@ -1,10 +1,19 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.apg.ui;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Iterator;
|
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.jce.provider.BouncyCastleProvider;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||||
@ -16,6 +25,7 @@ import org.spongycastle.openpgp.PGPSignatureGenerator;
|
|||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
|
import org.apg.R;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.ui.widget;
|
package org.apg.ui.widget;
|
||||||
|
|
||||||
public interface Editor {
|
public interface Editor {
|
||||||
public interface EditorListener {
|
public interface EditorListener {
|
@ -14,7 +14,7 @@
|
|||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.ui.widget;
|
package org.apg.ui.widget;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
@ -14,14 +14,14 @@
|
|||||||
* limitations under the License.
|
* 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.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.thialfihar.android.apg.Apg;
|
import org.apg.R;
|
||||||
import org.thialfihar.android.apg.Id;
|
|
||||||
import org.thialfihar.android.apg.R;
|
|
||||||
import org.thialfihar.android.apg.utils.Choice;
|
|
||||||
|
|
||||||
import android.app.DatePickerDialog;
|
import android.app.DatePickerDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
@ -14,9 +14,9 @@
|
|||||||
* limitations under the License.
|
* 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.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
@ -14,15 +14,15 @@
|
|||||||
* limitations under the License.
|
* 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.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.thialfihar.android.apg.Apg;
|
import org.apg.R;
|
||||||
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 android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
@ -14,12 +14,12 @@
|
|||||||
* limitations under the License.
|
* 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.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.R;
|
import org.apg.R;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.utils;
|
package org.apg.util;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.IApgService;
|
import org.apg.util.ApgConInterface.OnCallFinishListener;
|
||||||
import org.thialfihar.android.apg.utils.ApgConInterface.OnCallFinishListener;
|
import org.apg.IApgService;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg.utils;
|
package org.apg.util;
|
||||||
|
|
||||||
public interface ApgConInterface {
|
public interface ApgConInterface {
|
||||||
public static interface OnCallFinishListener {
|
public static interface OnCallFinishListener {
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.utils;
|
package org.apg.util;
|
||||||
|
|
||||||
public class Choice {
|
public class Choice {
|
||||||
private String mName;
|
private String mName;
|
@ -1,4 +1,4 @@
|
|||||||
package org.thialfihar.android.apg.utils;
|
package org.apg.util;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.thialfihar.android.apg.utils;
|
package org.apg.util;
|
||||||
|
|
||||||
import java.util.Iterator;
|
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