set svn:eol-style to LF for all code/resource files

This commit is contained in:
Thialfihar
2010-07-16 20:13:12 +00:00
parent ec10329664
commit f5efd73d33
37 changed files with 7339 additions and 7339 deletions

View File

@@ -1,38 +1,38 @@
<?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.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<LinearLayout <LinearLayout
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"
android:paddingBottom="5dip" android:paddingBottom="5dip"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/filterInfo" android:id="@+id/filterInfo"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="end"/> android:ellipsize="end"/>
<Button <Button
android:id="@+id/btn_clear" android:id="@+id/btn_clear"
android:text="@string/btn_clearFilter" android:text="@string/btn_clearFilter"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>

View File

@@ -1,80 +1,80 @@
<?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.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:singleLine="true" android:singleLine="true"
android:paddingLeft="10dip" android:paddingLeft="10dip"
android:layout_marginRight="?android:attr/scrollbarSize" android:layout_marginRight="?android:attr/scrollbarSize"
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingRight="3dip"> android:paddingRight="3dip">
<ImageView <ImageView
android:id="@+id/ic_masterKey" android:id="@+id/ic_masterKey"
android:src="@drawable/key_small" android:src="@drawable/key_small"
android:paddingRight="6dip" android:paddingRight="6dip"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/> android:layout_gravity="center_vertical"/>
<TextView <TextView
android:id="@+id/keyId" android:id="@+id/keyId"
android:text="Key ID" android:text="Key ID"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingRight="5dip" android:paddingRight="5dip"
android:typeface="monospace"/> android:typeface="monospace"/>
<TextView <TextView
android:id="@+id/keyDetails" android:id="@+id/keyDetails"
android:text="(RSA, 1024bit)" android:text="(RSA, 1024bit)"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<LinearLayout <LinearLayout
android:gravity="right" android:gravity="right"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingBottom="2dip" android:paddingBottom="2dip"
android:paddingTop="2dip" android:paddingTop="2dip"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_gravity="center_vertical"> android:layout_gravity="center_vertical">
<ImageView <ImageView
android:id="@+id/ic_encryptKey" android:id="@+id/ic_encryptKey"
android:src="@drawable/encrypted_small" android:src="@drawable/encrypted_small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<ImageView <ImageView
android:id="@+id/ic_signKey" android:id="@+id/ic_signKey"
android:src="@drawable/signed_small" android:src="@drawable/signed_small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -1,33 +1,33 @@
<?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.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingLeft="40dip" android:paddingLeft="40dip"
android:layout_marginRight="?android:attr/scrollbarSize" android:layout_marginRight="?android:attr/scrollbarSize"
android:singleLine="true" android:singleLine="true"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"> android:layout_height="?android:attr/listPreferredItemHeight">
<TextView <TextView
android:id="@+id/userId" android:id="@+id/userId"
android:text="User ID" android:text="User ID"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingRight="3dip"/> android:paddingRight="3dip"/>
</LinearLayout> </LinearLayout>

View File

@@ -1,258 +1,258 @@
<?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.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="app_name">APG</string> <string name="app_name">APG</string>
<!-- title_lowerCase: capitalized words, no punctuation --> <!-- title_lowerCase: capitalized words, no punctuation -->
<string name="title_mailInbox">Mail Inbox</string> <string name="title_mailInbox">Mail Inbox</string>
<string name="title_managePublicKeys">Administrér Offentlige Nøgler</string> <string name="title_managePublicKeys">Administrér Offentlige Nøgler</string>
<string name="title_manageSecretKeys">Administrér Private Nøgler</string> <string name="title_manageSecretKeys">Administrér Private Nøgler</string>
<string name="title_selectRecipients">Vælg Modtagere</string> <string name="title_selectRecipients">Vælg Modtagere</string>
<string name="title_selectSignature">Vælg Signatur</string> <string name="title_selectSignature">Vælg Signatur</string>
<string name="title_encrypt">Kryptér</string> <string name="title_encrypt">Kryptér</string>
<string name="title_decrypt">Afkryptér</string> <string name="title_decrypt">Afkryptér</string>
<string name="title_authentification">Autentificering</string> <string name="title_authentification">Autentificering</string>
<string name="title_createKey">Opret Nøgle</string> <string name="title_createKey">Opret Nøgle</string>
<string name="title_editKey">Redigér Nøgle</string> <string name="title_editKey">Redigér Nøgle</string>
<string name="title_preferences">Indstillinger</string> <string name="title_preferences">Indstillinger</string>
<string name="title_changePassPhrase">Skift Kodeord</string> <string name="title_changePassPhrase">Skift Kodeord</string>
<string name="title_setPassPhrase">Sæt Kodeord</string> <string name="title_setPassPhrase">Sæt Kodeord</string>
<string name="title_sendEmail">"Send Mail..."</string> <string name="title_sendEmail">"Send Mail..."</string>
<string name="title_encryptToFile">Kryptér Til Fil</string> <string name="title_encryptToFile">Kryptér Til Fil</string>
<string name="title_decryptToFile">Afkryptér Til Fil</string> <string name="title_decryptToFile">Afkryptér Til Fil</string>
<string name="title_addAccount">Tilføj Konto</string> <string name="title_addAccount">Tilføj Konto</string>
<string name="title_importKeys">Importér Nøgle</string> <string name="title_importKeys">Importér Nøgle</string>
<string name="title_exportKey">Eksportér Nøgle</string> <string name="title_exportKey">Eksportér Nøgle</string>
<string name="title_exportKeys">Eksportér Nøgler</string> <string name="title_exportKeys">Eksportér Nøgler</string>
<string name="title_keyNotFound">Ingen Nøgle Matchede</string> <string name="title_keyNotFound">Ingen Nøgle Matchede</string>
<!-- section_lowerCase: capitalized words, no punctuation --> <!-- section_lowerCase: capitalized words, no punctuation -->
<string name="section_userIds">Bruger ID</string> <string name="section_userIds">Bruger ID</string>
<string name="section_keys">Nøgler</string> <string name="section_keys">Nøgler</string>
<string name="section_general">Generelt</string> <string name="section_general">Generelt</string>
<string name="section_defaults">Standard Indstillinger</string> <string name="section_defaults">Standard Indstillinger</string>
<!-- btn_lowerCase: capitalized words, no punctuation --> <!-- btn_lowerCase: capitalized words, no punctuation -->
<string name="btn_encryptToClipboard">Kryptér Til Clipboard</string> <string name="btn_encryptToClipboard">Kryptér Til Clipboard</string>
<string name="btn_send">Kryptér Og Mail</string> <string name="btn_send">Kryptér Og Mail</string>
<string name="btn_encrypt">Kryptér</string> <string name="btn_encrypt">Kryptér</string>
<string name="btn_decrypt">Afkryptér</string> <string name="btn_decrypt">Afkryptér</string>
<string name="btn_verify">Bekræft</string> <string name="btn_verify">Bekræft</string>
<string name="btn_selectEncryptKeys">Vælg Modtagere</string> <string name="btn_selectEncryptKeys">Vælg Modtagere</string>
<string name="btn_reply">Svar</string> <string name="btn_reply">Svar</string>
<string name="btn_encryptMessage">Kryptér Besked</string> <string name="btn_encryptMessage">Kryptér Besked</string>
<string name="btn_decryptMessage">Afkryptér Besked</string> <string name="btn_decryptMessage">Afkryptér Besked</string>
<string name="btn_encryptFile">Kryptér Fil</string> <string name="btn_encryptFile">Kryptér Fil</string>
<string name="btn_decryptFile">Afkryptér Fil</string> <string name="btn_decryptFile">Afkryptér Fil</string>
<string name="btn_save">Gem</string> <string name="btn_save">Gem</string>
<string name="btn_doNotSave">Fortryd</string> <string name="btn_doNotSave">Fortryd</string>
<string name="btn_delete">Slet</string> <string name="btn_delete">Slet</string>
<string name="btn_noDate">Ingen</string> <string name="btn_noDate">Ingen</string>
<string name="btn_clearFilter">Ryd Filter</string> <string name="btn_clearFilter">Ryd Filter</string>
<!-- menu_lowerCase: capitalized words, no punctuation --> <!-- menu_lowerCase: capitalized words, no punctuation -->
<string name="menu_about">Om APG</string> <string name="menu_about">Om APG</string>
<string name="menu_addAccount">Tilføj GMail Konto</string> <string name="menu_addAccount">Tilføj GMail Konto</string>
<string name="menu_deleteAccount">Slet Konto</string> <string name="menu_deleteAccount">Slet Konto</string>
<string name="menu_managePublicKeys">Administrér Offentlige Nøgler</string> <string name="menu_managePublicKeys">Administrér Offentlige Nøgler</string>
<string name="menu_manageSecretKeys">Administrér Private Nøgler</string> <string name="menu_manageSecretKeys">Administrér Private Nøgler</string>
<string name="menu_preferences">Indstillinger</string> <string name="menu_preferences">Indstillinger</string>
<string name="menu_changePassPhrase">Skift Kodeord</string> <string name="menu_changePassPhrase">Skift Kodeord</string>
<string name="menu_setPassPhrase">Sæt Kodeord</string> <string name="menu_setPassPhrase">Sæt Kodeord</string>
<string name="menu_importKeys">Importér Nøgler</string> <string name="menu_importKeys">Importér Nøgler</string>
<string name="menu_exportKeys">Eksportér Nøgler</string> <string name="menu_exportKeys">Eksportér Nøgler</string>
<string name="menu_exportKey">Eksportér Nøgle</string> <string name="menu_exportKey">Eksportér Nøgle</string>
<string name="menu_deleteKey">Slet Nøgle</string> <string name="menu_deleteKey">Slet Nøgle</string>
<string name="menu_createKey">Opret Nøgle</string> <string name="menu_createKey">Opret Nøgle</string>
<string name="menu_editKey">Redigér Nøgle</string> <string name="menu_editKey">Redigér Nøgle</string>
<string name="menu_search">Søg</string> <string name="menu_search">Søg</string>
<!-- label_lowerCase: capitalized words, no punctuation --> <!-- label_lowerCase: capitalized words, no punctuation -->
<string name="label_sign">Signér</string> <string name="label_sign">Signér</string>
<string name="label_message">Besked</string> <string name="label_message">Besked</string>
<string name="label_file">Fil</string> <string name="label_file">Fil</string>
<string name="label_passPhrase">Kodeord</string> <string name="label_passPhrase">Kodeord</string>
<string name="label_passPhraseAgain">Igen</string> <string name="label_passPhraseAgain">Igen</string>
<string name="label_algorithm">Algoritme</string> <string name="label_algorithm">Algoritme</string>
<string name="label_asciiArmour">ASCII Rustning</string> <string name="label_asciiArmour">ASCII Rustning</string>
<string name="label_selectPublicKeys">Offentlig(e) Nøgle(r)</string> <string name="label_selectPublicKeys">Offentlig(e) Nøgle(r)</string>
<string name="label_deleteAfterEncryption">Slet Efter Kryptering</string> <string name="label_deleteAfterEncryption">Slet Efter Kryptering</string>
<string name="label_deleteAfterDecryption">Slet Efter Afkryptering</string> <string name="label_deleteAfterDecryption">Slet Efter Afkryptering</string>
<string name="label_encryptionAlgorithm">Krypteringsalgoritme</string> <string name="label_encryptionAlgorithm">Krypteringsalgoritme</string>
<string name="label_hashAlgorithm">Hash-algoritme</string> <string name="label_hashAlgorithm">Hash-algoritme</string>
<string name="label_asymmetric">Offentlig Nøgle</string> <string name="label_asymmetric">Offentlig Nøgle</string>
<string name="label_symmetric">Kodeord</string> <string name="label_symmetric">Kodeord</string>
<string name="label_passPhraseCacheTtl">Kodeords Cache</string> <string name="label_passPhraseCacheTtl">Kodeords Cache</string>
<string name="label_messageCompression">Besked Komprimering</string> <string name="label_messageCompression">Besked Komprimering</string>
<string name="label_fileCompression">Fil Komprimering</string> <string name="label_fileCompression">Fil Komprimering</string>
<string name="noKeysSelected">Vælg</string> <string name="noKeysSelected">Vælg</string>
<string name="oneKeySelected">1 Valgt</string> <string name="oneKeySelected">1 Valgt</string>
<string name="nKeysSelected">Valgt</string> <string name="nKeysSelected">Valgt</string>
<string name="unknownUserId">&lt;ukendt&gt;</string> <string name="unknownUserId">&lt;ukendt&gt;</string>
<string name="none">&lt;ingen&gt;</string> <string name="none">&lt;ingen&gt;</string>
<string name="noKey">&lt;ingen nøgle&gt;</string> <string name="noKey">&lt;ingen nøgle&gt;</string>
<string name="noDate">-</string> <string name="noDate">-</string>
<string name="noExpiry">&lt;udløber ikke&gt;</string> <string name="noExpiry">&lt;udløber ikke&gt;</string>
<string name="unknownStatus"></string> <string name="unknownStatus"></string>
<string name="canEncrypt">kan kryptere</string> <string name="canEncrypt">kan kryptere</string>
<string name="canSign">kan signere</string> <string name="canSign">kan signere</string>
<string name="expired">udløbet</string> <string name="expired">udløbet</string>
<string name="notValid">ugyldig</string> <string name="notValid">ugyldig</string>
<!-- choice_lowerCase: capitalized firwst word, no punctuation --> <!-- choice_lowerCase: capitalized firwst word, no punctuation -->
<string name="choice_none">Ingen</string> <string name="choice_none">Ingen</string>
<string name="choice_signOnly">Kun signering</string> <string name="choice_signOnly">Kun signering</string>
<string name="choice_encryptOnly">Kun kryptering</string> <string name="choice_encryptOnly">Kun kryptering</string>
<string name="choice_signAndEncrypt">Signér og kryptér</string> <string name="choice_signAndEncrypt">Signér og kryptér</string>
<string name="choice_15secs">15 secs</string> <string name="choice_15secs">15 secs</string>
<string name="choice_1min">1 min</string> <string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string> <string name="choice_3mins">3 min</string>
<string name="choice_5mins">5 min</string> <string name="choice_5mins">5 min</string>
<string name="choice_10mins">10 min</string> <string name="choice_10mins">10 min</string>
<string name="choice_untilQuit">Indtil slut</string> <string name="choice_untilQuit">Indtil slut</string>
<string name="dsa">DSA</string> <string name="dsa">DSA</string>
<string name="elgamal">ElGamal</string> <string name="elgamal">ElGamal</string>
<string name="rsa">RSA</string> <string name="rsa">RSA</string>
<string name="filemanager_titleOpen">Åbn...</string> <string name="filemanager_titleOpen">Åbn...</string>
<string name="filemanager_titleSave">Gem Som...</string> <string name="filemanager_titleSave">Gem Som...</string>
<string name="filemanager_titleEncrypt">Vælg Fil Som Skal Krypteres...</string> <string name="filemanager_titleEncrypt">Vælg Fil Som Skal Krypteres...</string>
<string name="filemanager_titleDecrypt">Vælg Fil Som Skal Afkrypteres...</string> <string name="filemanager_titleDecrypt">Vælg Fil Som Skal Afkrypteres...</string>
<string name="filemanager_btnOpen">Åbn</string> <string name="filemanager_btnOpen">Åbn</string>
<string name="filemanager_btnSave">Gem</string> <string name="filemanager_btnSave">Gem</string>
<string name="warning">Advarsel</string> <string name="warning">Advarsel</string>
<string name="error">Fejl</string> <string name="error">Fejl</string>
<string name="warningMessage">Advarsel: %s</string> <string name="warningMessage">Advarsel: %s</string>
<string name="errorMessage">Fejl: %s</string> <string name="errorMessage">Fejl: %s</string>
<!-- sentences --> <!-- sentences -->
<string name="wrongPassPhrase">Forkert kodeord.</string> <string name="wrongPassPhrase">Forkert kodeord.</string>
<string name="usingClipboardContent">Bruger clipboardets indhold.</string> <string name="usingClipboardContent">Bruger clipboardets indhold.</string>
<string name="keySaved">Nøgle gemt.</string> <string name="keySaved">Nøgle gemt.</string>
<string name="setAPassPhrase">Sæt et kodeord via Indstillinger først.</string> <string name="setAPassPhrase">Sæt et kodeord via Indstillinger først.</string>
<string name="noFilemanagerInstalled">Der er ikke installeret en kompatibel fil håndtering.</string> <string name="noFilemanagerInstalled">Der er ikke installeret en kompatibel fil håndtering.</string>
<string name="passPhrasesDoNotMatch">Kodeordet matchede ikke.</string> <string name="passPhrasesDoNotMatch">Kodeordet matchede ikke.</string>
<string name="passPhraseMustNotBeEmpty">Et tomt kodeord er ikke tilladt.</string> <string name="passPhraseMustNotBeEmpty">Et tomt kodeord er ikke tilladt.</string>
<string name="passPhraseForSymmetricEncryption">Kodeord til symmetrisk kryptering:</string> <string name="passPhraseForSymmetricEncryption">Kodeord til symmetrisk kryptering:</string>
<string name="passPhraseFor">Kodeord til %s:</string> <string name="passPhraseFor">Kodeord til %s:</string>
<string name="fileDeleteConfirmation">Er du sikker på at du vil slette \n%s?</string> <string name="fileDeleteConfirmation">Er du sikker på at du vil slette \n%s?</string>
<string name="fileDeleteSuccessful">Filen er slettet.</string> <string name="fileDeleteSuccessful">Filen er slettet.</string>
<string name="noFileSelected">Vælg en fil først.</string> <string name="noFileSelected">Vælg en fil først.</string>
<string name="decryptionSuccessful">Afkryptering lykkedes.</string> <string name="decryptionSuccessful">Afkryptering lykkedes.</string>
<string name="encryptionSuccessful">Kryptering lykkedes.</string> <string name="encryptionSuccessful">Kryptering lykkedes.</string>
<string name="encryptionToClipboardSuccessful">Kryptering til clipboard lykkedes.</string> <string name="encryptionToClipboardSuccessful">Kryptering til clipboard lykkedes.</string>
<string name="enterPassPhraseTwice">Tast kodeordet to gange.</string> <string name="enterPassPhraseTwice">Tast kodeordet to gange.</string>
<string name="selectEncryptionKey">Vælg mindst én krypteringsnøgle.</string> <string name="selectEncryptionKey">Vælg mindst én krypteringsnøgle.</string>
<string name="selectEncryptionOrSignatureKey">Vælg mindst én krypteringsnøgle eller signaturnøgle.</string> <string name="selectEncryptionOrSignatureKey">Vælg mindst én krypteringsnøgle eller signaturnøgle.</string>
<string name="specifyFileToEncryptTo">Angiv navnet på filen der skal krypteres til.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string> <string name="specifyFileToEncryptTo">Angiv navnet på filen der skal krypteres til.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string>
<string name="specifyFileToDecryptTo">Angiv navnet på filen der skal afkrypteres til.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string> <string name="specifyFileToDecryptTo">Angiv navnet på filen der skal afkrypteres til.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string>
<string name="specifyGoogleMailAccount">Angiv den Google Mail konto du ønsker at tilføje.</string> <string name="specifyGoogleMailAccount">Angiv den Google Mail konto du ønsker at tilføje.</string>
<string name="specifyFileToImportFrom">Angiv hvilken fil du ønsker at importere nøgler fra. (.asc eller .gpg)</string> <string name="specifyFileToImportFrom">Angiv hvilken fil du ønsker at importere nøgler fra. (.asc eller .gpg)</string>
<string name="specifyFileToExportTo">Angiv hvilken fil der skal eksporteres til.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string> <string name="specifyFileToExportTo">Angiv hvilken fil der skal eksporteres til.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string>
<string name="specifyFileToExportSecretKeysTo">Angiv hvilken fil der skal eksporteres til.\nADVARSEL! Du er ved at eksportere PRIVATE nøgler.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string> <string name="specifyFileToExportSecretKeysTo">Angiv hvilken fil der skal eksporteres til.\nADVARSEL! Du er ved at eksportere PRIVATE nøgler.\nADVARSEL! Filen vil blive overskrevet hvis den allerede eksisterer.</string>
<string name="keyDeletionConfirmation">Ønsker du at slette \'%s\'-nøglen?\nDu kan ikke fortryde denne handling!</string> <string name="keyDeletionConfirmation">Ønsker du at slette \'%s\'-nøglen?\nDu kan ikke fortryde denne handling!</string>
<string name="secretKeyDeletionConfirmation">Ønsker du at slette den PRIVATE nøgle, \'%s\'?\nDu kan ikke fortryde denne handling!</string> <string name="secretKeyDeletionConfirmation">Ønsker du at slette den PRIVATE nøgle, \'%s\'?\nDu kan ikke fortryde denne handling!</string>
<string name="keysAddedAndUpdated">Tilføjelse af %s nøgle(r) og opdatering af %s nøgle(r) lykkedes."</string> <string name="keysAddedAndUpdated">Tilføjelse af %s nøgle(r) og opdatering af %s nøgle(r) lykkedes."</string>
<string name="keysAdded">Tilføjelse af %s nøgle(r) lykkedes.</string> <string name="keysAdded">Tilføjelse af %s nøgle(r) lykkedes.</string>
<string name="keysUpdated">Opdatring af %s nøgle(r) lykkedes.</string> <string name="keysUpdated">Opdatring af %s nøgle(r) lykkedes.</string>
<string name="noKeysAddedOrUpdated">Ingen nøgler blev tilføjet eller opdateret.</string> <string name="noKeysAddedOrUpdated">Ingen nøgler blev tilføjet eller opdateret.</string>
<string name="keyExported">Eksport af 1 nøgle lykkedes.</string> <string name="keyExported">Eksport af 1 nøgle lykkedes.</string>
<string name="keysExported">Eksport af %s nøgler lykkedes.</string> <string name="keysExported">Eksport af %s nøgler lykkedes.</string>
<string name="noKeysExported">Ingen nøgler blev eksporteret.</string> <string name="noKeysExported">Ingen nøgler blev eksporteret.</string>
<string name="keyCreationElGamalInfo">NB: Kun undernøgler understøtter ElGamal, og for ELGamal vil den nærmeste nøglestørrelse - 1536, 2048, 3072, 4096, eller 8192 - blive brugt.</string> <string name="keyCreationElGamalInfo">NB: Kun undernøgler understøtter ElGamal, og for ELGamal vil den nærmeste nøglestørrelse - 1536, 2048, 3072, 4096, eller 8192 - blive brugt.</string>
<string name="keyNotFound">Kunne ikke finde %08X nøglen.</string> <string name="keyNotFound">Kunne ikke finde %08X nøglen.</string>
<!-- error_lowerCase: phrases, no punctuation, all lowercase, <!-- error_lowerCase: phrases, no punctuation, all lowercase,
they will be put after "errorMessage", e.g. "Error: file not found" --> they will be put after "errorMessage", e.g. "Error: file not found" -->
<string name="error_fileDeleteFailed">\'%s\' kunne ikke slettes</string> <string name="error_fileDeleteFailed">\'%s\' kunne ikke slettes</string>
<string name="error_fileNotFound">filen findes ikke</string> <string name="error_fileNotFound">filen findes ikke</string>
<string name="error_noSecretKeyFound">ingen egnet privat nøgle fundet</string> <string name="error_noSecretKeyFound">ingen egnet privat nøgle fundet</string>
<string name="error_noKnownEncryptionFound">ingen kendt krypterings måde fundet</string> <string name="error_noKnownEncryptionFound">ingen kendt krypterings måde fundet</string>
<string name="error_externalStorageNotReady">ekstern storage er ikke parat</string> <string name="error_externalStorageNotReady">ekstern storage er ikke parat</string>
<string name="error_accountNotFound">\'%s\'-kontoen blev ikke fundet</string> <string name="error_accountNotFound">\'%s\'-kontoen blev ikke fundet</string>
<string name="error_addingAccountFailed">\'%s\'-kontoen kunne ikke tilføjes</string> <string name="error_addingAccountFailed">\'%s\'-kontoen kunne ikke tilføjes</string>
<string name="error_invalidEmail">ugyldig email \'%s\'</string> <string name="error_invalidEmail">ugyldig email \'%s\'</string>
<string name="error_keySizeMinimum512bit">nøgle størrelsen skal være på mindst 512bit</string> <string name="error_keySizeMinimum512bit">nøgle størrelsen skal være på mindst 512bit</string>
<string name="error_masterKeyMustNotBeElGamal">hoved nøglen kan ikke være en ElGamal nøgle</string> <string name="error_masterKeyMustNotBeElGamal">hoved nøglen kan ikke være en ElGamal nøgle</string>
<string name="error_unknownAlgorithmChoice">ukendt algoritme valg</string> <string name="error_unknownAlgorithmChoice">ukendt algoritme valg</string>
<string name="error_userIdNeedsAName">angiv et navn</string> <string name="error_userIdNeedsAName">angiv et navn</string>
<string name="error_userIdNeedsAnEmailAddress">angiv en email adresse</string> <string name="error_userIdNeedsAnEmailAddress">angiv en email adresse</string>
<string name="error_keyNeedsAUserId">der skal bruges mindst ét bruger-id</string> <string name="error_keyNeedsAUserId">der skal bruges mindst ét bruger-id</string>
<string name="error_mainUserIdMustNotBeEmpty">hovedbruger-id kan ikke være tomt</string> <string name="error_mainUserIdMustNotBeEmpty">hovedbruger-id kan ikke være tomt</string>
<string name="error_keyNeedsMasterKey">der skal mindst bruges en hovednøgle</string> <string name="error_keyNeedsMasterKey">der skal mindst bruges en hovednøgle</string>
<string name="error_expiryMustComeAfterCreation">udløbsdatoen skal være senere end oprettelsesdatoen</string> <string name="error_expiryMustComeAfterCreation">udløbsdatoen skal være senere end oprettelsesdatoen</string>
<string name="error_noEncryptionKeysOrPassPhrase">hverken krypteringsnøgler eller kodeord modtaget</string> <string name="error_noEncryptionKeysOrPassPhrase">hverken krypteringsnøgler eller kodeord modtaget</string>
<string name="error_signatureFailed">signering mislykkedes</string> <string name="error_signatureFailed">signering mislykkedes</string>
<string name="error_noSignaturePassPhrase">intet kodeord modtaget</string> <string name="error_noSignaturePassPhrase">intet kodeord modtaget</string>
<string name="error_noSignatureKey">ingen signatur nøgle modtaget</string> <string name="error_noSignatureKey">ingen signatur nøgle modtaget</string>
<string name="error_invalidData">ikke gyldig krypteringsdata</string> <string name="error_invalidData">ikke gyldig krypteringsdata</string>
<string name="error_corruptData">beskadiget data</string> <string name="error_corruptData">beskadiget data</string>
<string name="error_noSymmetricEncryptionPacket">kunne ikke finde en pakke med symmetrisk kryptering</string> <string name="error_noSymmetricEncryptionPacket">kunne ikke finde en pakke med symmetrisk kryptering</string>
<string name="error_wrongPassPhrase">forkert kodeord</string> <string name="error_wrongPassPhrase">forkert kodeord</string>
<string name="error_savingKeys">der opstod en fejl da nøglen eller nøglerne skulle gemmes</string> <string name="error_savingKeys">der opstod en fejl da nøglen eller nøglerne skulle gemmes</string>
<!-- progress_lowerCase: lowercase, phrases, usually ending in '...' --> <!-- progress_lowerCase: lowercase, phrases, usually ending in '...' -->
<string name="progress_done">færdig.</string> <string name="progress_done">færdig.</string>
<string name="progress_initializing">starter op...</string> <string name="progress_initializing">starter op...</string>
<string name="progress_saving">gemmer...</string> <string name="progress_saving">gemmer...</string>
<string name="progress_importing">importerer...</string> <string name="progress_importing">importerer...</string>
<string name="progress_exporting">eksporterer...</string> <string name="progress_exporting">eksporterer...</string>
<string name="progress_generating">genererer nøgle, dette kan tage et stykke tid...</string> <string name="progress_generating">genererer nøgle, dette kan tage et stykke tid...</string>
<string name="progress_buildingKey">opbygger nøgle...</string> <string name="progress_buildingKey">opbygger nøgle...</string>
<string name="progress_preparingMasterKey">forbereder hovednøgle...</string> <string name="progress_preparingMasterKey">forbereder hovednøgle...</string>
<string name="progress_certifyingMasterKey">bekræfter hovednøgle...</string> <string name="progress_certifyingMasterKey">bekræfter hovednøgle...</string>
<string name="progress_buildingMasterKeyRing">bygger hovednøglering...</string> <string name="progress_buildingMasterKeyRing">bygger hovednøglering...</string>
<string name="progress_addingSubKeys">tilføjer undernøgler...</string> <string name="progress_addingSubKeys">tilføjer undernøgler...</string>
<string name="progress_savingKeyRing">gemmer nøglering...</string> <string name="progress_savingKeyRing">gemmer nøglering...</string>
<string name="progress_importingSecretKeys">importerer private nøgler...</string> <string name="progress_importingSecretKeys">importerer private nøgler...</string>
<string name="progress_importingPublicKeys">importerer offentlige nøgler...</string> <string name="progress_importingPublicKeys">importerer offentlige nøgler...</string>
<string name="progress_reloadingKeys">genloader nøgler...</string> <string name="progress_reloadingKeys">genloader nøgler...</string>
<string name="progress_exportingKey">eksporterer nøgle...</string> <string name="progress_exportingKey">eksporterer nøgle...</string>
<string name="progress_exportingKeys">eksporterer nøgler...</string> <string name="progress_exportingKeys">eksporterer nøgler...</string>
<string name="progress_extractingSignatureKey">henter signatur nøgle...</string> <string name="progress_extractingSignatureKey">henter signatur nøgle...</string>
<string name="progress_extractingKey">henter nøgle...</string> <string name="progress_extractingKey">henter nøgle...</string>
<string name="progress_preparingStreams">forbereder streams...</string> <string name="progress_preparingStreams">forbereder streams...</string>
<string name="progress_encrypting">krypterer data...</string> <string name="progress_encrypting">krypterer data...</string>
<string name="progress_decrypting">afkrypterer data...</string> <string name="progress_decrypting">afkrypterer data...</string>
<string name="progress_preparingSignature">forbereder signatur...</string> <string name="progress_preparingSignature">forbereder signatur...</string>
<string name="progress_generatingSignature">skaber signatur...</string> <string name="progress_generatingSignature">skaber signatur...</string>
<string name="progress_processingSignature">behandler signatur...</string> <string name="progress_processingSignature">behandler signatur...</string>
<string name="progress_verifyingSignature">bekræfter signatur...</string> <string name="progress_verifyingSignature">bekræfter signatur...</string>
<string name="progress_signing">signerer...</string> <string name="progress_signing">signerer...</string>
<string name="progress_readingData">læser data...</string> <string name="progress_readingData">læser data...</string>
<string name="progress_findingKey">søger nøgle...</string> <string name="progress_findingKey">søger nøgle...</string>
<string name="progress_decompressingData">afkomprimerer data...</string> <string name="progress_decompressingData">afkomprimerer data...</string>
<string name="progress_verifyingIntegrity">bekræfter integritet...</string> <string name="progress_verifyingIntegrity">bekræfter integritet...</string>
<!-- permission strings --> <!-- permission strings -->
<string name="permission_read_key_details_label">Læs nøgle detaljer fra APG.</string> <string name="permission_read_key_details_label">Læs nøgle detaljer fra APG.</string>
<string name="permission_read_key_details_description">Læs om offentlige og private nøgler gemt i APG, f. eks. nøgle ID og bruger ID. Selve nøglerne kan IKKE læses.</string> <string name="permission_read_key_details_description">Læs om offentlige og private nøgler gemt i APG, f. eks. nøgle ID og bruger ID. Selve nøglerne kan IKKE læses.</string>
<!-- action strings --> <!-- action strings -->
<string name="action_encrypt">Kryptér</string> <string name="action_encrypt">Kryptér</string>
<string name="action_decrypt">Afkryptér</string> <string name="action_decrypt">Afkryptér</string>
<string name="action_importPublic">Importér Offentlige Nøgler</string> <string name="action_importPublic">Importér Offentlige Nøgler</string>
<string name="action_importSecret">Importér Private Nøgler</string> <string name="action_importSecret">Importér Private Nøgler</string>
<string name="hint_publicKeys">Søg I Offentlige Nøgler</string> <string name="hint_publicKeys">Søg I Offentlige Nøgler</string>
<string name="hint_secretKeys">Søg I Private Nøgler</string> <string name="hint_secretKeys">Søg I Private Nøgler</string>
<string name="filterInfo">Filter: \"%s\"</string> <string name="filterInfo">Filter: \"%s\"</string>
</resources> </resources>

File diff suppressed because it is too large Load Diff

View File

@@ -1,112 +1,112 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import org.bouncycastle2.jce.provider.BouncyCastleProvider; import org.bouncycastle2.jce.provider.BouncyCastleProvider;
import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKey;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
public class AskForSecretKeyPassPhrase { public class AskForSecretKeyPassPhrase {
public static interface PassPhraseCallbackInterface { public static interface PassPhraseCallbackInterface {
void passPhraseCallback(long keyId, String passPhrase); void passPhraseCallback(long keyId, String passPhrase);
} }
public static Dialog createDialog(Activity context, long secretKeyId, public static Dialog createDialog(Activity context, long secretKeyId,
PassPhraseCallbackInterface callback) { PassPhraseCallbackInterface callback) {
AlertDialog.Builder alert = new AlertDialog.Builder(context); AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(R.string.title_authentification); alert.setTitle(R.string.title_authentification);
final PGPSecretKey secretKey; final PGPSecretKey secretKey;
final Activity activity = context; final Activity activity = context;
if (secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none) { if (secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none) {
secretKey = null; secretKey = null;
alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption)); alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption));
} else { } else {
secretKey = Apg.getMasterKey(Apg.getSecretKeyRing(secretKeyId)); secretKey = Apg.getMasterKey(Apg.getSecretKeyRing(secretKeyId));
if (secretKey == null) { if (secretKey == null) {
alert.setTitle(R.string.title_keyNotFound); alert.setTitle(R.string.title_keyNotFound);
alert.setMessage(context.getString(R.string.keyNotFound, secretKeyId)); alert.setMessage(context.getString(R.string.keyNotFound, secretKeyId));
alert.setPositiveButton(android.R.string.ok, new OnClickListener() { alert.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
activity.removeDialog(Id.dialog.pass_phrase); activity.removeDialog(Id.dialog.pass_phrase);
} }
}); });
alert.setCancelable(false); alert.setCancelable(false);
return alert.create(); return alert.create();
} }
String userId = Apg.getMainUserIdSafe(context, secretKey); String userId = Apg.getMainUserIdSafe(context, secretKey);
alert.setMessage(context.getString(R.string.passPhraseFor, userId)); alert.setMessage(context.getString(R.string.passPhraseFor, userId));
} }
LayoutInflater inflater = LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); (LayoutInflater) context.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);
inputNotUsed.setVisibility(View.GONE); inputNotUsed.setVisibility(View.GONE);
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 {
secretKey.extractPrivateKey(passPhrase.toCharArray(), secretKey.extractPrivateKey(passPhrase.toCharArray(),
new BouncyCastleProvider()); new BouncyCastleProvider());
} catch (PGPException e) { } catch (PGPException e) {
Toast.makeText(activity, Toast.makeText(activity,
R.string.wrongPassPhrase, R.string.wrongPassPhrase,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
return; return;
} }
keyId = secretKey.getKeyID(); keyId = secretKey.getKeyID();
} else { } else {
keyId = Id.key.symmetric; keyId = Id.key.symmetric;
} }
cb.passPhraseCallback(keyId, passPhrase); cb.passPhraseCallback(keyId, passPhrase);
} }
}); });
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);
} }
}); });
return alert.create(); return alert.create();
} }
} }

View File

@@ -1,381 +1,381 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.File; import java.io.File;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class BaseActivity extends Activity public class BaseActivity extends Activity
implements Runnable, ProgressDialogUpdater, implements Runnable, ProgressDialogUpdater,
AskForSecretKeyPassPhrase.PassPhraseCallbackInterface { AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
private ProgressDialog mProgressDialog = null; private ProgressDialog mProgressDialog = null;
private Thread mRunningThread = null; private Thread mRunningThread = null;
private long mSecretKeyId = 0; private long mSecretKeyId = 0;
private String mDeleteFile = null; private String mDeleteFile = null;
protected Preferences mPreferences; protected Preferences mPreferences;
private Handler mHandler = new Handler() { private Handler mHandler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
handlerCallback(msg); handlerCallback(msg);
} }
}; };
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mPreferences = Preferences.getPreferences(this); mPreferences = Preferences.getPreferences(this);
Apg.initialize(this); Apg.initialize(this);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File dir = new File(Constants.path.app_dir); File dir = new File(Constants.path.app_dir);
if (!dir.exists() && !dir.mkdirs()) { if (!dir.exists() && !dir.mkdirs()) {
// ignore this for now, it's not crucial // ignore this for now, it's not crucial
// that the directory doesn't exist at this point // that the directory doesn't exist at this point
} }
} }
startCacheService(this, mPreferences); startCacheService(this, mPreferences);
} }
public static void startCacheService(Activity activity, Preferences preferences) { public static void startCacheService(Activity activity, Preferences preferences) {
Intent intent = new Intent(activity, Service.class); Intent intent = new Intent(activity, Service.class);
intent.putExtra(Service.EXTRA_TTL, preferences.getPassPhraseCacheTtl()); intent.putExtra(Service.EXTRA_TTL, preferences.getPassPhraseCacheTtl());
activity.startService(intent); activity.startService(intent);
} }
@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(android.R.drawable.ic_menu_preferences); .setIcon(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(android.R.drawable.ic_menu_info_details); .setIcon(android.R.drawable.ic_menu_info_details);
return true; return true;
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case Id.menu.option.about: { case Id.menu.option.about: {
showDialog(Id.dialog.about); showDialog(Id.dialog.about);
return true; return true;
} }
case Id.menu.option.preferences: { case Id.menu.option.preferences: {
startActivity(new Intent(this, PreferencesActivity.class)); startActivity(new Intent(this, PreferencesActivity.class));
return true; return true;
} }
case Id.menu.option.search: { case Id.menu.option.search: {
startSearch("", false, null, false); startSearch("", false, null, false);
return true; return true;
} }
default: { default: {
break; break;
} }
} }
return false; return false;
} }
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
// in case it is a progress dialog // in case it is a progress dialog
mProgressDialog = new ProgressDialog(this); mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false); mProgressDialog.setCancelable(false);
switch (id) { switch (id) {
case Id.dialog.encrypting: { case Id.dialog.encrypting: {
mProgressDialog.setMessage(this.getString(R.string.progress_initializing)); mProgressDialog.setMessage(this.getString(R.string.progress_initializing));
return mProgressDialog; return mProgressDialog;
} }
case Id.dialog.decrypting: { case Id.dialog.decrypting: {
mProgressDialog.setMessage(this.getString(R.string.progress_initializing)); mProgressDialog.setMessage(this.getString(R.string.progress_initializing));
return mProgressDialog; return mProgressDialog;
} }
case Id.dialog.saving: { case Id.dialog.saving: {
mProgressDialog.setMessage(this.getString(R.string.progress_saving)); mProgressDialog.setMessage(this.getString(R.string.progress_saving));
return mProgressDialog; return mProgressDialog;
} }
case Id.dialog.importing: { case Id.dialog.importing: {
mProgressDialog.setMessage(this.getString(R.string.progress_importing)); mProgressDialog.setMessage(this.getString(R.string.progress_importing));
return mProgressDialog; return mProgressDialog;
} }
case Id.dialog.exporting: { case Id.dialog.exporting: {
mProgressDialog.setMessage(this.getString(R.string.progress_exporting)); mProgressDialog.setMessage(this.getString(R.string.progress_exporting));
return mProgressDialog; return mProgressDialog;
} }
default: { default: {
break; break;
} }
} }
mProgressDialog = null; mProgressDialog = null;
switch (id) { switch (id) {
case Id.dialog.about: { case Id.dialog.about: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("About " + Apg.getFullVersion(this)); alert.setTitle("About " + Apg.getFullVersion(this));
LayoutInflater inflater = LayoutInflater inflater =
(LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.info, null); View layout = inflater.inflate(R.layout.info, null);
TextView message = (TextView) layout.findViewById(R.id.message); TextView message = (TextView) layout.findViewById(R.id.message);
message.setText("This is an attempt to bring OpenPGP to Android. " + 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" + "It is far from complete, but more features are planned (see website).\n\n" +
"Feel free to send bug reports, suggestions, feature requests, feedback, " + "Feel free to send bug reports, suggestions, feature requests, feedback, " +
"photographs.\n\n" + "photographs.\n\n" +
"mail: thi@thialfihar.org\n" + "mail: thi@thialfihar.org\n" +
"site: http://apg.thialfihar.org\n\n" + "site: http://apg.thialfihar.org\n\n" +
"This software is provided \"as is\", without warranty of any kind."); "This software is provided \"as is\", without warranty of any kind.");
alert.setView(layout); alert.setView(layout);
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) {
BaseActivity.this.removeDialog(Id.dialog.about); BaseActivity.this.removeDialog(Id.dialog.about);
} }
}); });
return alert.create(); return alert.create();
} }
case Id.dialog.pass_phrase: { case Id.dialog.pass_phrase: {
return AskForSecretKeyPassPhrase.createDialog(this, getSecretKeyId(), this); return AskForSecretKeyPassPhrase.createDialog(this, getSecretKeyId(), this);
} }
case Id.dialog.pass_phrases_do_not_match: { case Id.dialog.pass_phrases_do_not_match: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert); alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.error); alert.setTitle(R.string.error);
alert.setMessage(R.string.passPhrasesDoNotMatch); alert.setMessage(R.string.passPhrasesDoNotMatch);
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.pass_phrases_do_not_match); removeDialog(Id.dialog.pass_phrases_do_not_match);
} }
}); });
alert.setCancelable(false); alert.setCancelable(false);
return alert.create(); return alert.create();
} }
case Id.dialog.no_pass_phrase: { case Id.dialog.no_pass_phrase: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert); alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.error); alert.setTitle(R.string.error);
alert.setMessage(R.string.passPhraseMustNotBeEmpty); alert.setMessage(R.string.passPhraseMustNotBeEmpty);
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.no_pass_phrase); removeDialog(Id.dialog.no_pass_phrase);
} }
}); });
alert.setCancelable(false); alert.setCancelable(false);
return alert.create(); return alert.create();
} }
case Id.dialog.delete_file: { case Id.dialog.delete_file: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert); alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning); alert.setTitle(R.string.warning);
alert.setMessage(this.getString(R.string.fileDeleteConfirmation, getDeleteFile())); alert.setMessage(this.getString(R.string.fileDeleteConfirmation, getDeleteFile()));
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.delete_file); removeDialog(Id.dialog.delete_file);
File file = new File(getDeleteFile()); File file = new File(getDeleteFile());
String msg = ""; String msg = "";
if (file.delete()) { if (file.delete()) {
msg = BaseActivity.this.getString( msg = BaseActivity.this.getString(
R.string.fileDeleteSuccessful); R.string.fileDeleteSuccessful);
} else { } else {
msg = BaseActivity.this.getString( msg = BaseActivity.this.getString(
R.string.errorMessage, R.string.errorMessage,
BaseActivity.this.getString( BaseActivity.this.getString(
R.string.error_fileDeleteFailed, file)); R.string.error_fileDeleteFailed, file));
} }
Toast.makeText(BaseActivity.this, Toast.makeText(BaseActivity.this,
msg, Toast.LENGTH_SHORT).show(); msg, Toast.LENGTH_SHORT).show();
} }
}); });
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.delete_file); removeDialog(Id.dialog.delete_file);
} }
}); });
alert.setCancelable(true); alert.setCancelable(true);
return alert.create(); return alert.create();
} }
default: { default: {
break; break;
} }
} }
return super.onCreateDialog(id); return super.onCreateDialog(id);
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case Id.request.secret_keys: { case Id.request.secret_keys: {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras(); Bundle bundle = data.getExtras();
setSecretKeyId(bundle.getLong(Apg.EXTRA_KEY_ID)); setSecretKeyId(bundle.getLong(Apg.EXTRA_KEY_ID));
} else { } else {
setSecretKeyId(Id.key.none); setSecretKeyId(Id.key.none);
} }
break; break;
} }
default: { default: {
break; break;
} }
} }
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
public void setProgress(int resourceId, int progress, int max) { public void setProgress(int resourceId, int progress, int max) {
setProgress(getString(resourceId), progress, max); setProgress(getString(resourceId), progress, max);
} }
public void setProgress(int progress, int max) { public void setProgress(int progress, int max) {
Message msg = new Message(); Message msg = new Message();
Bundle data = new Bundle(); Bundle data = new Bundle();
data.putInt(Apg.EXTRA_STATUS, Id.message.progress_update); data.putInt(Apg.EXTRA_STATUS, Id.message.progress_update);
data.putInt(Apg.EXTRA_PROGRESS, progress); data.putInt(Apg.EXTRA_PROGRESS, progress);
data.putInt(Apg.EXTRA_MAX, max); data.putInt(Apg.EXTRA_MAX, max);
msg.setData(data); msg.setData(data);
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
} }
public void setProgress(String message, int progress, int max) { public void setProgress(String message, int progress, int max) {
Message msg = new Message(); Message msg = new Message();
Bundle data = new Bundle(); Bundle data = new Bundle();
data.putInt(Apg.EXTRA_STATUS, Id.message.progress_update); data.putInt(Apg.EXTRA_STATUS, Id.message.progress_update);
data.putString(Apg.EXTRA_MESSAGE, message); data.putString(Apg.EXTRA_MESSAGE, message);
data.putInt(Apg.EXTRA_PROGRESS, progress); data.putInt(Apg.EXTRA_PROGRESS, progress);
data.putInt(Apg.EXTRA_MAX, max); data.putInt(Apg.EXTRA_MAX, max);
msg.setData(data); msg.setData(data);
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
} }
public void handlerCallback(Message msg) { public void handlerCallback(Message msg) {
Bundle data = msg.getData(); Bundle data = msg.getData();
if (data == null) { if (data == null) {
return; return;
} }
int type = data.getInt(Apg.EXTRA_STATUS); int type = data.getInt(Apg.EXTRA_STATUS);
switch (type) { switch (type) {
case Id.message.progress_update: { case Id.message.progress_update: {
String message = data.getString(Apg.EXTRA_MESSAGE); String message = data.getString(Apg.EXTRA_MESSAGE);
if (mProgressDialog != null) { if (mProgressDialog != null) {
if (message != null) { if (message != null) {
mProgressDialog.setMessage(message); mProgressDialog.setMessage(message);
} }
mProgressDialog.setMax(data.getInt(Apg.EXTRA_MAX)); mProgressDialog.setMax(data.getInt(Apg.EXTRA_MAX));
mProgressDialog.setProgress(data.getInt(Apg.EXTRA_PROGRESS)); mProgressDialog.setProgress(data.getInt(Apg.EXTRA_PROGRESS));
} }
break; break;
} }
case Id.message.import_done: // intentionall no break case Id.message.import_done: // intentionall no break
case Id.message.export_done: // intentionall no break case Id.message.export_done: // intentionall no break
case Id.message.done: { case Id.message.done: {
mProgressDialog = null; mProgressDialog = null;
doneCallback(msg); doneCallback(msg);
break; break;
} }
} }
} }
public void doneCallback(Message msg) { public void doneCallback(Message msg) {
} }
public void passPhraseCallback(long keyId, String passPhrase) { public void passPhraseCallback(long keyId, String passPhrase) {
Apg.setCachedPassPhrase(keyId, passPhrase); Apg.setCachedPassPhrase(keyId, passPhrase);
} }
public void sendMessage(Message msg) { public void sendMessage(Message msg) {
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
} }
public void startThread() { public void startThread() {
mRunningThread = new Thread(this); mRunningThread = new Thread(this);
mRunningThread.start(); mRunningThread.start();
} }
public void run() { public void run() {
} }
public void setSecretKeyId(long id) { public void setSecretKeyId(long id) {
mSecretKeyId = id; mSecretKeyId = id;
} }
public long getSecretKeyId() { public long getSecretKeyId() {
return mSecretKeyId; return mSecretKeyId;
} }
protected void setDeleteFile(String deleteFile) { protected void setDeleteFile(String deleteFile) {
mDeleteFile = deleteFile; mDeleteFile = deleteFile;
} }
protected String getDeleteFile() { protected String getDeleteFile() {
return mDeleteFile; return mDeleteFile;
} }
} }

View File

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

View File

@@ -1,35 +1,35 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import android.os.Environment; import android.os.Environment;
public final class Constants { public final class Constants {
public static final class path { public static final class path {
public static final String app_dir = Environment.getExternalStorageDirectory() + "/APG"; public static final String app_dir = Environment.getExternalStorageDirectory() + "/APG";
} }
public static final class pref { public static final class pref {
public static final String has_seen_change_log = "seenChangeLogDialog"; public static final String has_seen_change_log = "seenChangeLogDialog";
public static final String default_encryption_algorithm = "defaultEncryptionAlgorithm"; public static final String default_encryption_algorithm = "defaultEncryptionAlgorithm";
public static final String default_hash_algorithm = "defaultHashAlgorithm"; public static final String default_hash_algorithm = "defaultHashAlgorithm";
public static final String default_ascii_armour = "defaultAsciiArmour"; public static final String default_ascii_armour = "defaultAsciiArmour";
public static final String default_message_compression = "defaultMessageCompression"; public static final String default_message_compression = "defaultMessageCompression";
public static final String default_file_compression = "defaultFileCompression"; public static final String default_file_compression = "defaultFileCompression";
public static final String pass_phrase_cache_ttl = "passPhraseCacheTtl"; public static final String pass_phrase_cache_ttl = "passPhraseCacheTtl";
} }
} }

View File

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

View File

@@ -1,88 +1,88 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; 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.thialfihar.android.apg.Apg.GeneralException;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
public class DataSource { public class DataSource {
private Uri mContentUri = null; private Uri mContentUri = null;
private String mText = null; private String mText = null;
private byte[] mData = null; private byte[] mData = null;
public DataSource() { public DataSource() {
} }
public void setUri(Uri uri) { public void setUri(Uri uri) {
mContentUri = uri; mContentUri = uri;
} }
public void setUri(String uri) { public void setUri(String uri) {
if (uri.startsWith("/")) { if (uri.startsWith("/")) {
setUri(Uri.parse("file://" + uri)); setUri(Uri.parse("file://" + uri));
} else { } else {
setUri(Uri.parse(uri)); setUri(Uri.parse(uri));
} }
} }
public void setText(String text) { public void setText(String text) {
mText = text; mText = text;
} }
public void setData(byte[] data) { public void setData(byte[] data) {
mData = data; mData = data;
} }
public InputData getInputData(Context context, boolean withSize) public InputData getInputData(Context context, boolean withSize)
throws GeneralException, FileNotFoundException, IOException { throws GeneralException, FileNotFoundException, IOException {
InputStream in = null; InputStream in = null;
long size = 0; long size = 0;
if (mContentUri != null) { if (mContentUri != null) {
if (mContentUri.getScheme().equals("file")) { if (mContentUri.getScheme().equals("file")) {
// get the rest after "file://" // get the rest after "file://"
String path = mContentUri.toString().substring(6); String path = mContentUri.toString().substring(6);
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);
File file = new File(path); File file = new File(path);
if (withSize) { if (withSize) {
size = file.length(); size = file.length();
} }
} else { } else {
in = context.getContentResolver().openInputStream(mContentUri); in = context.getContentResolver().openInputStream(mContentUri);
if (withSize) { if (withSize) {
InputStream tmp = context.getContentResolver().openInputStream(mContentUri); InputStream tmp = context.getContentResolver().openInputStream(mContentUri);
size = Apg.getLengthOfStream(tmp); size = Apg.getLengthOfStream(tmp);
tmp.close(); tmp.close();
} }
} }
} else if (mText != null || mData != null) { } else if (mText != null || mData != null) {
byte[] bytes = null; byte[] bytes = null;
if (mData != null) { if (mData != null) {
bytes = mData; bytes = mData;
} else { } else {
bytes = mText.getBytes(); bytes = mText.getBytes();
} }
in = new ByteArrayInputStream(bytes); in = new ByteArrayInputStream(bytes);
if (withSize) { if (withSize) {
size = bytes.length; size = bytes.length;
} }
} }
return new InputData(in, size); return new InputData(in, size);
} }
} }

View File

@@ -1,118 +1,118 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.Toast; import android.widget.Toast;
public class FileDialog { public class FileDialog {
private static EditText mFilename; private static EditText mFilename;
private static ImageButton mBrowse; private static ImageButton mBrowse;
private static Activity mActivity; private static Activity mActivity;
private static String mFileManagerTitle; private static String mFileManagerTitle;
private static String mFileManagerButton; private static String mFileManagerButton;
private static int mRequestCode; private static int mRequestCode;
public static interface OnClickListener { public static interface OnClickListener {
public void onCancelClick(); public void onCancelClick();
public void onOkClick(String filename); public void onOkClick(String filename);
} }
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 fileManagerButton, String fileManagerTitle, String fileManagerButton,
int requestCode) { 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.getSystemService(Context.LAYOUT_INFLATER_SERVICE); (LayoutInflater) activity.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);
alert.setMessage(message); alert.setMessage(message);
View view = (View) inflater.inflate(R.layout.file_dialog, null); View view = (View) inflater.inflate(R.layout.file_dialog, null);
mActivity = activity; mActivity = activity;
mFilename = (EditText) view.findViewById(R.id.input); mFilename = (EditText) view.findViewById(R.id.input);
mFilename.setText(defaultFile); mFilename.setText(defaultFile);
mBrowse = (ImageButton) view.findViewById(R.id.btn_browse); mBrowse = (ImageButton) view.findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() { mBrowse.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
openFile(); openFile();
} }
}); });
mFileManagerTitle = fileManagerTitle; mFileManagerTitle = fileManagerTitle;
mFileManagerButton = fileManagerButton; mFileManagerButton = fileManagerButton;
mRequestCode = requestCode; mRequestCode = requestCode;
alert.setView(view); alert.setView(view);
final OnClickListener clickListener = onClickListener; final OnClickListener clickListener = onClickListener;
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
clickListener.onOkClick(mFilename.getText().toString()); clickListener.onOkClick(mFilename.getText().toString());
} }
}); });
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();
} }
}); });
return alert.create(); return alert.create();
} }
public static void setFilename(String filename) { public static void setFilename(String filename) {
if (mFilename != null) { if (mFilename != null) {
mFilename.setText(filename); mFilename.setText(filename);
} }
} }
/** /**
* Opens the file manager to select a file to open. * Opens the file manager to select a file to open.
*/ */
private static void openFile() { private static void openFile() {
String filename = mFilename.getText().toString(); String filename = mFilename.getText().toString();
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setData(Uri.parse("file://" + filename)); intent.setData(Uri.parse("file://" + filename));
intent.setType("*/*"); intent.setType("*/*");
try { try {
mActivity.startActivityForResult(intent, mRequestCode); mActivity.startActivityForResult(intent, mRequestCode);
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
// No compatible file manager was found. // No compatible file manager was found.
Toast.makeText(mActivity, R.string.noFilemanagerInstalled, Toast.LENGTH_SHORT).show(); Toast.makeText(mActivity, R.string.noFilemanagerInstalled, Toast.LENGTH_SHORT).show();
} }
} }
} }

View File

@@ -1,177 +1,177 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; 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.thialfihar.android.apg.utils.Choice;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.ListView; import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
public class GeneralActivity extends BaseActivity { public class GeneralActivity extends BaseActivity {
private Intent mIntent; private Intent mIntent;
private ArrayAdapter<Choice> mAdapter; private ArrayAdapter<Choice> mAdapter;
private ListView mList; private ListView mList;
private Button mCancelButton; private Button mCancelButton;
private String mDataString; private String mDataString;
private Uri mDataUri; private Uri mDataUri;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.general); setContentView(R.layout.general);
mIntent = getIntent(); mIntent = getIntent();
InputStream inStream = null; InputStream inStream = null;
{ {
String data = mIntent.getStringExtra(Intent.EXTRA_TEXT); String data = mIntent.getStringExtra(Intent.EXTRA_TEXT);
if (data != null) { if (data != null) {
mDataString = data; mDataString = data;
inStream = new ByteArrayInputStream(data.getBytes()); inStream = new ByteArrayInputStream(data.getBytes());
} }
} }
if (inStream == null) { if (inStream == null) {
Uri data = mIntent.getData(); Uri data = mIntent.getData();
if (data != null) { if (data != null) {
mDataUri = data; mDataUri = data;
try { try {
inStream = getContentResolver().openInputStream(data); inStream = getContentResolver().openInputStream(data);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
// didn't work // didn't work
Toast.makeText(this, "failed to open stream", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "failed to open stream", Toast.LENGTH_SHORT).show();
} }
} }
} }
if (inStream == null) { if (inStream == null) {
Toast.makeText(this, "no data found", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "no data found", Toast.LENGTH_SHORT).show();
finish(); finish();
return; return;
} }
int contentType = Id.content.unknown; int contentType = Id.content.unknown;
try { try {
contentType = Apg.getStreamContent(this, inStream); contentType = Apg.getStreamContent(this, inStream);
inStream.close(); inStream.close();
} catch (IOException e) { } catch (IOException e) {
// just means that there's no PGP data in there // just means that there's no PGP data in there
} }
mList = (ListView) findViewById(R.id.options); mList = (ListView) findViewById(R.id.options);
Vector<Choice> choices = new Vector<Choice>(); Vector<Choice> choices = new Vector<Choice>();
if (contentType == Id.content.keys) { if (contentType == Id.content.keys) {
choices.add(new Choice(Id.choice.action.import_public, choices.add(new Choice(Id.choice.action.import_public,
getString(R.string.action_importPublic))); getString(R.string.action_importPublic)));
choices.add(new Choice(Id.choice.action.import_secret, choices.add(new Choice(Id.choice.action.import_secret,
getString(R.string.action_importSecret))); getString(R.string.action_importSecret)));
} }
if (contentType == Id.content.encrypted_data) { if (contentType == Id.content.encrypted_data) {
choices.add(new Choice(Id.choice.action.decrypt, getString(R.string.action_decrypt))); choices.add(new Choice(Id.choice.action.decrypt, getString(R.string.action_decrypt)));
} }
if (contentType == Id.content.unknown) { if (contentType == Id.content.unknown) {
choices.add(new Choice(Id.choice.action.encrypt, getString(R.string.action_encrypt))); choices.add(new Choice(Id.choice.action.encrypt, getString(R.string.action_encrypt)));
} }
mAdapter = new ArrayAdapter<Choice>(this, android.R.layout.simple_list_item_1, choices); mAdapter = new ArrayAdapter<Choice>(this, android.R.layout.simple_list_item_1, choices);
mList.setAdapter(mAdapter); mList.setAdapter(mAdapter);
mList.setOnItemClickListener(new OnItemClickListener() { mList.setOnItemClickListener(new OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
clicked(mAdapter.getItem(arg2).getId()); clicked(mAdapter.getItem(arg2).getId());
} }
}); });
mCancelButton = (Button) findViewById(R.id.btn_cancel); mCancelButton = (Button) findViewById(R.id.btn_cancel);
mCancelButton.setOnClickListener(new OnClickListener() { mCancelButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
GeneralActivity.this.finish(); GeneralActivity.this.finish();
} }
}); });
if (choices.size() == 1) { if (choices.size() == 1) {
clicked(choices.get(0).getId()); clicked(choices.get(0).getId());
} }
} }
private void clicked(int id) { private void clicked(int id) {
Intent intent = new Intent(); Intent intent = new Intent();
switch (id) { switch (id) {
case Id.choice.action.encrypt: { case Id.choice.action.encrypt: {
intent.setClass(this, EncryptActivity.class); intent.setClass(this, EncryptActivity.class);
if (mDataString != null) { if (mDataString != null) {
intent.setAction(Apg.Intent.ENCRYPT); intent.setAction(Apg.Intent.ENCRYPT);
intent.putExtra(Apg.EXTRA_TEXT, mDataString); intent.putExtra(Apg.EXTRA_TEXT, mDataString);
} else if (mDataUri != null) { } else if (mDataUri != null) {
intent.setAction(Apg.Intent.ENCRYPT_FILE); intent.setAction(Apg.Intent.ENCRYPT_FILE);
intent.setDataAndType(mDataUri, mIntent.getType()); intent.setDataAndType(mDataUri, mIntent.getType());
} }
break; break;
} }
case Id.choice.action.decrypt: { case Id.choice.action.decrypt: {
intent.setClass(this, DecryptActivity.class); intent.setClass(this, DecryptActivity.class);
if (mDataString != null) { if (mDataString != null) {
intent.setAction(Apg.Intent.DECRYPT); intent.setAction(Apg.Intent.DECRYPT);
intent.putExtra(Apg.EXTRA_TEXT, mDataString); intent.putExtra(Apg.EXTRA_TEXT, mDataString);
} else if (mDataUri != null) { } else if (mDataUri != null) {
intent.setAction(Apg.Intent.DECRYPT_FILE); intent.setAction(Apg.Intent.DECRYPT_FILE);
intent.setDataAndType(mDataUri, mIntent.getType()); intent.setDataAndType(mDataUri, mIntent.getType());
} }
break; break;
} }
case Id.choice.action.import_public: { case Id.choice.action.import_public: {
intent.setClass(this, PublicKeyListActivity.class); intent.setClass(this, PublicKeyListActivity.class);
intent.setAction(Apg.Intent.IMPORT); intent.setAction(Apg.Intent.IMPORT);
if (mDataString != null) { if (mDataString != null) {
intent.putExtra(Apg.EXTRA_TEXT, mDataString); intent.putExtra(Apg.EXTRA_TEXT, mDataString);
} else if (mDataUri != null) { } else if (mDataUri != null) {
intent.setDataAndType(mDataUri, mIntent.getType()); intent.setDataAndType(mDataUri, mIntent.getType());
} }
break; break;
} }
case Id.choice.action.import_secret: { case Id.choice.action.import_secret: {
intent.setClass(this, SecretKeyListActivity.class); intent.setClass(this, SecretKeyListActivity.class);
intent.setAction(Apg.Intent.IMPORT); intent.setAction(Apg.Intent.IMPORT);
if (mDataString != null) { if (mDataString != null) {
intent.putExtra(Apg.EXTRA_TEXT, mDataString); intent.putExtra(Apg.EXTRA_TEXT, mDataString);
} else if (mDataUri != null) { } else if (mDataUri != null) {
intent.setDataAndType(mDataUri, mIntent.getType()); intent.setDataAndType(mDataUri, mIntent.getType());
} }
break; break;
} }
default: { default: {
// shouldn't happen // shouldn't happen
return; return;
} }
} }
startActivity(intent); startActivity(intent);
finish(); finish();
} }
} }

View File

@@ -1,155 +1,155 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import org.bouncycastle2.bcpg.CompressionAlgorithmTags; import org.bouncycastle2.bcpg.CompressionAlgorithmTags;
public final class Id { public final class Id {
public static final class menu { public static final class menu {
public static final int export = 0x21070001; public static final int export = 0x21070001;
public static final int delete = 0x21070002; public static final int delete = 0x21070002;
public static final int edit = 0x21070003; public static final int edit = 0x21070003;
public static final class option { public static final class option {
public static final int new_pass_phrase = 0x21070001; public static final int new_pass_phrase = 0x21070001;
public static final int create = 0x21070002; public static final int create = 0x21070002;
public static final int about = 0x21070003; public static final int about = 0x21070003;
public static final int manage_public_keys = 0x21070004; public static final int manage_public_keys = 0x21070004;
public static final int manage_secret_keys = 0x21070005; public static final int manage_secret_keys = 0x21070005;
public static final int import_keys = 0x21070006; public static final int import_keys = 0x21070006;
public static final int export_keys = 0x21070007; public static final int export_keys = 0x21070007;
public static final int preferences = 0x21070008; public static final int preferences = 0x21070008;
public static final int search = 0x21070009; public static final int search = 0x21070009;
} }
} }
public static final class message { public static final class message {
public static final int progress_update = 0x21070001; public static final int progress_update = 0x21070001;
public static final int done = 0x21070002; public static final int done = 0x21070002;
public static final int import_keys = 0x21070003; public static final int import_keys = 0x21070003;
public static final int export_keys = 0x21070004; public static final int export_keys = 0x21070004;
public static final int import_done = 0x21070005; public static final int import_done = 0x21070005;
public static final int export_done = 0x21070006; public static final int export_done = 0x21070006;
public static final int create_key = 0x21070007; public static final int create_key = 0x21070007;
public static final int edit_key = 0x21070008; public static final int edit_key = 0x21070008;
} }
public static final class request { public static final class request {
public static final int public_keys = 0x21070001; public static final int public_keys = 0x21070001;
public static final int secret_keys = 0x21070002; public static final int secret_keys = 0x21070002;
public static final int filename = 0x21070003; public static final int filename = 0x21070003;
public static final int output_filename = 0x21070004; public static final int output_filename = 0x21070004;
} }
public static final class dialog { public static final class dialog {
public static final int pass_phrase = 0x21070001; public static final int pass_phrase = 0x21070001;
public static final int encrypting = 0x21070002; public static final int encrypting = 0x21070002;
public static final int decrypting = 0x21070003; public static final int decrypting = 0x21070003;
public static final int new_pass_phrase = 0x21070004; public static final int new_pass_phrase = 0x21070004;
public static final int pass_phrases_do_not_match = 0x21070005; public static final int pass_phrases_do_not_match = 0x21070005;
public static final int no_pass_phrase = 0x21070006; public static final int no_pass_phrase = 0x21070006;
public static final int saving = 0x21070007; public static final int saving = 0x21070007;
public static final int delete_key = 0x21070008; public static final int delete_key = 0x21070008;
public static final int import_keys = 0x21070009; public static final int import_keys = 0x21070009;
public static final int importing = 0x2107000a; public static final int importing = 0x2107000a;
public static final int export_key = 0x2107000b; public static final int export_key = 0x2107000b;
public static final int export_keys = 0x2107000c; public static final int export_keys = 0x2107000c;
public static final int exporting = 0x2107000d; public static final int exporting = 0x2107000d;
public static final int new_account = 0x2107000e; public static final int new_account = 0x2107000e;
public static final int about = 0x2107000f; public static final int about = 0x2107000f;
public static final int change_log = 0x21070010; public static final int change_log = 0x21070010;
public static final int output_filename = 0x21070011; public static final int output_filename = 0x21070011;
public static final int delete_file = 0x21070012; public static final int delete_file = 0x21070012;
} }
public static final class task { public static final class task {
public static final int import_keys = 0x21070001; public static final int import_keys = 0x21070001;
public static final int export_keys = 0x21070002; public static final int export_keys = 0x21070002;
} }
public static final class database { public static final class database {
public static final int type_public = 0; public static final int type_public = 0;
public static final int type_secret = 1; public static final int type_secret = 1;
} }
public static final class type { public static final class type {
public static final int public_key = 0x21070001; public static final int public_key = 0x21070001;
public static final int secret_key = 0x21070002; public static final int secret_key = 0x21070002;
public static final int user_id = 0x21070003; public static final int user_id = 0x21070003;
public static final int key = 0x21070004; public static final int key = 0x21070004;
} }
public static final class choice { public static final class choice {
public static final class algorithm { public static final class algorithm {
public static final int dsa = 0x21070001; public static final int dsa = 0x21070001;
public static final int elgamal = 0x21070002; public static final int elgamal = 0x21070002;
public static final int rsa = 0x21070003; public static final int rsa = 0x21070003;
} }
public static final class compression { public static final class compression {
public static final int none = 0x21070001; public static final int none = 0x21070001;
public static final int zlib = CompressionAlgorithmTags.ZLIB; public static final int zlib = CompressionAlgorithmTags.ZLIB;
public static final int bzip2 = CompressionAlgorithmTags.BZIP2; public static final int bzip2 = CompressionAlgorithmTags.BZIP2;
public static final int zip = CompressionAlgorithmTags.ZIP; public static final int zip = CompressionAlgorithmTags.ZIP;
} }
public static final class usage { public static final class usage {
public static final int sign_only = 0x21070001; public static final int sign_only = 0x21070001;
public static final int encrypt_only = 0x21070002; public static final int encrypt_only = 0x21070002;
public static final int sign_and_encrypt = 0x21070003; public static final int sign_and_encrypt = 0x21070003;
} }
public static final class action { public static final class action {
public static final int encrypt = 0x21070001; public static final int encrypt = 0x21070001;
public static final int decrypt = 0x21070002; public static final int decrypt = 0x21070002;
public static final int import_public = 0x21070003; public static final int import_public = 0x21070003;
public static final int import_secret = 0x21070004; public static final int import_secret = 0x21070004;
} }
} }
public static final class return_value { public static final class return_value {
public static final int ok = 0; public static final int ok = 0;
public static final int error = -1; public static final int error = -1;
public static final int no_master_key = -2; public static final int no_master_key = -2;
public static final int updated = 1; public static final int updated = 1;
} }
public static final class target { public static final class target {
public static final int clipboard = 0x21070001; public static final int clipboard = 0x21070001;
public static final int email = 0x21070002; public static final int email = 0x21070002;
public static final int file = 0x21070003; public static final int file = 0x21070003;
public static final int message = 0x21070004; public static final int message = 0x21070004;
} }
public static final class mode { public static final class mode {
public static final int undefined = 0x21070001; public static final int undefined = 0x21070001;
public static final int byte_array = 0x21070002; public static final int byte_array = 0x21070002;
public static final int file = 0x21070003; public static final int file = 0x21070003;
public static final int stream = 0x21070004; public static final int stream = 0x21070004;
} }
public static final class key { public static final class key {
public static final int none = 0; public static final int none = 0;
public static final int symmetric = -1; public static final int symmetric = -1;
} }
public static final class content { public static final class content {
public static final int unknown = 0; public static final int unknown = 0;
public static final int encrypted_data = 1; public static final int encrypted_data = 1;
public static final int keys = 2; public static final int keys = 2;
} }
} }

View File

@@ -1,25 +1,25 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.InputStream; import java.io.InputStream;
public class InputData { public class InputData {
private PositionAwareInputStream mInputStream; private PositionAwareInputStream mInputStream;
private long mSize; private long mSize;
InputData(InputStream inputStream, long size) { InputData(InputStream inputStream, long size) {
mInputStream = new PositionAwareInputStream(inputStream); mInputStream = new PositionAwareInputStream(inputStream);
mSize = size; mSize = size;
} }
public InputStream getInputStream() { public InputStream getInputStream() {
return mInputStream; return mInputStream;
} }
public long getSize() { public long getSize() {
return mSize; return mSize;
} }
public long getStreamPosition() { public long getStreamPosition() {
return mInputStream.position(); return mInputStream.position();
} }
} }

View File

@@ -1,95 +1,95 @@
/* /*
* Copyright 2010 Google Inc. * Copyright 2010 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import android.content.Context; import android.content.Context;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.util.AttributeSet; import android.util.AttributeSet;
/** /**
* A list preference which persists its values as integers instead of strings. * A list preference which persists its values as integers instead of strings.
* Code reading the values should use * Code reading the values should use
* {@link android.content.SharedPreferences#getInt}. * {@link android.content.SharedPreferences#getInt}.
* When using XML-declared arrays for entry values, the arrays should be regular * When using XML-declared arrays for entry values, the arrays should be regular
* string arrays containing valid integer values. * string arrays containing valid integer values.
* *
* @author Rodrigo Damazio * @author Rodrigo Damazio
*/ */
public class IntegerListPreference extends ListPreference { public class IntegerListPreference extends ListPreference {
public IntegerListPreference(Context context) { public IntegerListPreference(Context context) {
super(context); super(context);
verifyEntryValues(null); verifyEntryValues(null);
} }
public IntegerListPreference(Context context, AttributeSet attrs) { public IntegerListPreference(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
verifyEntryValues(null); verifyEntryValues(null);
} }
@Override @Override
public void setEntryValues(CharSequence[] entryValues) { public void setEntryValues(CharSequence[] entryValues) {
CharSequence[] oldValues = getEntryValues(); CharSequence[] oldValues = getEntryValues();
super.setEntryValues(entryValues); super.setEntryValues(entryValues);
verifyEntryValues(oldValues); verifyEntryValues(oldValues);
} }
@Override @Override
public void setEntryValues(int entryValuesResId) { public void setEntryValues(int entryValuesResId) {
CharSequence[] oldValues = getEntryValues(); CharSequence[] oldValues = getEntryValues();
super.setEntryValues(entryValuesResId); super.setEntryValues(entryValuesResId);
verifyEntryValues(oldValues); verifyEntryValues(oldValues);
} }
@Override @Override
protected String getPersistedString(String defaultReturnValue) { protected String getPersistedString(String defaultReturnValue) {
// During initial load, there's no known default value // During initial load, there's no known default value
int defaultIntegerValue = Integer.MIN_VALUE; int defaultIntegerValue = Integer.MIN_VALUE;
if (defaultReturnValue != null) { if (defaultReturnValue != null) {
defaultIntegerValue = Integer.parseInt(defaultReturnValue); defaultIntegerValue = Integer.parseInt(defaultReturnValue);
} }
// When the list preference asks us to read a string, instead read an // When the list preference asks us to read a string, instead read an
// integer. // integer.
int value = getPersistedInt(defaultIntegerValue); int value = getPersistedInt(defaultIntegerValue);
return Integer.toString(value); return Integer.toString(value);
} }
@Override @Override
protected boolean persistString(String value) { protected boolean persistString(String value) {
// When asked to save a string, instead save an integer // When asked to save a string, instead save an integer
return persistInt(Integer.parseInt(value)); return persistInt(Integer.parseInt(value));
} }
private void verifyEntryValues(CharSequence[] oldValues) { private void verifyEntryValues(CharSequence[] oldValues) {
CharSequence[] entryValues = getEntryValues(); CharSequence[] entryValues = getEntryValues();
if (entryValues == null) { if (entryValues == null) {
return; return;
} }
for (CharSequence entryValue : entryValues) { for (CharSequence entryValue : entryValues) {
try { try {
Integer.parseInt(entryValue.toString()); Integer.parseInt(entryValue.toString());
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
super.setEntryValues(oldValues); super.setEntryValues(oldValues);
throw nfe; throw nfe;
} }
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,218 +1,218 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.util.Vector; import java.util.Vector;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import android.app.ListActivity; import android.app.ListActivity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html; import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListAdapter; import android.widget.ListAdapter;
import android.widget.TextView; import android.widget.TextView;
public class MailListActivity extends ListActivity { public class MailListActivity extends ListActivity {
LayoutInflater mInflater = null; LayoutInflater mInflater = null;
private static class Conversation { private static class Conversation {
public long id; public long id;
public String subject; public String subject;
public Vector<Message> messages; public Vector<Message> messages;
public Conversation(long id, String subject) { public Conversation(long id, String subject) {
this.id = id; this.id = id;
this.subject = subject; this.subject = subject;
} }
} }
private static class Message { private static class Message {
public Conversation parent; public Conversation parent;
public long id; public long id;
public String subject; public String subject;
public String fromAddress; public String fromAddress;
public String data; public String data;
public String replyTo; public String replyTo;
public boolean signedOnly; public boolean signedOnly;
public Message(Conversation parent, long id, String subject, public Message(Conversation parent, long id, String subject,
String fromAddress, String replyTo, String fromAddress, String replyTo,
String data, boolean signedOnly) { String data, boolean signedOnly) {
this.parent = parent; this.parent = parent;
this.id = id; this.id = id;
this.subject = subject; this.subject = subject;
this.fromAddress = fromAddress; this.fromAddress = fromAddress;
this.replyTo = replyTo; this.replyTo = replyTo;
this.data = data; this.data = data;
if (this.replyTo == null || this.replyTo.equals("")) { if (this.replyTo == null || this.replyTo.equals("")) {
this.replyTo = this.fromAddress; this.replyTo = this.fromAddress;
} }
this.signedOnly = signedOnly; this.signedOnly = signedOnly;
} }
} }
private Vector<Conversation> mconversations; private Vector<Conversation> mconversations;
private Vector<Message> mmessages; private Vector<Message> mmessages;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mconversations = new Vector<Conversation>(); mconversations = new Vector<Conversation>();
mmessages = new Vector<Message>(); mmessages = new Vector<Message>();
String account = getIntent().getExtras().getString(Apg.EXTRA_ACCOUNT); String account = getIntent().getExtras().getString(Apg.EXTRA_ACCOUNT);
// TODO: what if account is null? // TODO: what if account is null?
Uri uri = Uri.parse("content://gmail-ls/conversations/" + account); Uri uri = Uri.parse("content://gmail-ls/conversations/" + account);
Cursor cursor = Cursor cursor =
managedQuery(uri, new String[] { "conversation_id", "subject" }, null, null, null); managedQuery(uri, new String[] { "conversation_id", "subject" }, null, null, null);
for (int i = 0; i < cursor.getCount(); ++i) { for (int i = 0; i < cursor.getCount(); ++i) {
cursor.moveToPosition(i); cursor.moveToPosition(i);
int idIndex = cursor.getColumnIndex("conversation_id"); int idIndex = cursor.getColumnIndex("conversation_id");
int subjectIndex = cursor.getColumnIndex("subject"); int subjectIndex = cursor.getColumnIndex("subject");
long conversationId = cursor.getLong(idIndex); long conversationId = cursor.getLong(idIndex);
Conversation conversation = Conversation conversation =
new Conversation(conversationId, cursor.getString(subjectIndex)); new Conversation(conversationId, cursor.getString(subjectIndex));
Uri messageUri = Uri.withAppendedPath(uri, "" + conversationId + "/messages"); Uri messageUri = Uri.withAppendedPath(uri, "" + conversationId + "/messages");
Cursor messageCursor = Cursor messageCursor =
managedQuery(messageUri, new String[] { managedQuery(messageUri, new String[] {
"messageId", "messageId",
"subject", "subject",
"fromAddress", "fromAddress",
"replyToAddresses", "replyToAddresses",
"body" }, null, null, null); "body" }, null, null, null);
Vector<Message> messages = new Vector<Message>(); Vector<Message> messages = new Vector<Message>();
for (int j = 0; j < messageCursor.getCount(); ++j) { for (int j = 0; j < messageCursor.getCount(); ++j) {
messageCursor.moveToPosition(j); messageCursor.moveToPosition(j);
idIndex = messageCursor.getColumnIndex("messageId"); idIndex = messageCursor.getColumnIndex("messageId");
subjectIndex = messageCursor.getColumnIndex("subject"); subjectIndex = messageCursor.getColumnIndex("subject");
int fromAddressIndex = messageCursor.getColumnIndex("fromAddress"); int fromAddressIndex = messageCursor.getColumnIndex("fromAddress");
int replyToIndex = messageCursor.getColumnIndex("replyToAddresses"); int replyToIndex = messageCursor.getColumnIndex("replyToAddresses");
int bodyIndex = messageCursor.getColumnIndex("body"); int bodyIndex = messageCursor.getColumnIndex("body");
String data = messageCursor.getString(bodyIndex); String data = messageCursor.getString(bodyIndex);
data = Html.fromHtml(data).toString(); data = Html.fromHtml(data).toString();
boolean signedOnly = false; boolean signedOnly = false;
Matcher matcher = Apg.PGP_MESSAGE.matcher(data); Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
if (matcher.matches()) { if (matcher.matches()) {
data = matcher.group(1); data = matcher.group(1);
} else { } else {
matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data); matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data);
if (matcher.matches()) { if (matcher.matches()) {
data = matcher.group(1); data = matcher.group(1);
signedOnly = true; signedOnly = true;
} else { } else {
data = null; data = null;
} }
} }
Message message = Message message =
new Message(conversation, new Message(conversation,
messageCursor.getLong(idIndex), messageCursor.getLong(idIndex),
messageCursor.getString(subjectIndex), messageCursor.getString(subjectIndex),
messageCursor.getString(fromAddressIndex), messageCursor.getString(fromAddressIndex),
messageCursor.getString(replyToIndex), messageCursor.getString(replyToIndex),
data, signedOnly); data, signedOnly);
messages.add(message); messages.add(message);
mmessages.add(message); mmessages.add(message);
} }
conversation.messages = messages; conversation.messages = messages;
mconversations.add(conversation); mconversations.add(conversation);
} }
setListAdapter(new MailboxAdapter()); setListAdapter(new MailboxAdapter());
getListView().setOnItemClickListener(new OnItemClickListener() { getListView().setOnItemClickListener(new OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long id) { public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
Intent intent = new Intent(MailListActivity.this, DecryptActivity.class); Intent intent = new Intent(MailListActivity.this, DecryptActivity.class);
intent.setAction(Apg.Intent.DECRYPT); intent.setAction(Apg.Intent.DECRYPT);
Message message = (Message) ((MailboxAdapter) getListAdapter()).getItem(position); Message message = (Message) ((MailboxAdapter) getListAdapter()).getItem(position);
intent.putExtra(Apg.EXTRA_TEXT, message.data); intent.putExtra(Apg.EXTRA_TEXT, message.data);
intent.putExtra(Apg.EXTRA_SUBJECT, message.subject); intent.putExtra(Apg.EXTRA_SUBJECT, message.subject);
intent.putExtra(Apg.EXTRA_REPLY_TO, message.replyTo); intent.putExtra(Apg.EXTRA_REPLY_TO, message.replyTo);
startActivity(intent); startActivity(intent);
} }
}); });
} }
private class MailboxAdapter extends BaseAdapter implements ListAdapter { private class MailboxAdapter extends BaseAdapter implements ListAdapter {
@Override @Override
public boolean isEnabled(int position) { public boolean isEnabled(int position) {
Message message = (Message) getItem(position); Message message = (Message) getItem(position);
return message.data != null; return message.data != null;
} }
@Override @Override
public boolean hasStableIds() { public boolean hasStableIds() {
return true; return true;
} }
@Override @Override
public int getCount() { public int getCount() {
return mmessages.size(); return mmessages.size();
} }
@Override @Override
public Object getItem(int position) { public Object getItem(int position) {
return mmessages.get(position); return mmessages.get(position);
} }
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
return mmessages.get(position).id; return mmessages.get(position).id;
} }
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
View view = mInflater.inflate(R.layout.mailbox_message_item, null); View view = mInflater.inflate(R.layout.mailbox_message_item, null);
Message message = (Message) getItem(position); Message message = (Message) getItem(position);
TextView subject = (TextView) view.findViewById(R.id.subject); TextView subject = (TextView) view.findViewById(R.id.subject);
TextView email = (TextView) view.findViewById(R.id.emailAddress); TextView email = (TextView) view.findViewById(R.id.emailAddress);
ImageView status = (ImageView) view.findViewById(R.id.ic_status); ImageView status = (ImageView) view.findViewById(R.id.ic_status);
subject.setText(message.subject); subject.setText(message.subject);
email.setText(message.fromAddress); email.setText(message.fromAddress);
if (message.data != null) { if (message.data != null) {
if (message.signedOnly) { if (message.signedOnly) {
status.setImageResource(R.drawable.signed); status.setImageResource(R.drawable.signed);
} else { } else {
status.setImageResource(R.drawable.encrypted); status.setImageResource(R.drawable.encrypted);
} }
status.setVisibility(View.VISIBLE); status.setVisibility(View.VISIBLE);
} else { } else {
status.setVisibility(View.INVISIBLE); status.setVisibility(View.INVISIBLE);
} }
return view; return view;
} }
} }
} }

View File

@@ -1,67 +1,67 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
public class PositionAwareInputStream extends InputStream { public class PositionAwareInputStream extends InputStream {
private InputStream mStream; private InputStream mStream;
private long mPosition; private long mPosition;
public PositionAwareInputStream(InputStream in) { public PositionAwareInputStream(InputStream in) {
mStream = in; mStream = in;
mPosition = 0; mPosition = 0;
} }
@Override @Override
public int read() throws IOException { public int read() throws IOException {
int ch = mStream.read(); int ch = mStream.read();
++mPosition; ++mPosition;
return ch; return ch;
} }
@Override @Override
public int available() throws IOException { public int available() throws IOException {
return mStream.available(); return mStream.available();
} }
@Override @Override
public void close() throws IOException { public void close() throws IOException {
mStream.close(); mStream.close();
} }
@Override @Override
public boolean markSupported() { public boolean markSupported() {
return false; return false;
} }
@Override @Override
public int read(byte[] b) throws IOException { public int read(byte[] b) throws IOException {
int result = mStream.read(b); int result = mStream.read(b);
mPosition += result; mPosition += result;
return result; return result;
} }
@Override @Override
public int read(byte[] b, int offset, int length) throws IOException { public int read(byte[] b, int offset, int length) throws IOException {
int result = mStream.read(b, offset, length); int result = mStream.read(b, offset, length);
mPosition += result; mPosition += result;
return result; return result;
} }
@Override @Override
public synchronized void reset() throws IOException { public synchronized void reset() throws IOException {
mStream.reset(); mStream.reset();
mPosition = 0; mPosition = 0;
} }
@Override @Override
public long skip(long n) throws IOException { public long skip(long n) throws IOException {
long result = mStream.skip(n); long result = mStream.skip(n);
mPosition += result; mPosition += result;
return result; return result;
} }
public long position() { public long position() {
return mPosition; return mPosition;
} }
} }

View File

@@ -1,180 +1,180 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import org.bouncycastle2.bcpg.HashAlgorithmTags; import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPEncryptedData; import org.bouncycastle2.openpgp.PGPEncryptedData;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
public class PreferencesActivity extends PreferenceActivity { public class PreferencesActivity extends PreferenceActivity {
private IntegerListPreference mPassPhraseCacheTtl = null; private IntegerListPreference mPassPhraseCacheTtl = null;
private IntegerListPreference mEncryptionAlgorithm = null; private IntegerListPreference mEncryptionAlgorithm = null;
private IntegerListPreference mHashAlgorithm = null; private IntegerListPreference mHashAlgorithm = null;
private IntegerListPreference mMessageCompression = null; private IntegerListPreference mMessageCompression = null;
private IntegerListPreference mFileCompression = null; private IntegerListPreference mFileCompression = null;
private CheckBoxPreference mAsciiArmour = null; private CheckBoxPreference mAsciiArmour = null;
private Preferences mPreferences; private Preferences mPreferences;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mPreferences = Preferences.getPreferences(this); mPreferences = Preferences.getPreferences(this);
addPreferencesFromResource(R.xml.apg_preferences); addPreferencesFromResource(R.xml.apg_preferences);
mPassPhraseCacheTtl = (IntegerListPreference) findPreference(Constants.pref.pass_phrase_cache_ttl); mPassPhraseCacheTtl = (IntegerListPreference) findPreference(Constants.pref.pass_phrase_cache_ttl);
mPassPhraseCacheTtl.setValue("" + mPreferences.getPassPhraseCacheTtl()); mPassPhraseCacheTtl.setValue("" + mPreferences.getPassPhraseCacheTtl());
mPassPhraseCacheTtl.setSummary(mPassPhraseCacheTtl.getEntry()); mPassPhraseCacheTtl.setSummary(mPassPhraseCacheTtl.getEntry());
mPassPhraseCacheTtl.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() mPassPhraseCacheTtl.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{ {
public boolean onPreferenceChange(Preference preference, Object newValue) public boolean onPreferenceChange(Preference preference, Object newValue)
{ {
mPassPhraseCacheTtl.setValue(newValue.toString()); mPassPhraseCacheTtl.setValue(newValue.toString());
mPassPhraseCacheTtl.setSummary(mPassPhraseCacheTtl.getEntry()); mPassPhraseCacheTtl.setSummary(mPassPhraseCacheTtl.getEntry());
mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString())); mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString()));
BaseActivity.startCacheService(PreferencesActivity.this, mPreferences); BaseActivity.startCacheService(PreferencesActivity.this, mPreferences);
return false; return false;
} }
}); });
mEncryptionAlgorithm = (IntegerListPreference) findPreference(Constants.pref.default_encryption_algorithm); mEncryptionAlgorithm = (IntegerListPreference) findPreference(Constants.pref.default_encryption_algorithm);
int valueIds[] = { int valueIds[] = {
PGPEncryptedData.AES_128, PGPEncryptedData.AES_192, PGPEncryptedData.AES_256, PGPEncryptedData.AES_128, PGPEncryptedData.AES_192, PGPEncryptedData.AES_256,
PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH, PGPEncryptedData.CAST5, PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH, PGPEncryptedData.CAST5,
PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES, PGPEncryptedData.IDEA, PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES, PGPEncryptedData.IDEA,
}; };
String entries[] = { String entries[] = {
"AES-128", "AES-192", "AES-256", "AES-128", "AES-192", "AES-256",
"Blowfish", "Twofish", "CAST5", "Blowfish", "Twofish", "CAST5",
"DES", "Triple DES", "IDEA", "DES", "Triple DES", "IDEA",
}; };
String values[] = new String[valueIds.length]; String values[] = new String[valueIds.length];
for (int i = 0; i < values.length; ++i) { for (int i = 0; i < values.length; ++i) {
values[i] = "" + valueIds[i]; values[i] = "" + valueIds[i];
} }
mEncryptionAlgorithm.setEntries(entries); mEncryptionAlgorithm.setEntries(entries);
mEncryptionAlgorithm.setEntryValues(values); mEncryptionAlgorithm.setEntryValues(values);
mEncryptionAlgorithm.setValue("" + mPreferences.getDefaultEncryptionAlgorithm()); mEncryptionAlgorithm.setValue("" + mPreferences.getDefaultEncryptionAlgorithm());
mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry()); mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry());
mEncryptionAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() mEncryptionAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{ {
public boolean onPreferenceChange(Preference preference, Object newValue) public boolean onPreferenceChange(Preference preference, Object newValue)
{ {
mEncryptionAlgorithm.setValue(newValue.toString()); mEncryptionAlgorithm.setValue(newValue.toString());
mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry()); mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry());
mPreferences.setDefaultEncryptionAlgorithm(Integer.parseInt(newValue.toString())); mPreferences.setDefaultEncryptionAlgorithm(Integer.parseInt(newValue.toString()));
return false; return false;
} }
}); });
mHashAlgorithm = (IntegerListPreference) findPreference(Constants.pref.default_hash_algorithm); mHashAlgorithm = (IntegerListPreference) findPreference(Constants.pref.default_hash_algorithm);
valueIds = new int[] { valueIds = new int[] {
HashAlgorithmTags.MD5, HashAlgorithmTags.RIPEMD160, HashAlgorithmTags.SHA1, HashAlgorithmTags.MD5, HashAlgorithmTags.RIPEMD160, HashAlgorithmTags.SHA1,
HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256, HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256, HashAlgorithmTags.SHA384,
HashAlgorithmTags.SHA512, HashAlgorithmTags.SHA512,
}; };
entries = new String[] { entries = new String[] {
"MD5", "RIPEMD-160", "SHA-1", "MD5", "RIPEMD-160", "SHA-1",
"SHA-224", "SHA-256", "SHA-384", "SHA-224", "SHA-256", "SHA-384",
"SHA-512", "SHA-512",
}; };
values = new String[valueIds.length]; values = new String[valueIds.length];
for (int i = 0; i < values.length; ++i) { for (int i = 0; i < values.length; ++i) {
values[i] = "" + valueIds[i]; values[i] = "" + valueIds[i];
} }
mHashAlgorithm.setEntries(entries); mHashAlgorithm.setEntries(entries);
mHashAlgorithm.setEntryValues(values); mHashAlgorithm.setEntryValues(values);
mHashAlgorithm.setValue("" + mPreferences.getDefaultHashAlgorithm()); mHashAlgorithm.setValue("" + mPreferences.getDefaultHashAlgorithm());
mHashAlgorithm.setSummary(mHashAlgorithm.getEntry()); mHashAlgorithm.setSummary(mHashAlgorithm.getEntry());
mHashAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() mHashAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{ {
public boolean onPreferenceChange(Preference preference, Object newValue) public boolean onPreferenceChange(Preference preference, Object newValue)
{ {
mHashAlgorithm.setValue(newValue.toString()); mHashAlgorithm.setValue(newValue.toString());
mHashAlgorithm.setSummary(mHashAlgorithm.getEntry()); mHashAlgorithm.setSummary(mHashAlgorithm.getEntry());
mPreferences.setDefaultHashAlgorithm(Integer.parseInt(newValue.toString())); mPreferences.setDefaultHashAlgorithm(Integer.parseInt(newValue.toString()));
return false; return false;
} }
}); });
mMessageCompression = (IntegerListPreference) findPreference(Constants.pref.default_message_compression); mMessageCompression = (IntegerListPreference) findPreference(Constants.pref.default_message_compression);
valueIds = new int[] { valueIds = new int[] {
Id.choice.compression.none, Id.choice.compression.none,
Id.choice.compression.zip, Id.choice.compression.zip,
Id.choice.compression.zlib, Id.choice.compression.zlib,
Id.choice.compression.bzip2, Id.choice.compression.bzip2,
}; };
entries = new String[] { entries = new String[] {
getString(R.string.choice_none) + " (" + getString(R.string.fast) + ")", getString(R.string.choice_none) + " (" + getString(R.string.fast) + ")",
"ZIP (" + getString(R.string.fast) + ")", "ZIP (" + getString(R.string.fast) + ")",
"ZLIB (" + getString(R.string.fast) + ")", "ZLIB (" + getString(R.string.fast) + ")",
"BZIP2 (" + getString(R.string.very_slow) + ")", "BZIP2 (" + getString(R.string.very_slow) + ")",
}; };
values = new String[valueIds.length]; values = new String[valueIds.length];
for (int i = 0; i < values.length; ++i) { for (int i = 0; i < values.length; ++i) {
values[i] = "" + valueIds[i]; values[i] = "" + valueIds[i];
} }
mMessageCompression.setEntries(entries); mMessageCompression.setEntries(entries);
mMessageCompression.setEntryValues(values); mMessageCompression.setEntryValues(values);
mMessageCompression.setValue("" + mPreferences.getDefaultMessageCompression()); mMessageCompression.setValue("" + mPreferences.getDefaultMessageCompression());
mMessageCompression.setSummary(mMessageCompression.getEntry()); mMessageCompression.setSummary(mMessageCompression.getEntry());
mMessageCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() mMessageCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{ {
public boolean onPreferenceChange(Preference preference, Object newValue) public boolean onPreferenceChange(Preference preference, Object newValue)
{ {
mMessageCompression.setValue(newValue.toString()); mMessageCompression.setValue(newValue.toString());
mMessageCompression.setSummary(mMessageCompression.getEntry()); mMessageCompression.setSummary(mMessageCompression.getEntry());
mPreferences.setDefaultMessageCompression(Integer.parseInt(newValue.toString())); mPreferences.setDefaultMessageCompression(Integer.parseInt(newValue.toString()));
return false; return false;
} }
}); });
mFileCompression = (IntegerListPreference) findPreference(Constants.pref.default_file_compression); mFileCompression = (IntegerListPreference) findPreference(Constants.pref.default_file_compression);
mFileCompression.setEntries(entries); mFileCompression.setEntries(entries);
mFileCompression.setEntryValues(values); mFileCompression.setEntryValues(values);
mFileCompression.setValue("" + mPreferences.getDefaultFileCompression()); mFileCompression.setValue("" + mPreferences.getDefaultFileCompression());
mFileCompression.setSummary(mFileCompression.getEntry()); mFileCompression.setSummary(mFileCompression.getEntry());
mFileCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() mFileCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{ {
public boolean onPreferenceChange(Preference preference, Object newValue) public boolean onPreferenceChange(Preference preference, Object newValue)
{ {
mFileCompression.setValue(newValue.toString()); mFileCompression.setValue(newValue.toString());
mFileCompression.setSummary(mFileCompression.getEntry()); mFileCompression.setSummary(mFileCompression.getEntry());
mPreferences.setDefaultFileCompression(Integer.parseInt(newValue.toString())); mPreferences.setDefaultFileCompression(Integer.parseInt(newValue.toString()));
return false; return false;
} }
}); });
mAsciiArmour = (CheckBoxPreference) findPreference(Constants.pref.default_ascii_armour); mAsciiArmour = (CheckBoxPreference) findPreference(Constants.pref.default_ascii_armour);
mAsciiArmour.setChecked(mPreferences.getDefaultAsciiArmour()); mAsciiArmour.setChecked(mPreferences.getDefaultAsciiArmour());
mAsciiArmour.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() mAsciiArmour.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{ {
public boolean onPreferenceChange(Preference preference, Object newValue) public boolean onPreferenceChange(Preference preference, Object newValue)
{ {
mAsciiArmour.setChecked((Boolean)newValue); mAsciiArmour.setChecked((Boolean)newValue);
mPreferences.setDefaultAsciiArmour((Boolean)newValue); mPreferences.setDefaultAsciiArmour((Boolean)newValue);
return false; return false;
} }
}); });
} }
} }

View File

@@ -1,185 +1,185 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.math.BigInteger; import java.math.BigInteger;
public final class Primes { public final class Primes {
// taken from http://www.ietf.org/rfc/rfc3526.txt // taken from http://www.ietf.org/rfc/rfc3526.txt
public static final String P1536 = public static final String P1536 =
"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" +
"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" +
"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" +
"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" +
"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" +
"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" +
"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" +
"670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF"; "670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF";
public static final String P2048 = public static final String P2048 =
"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" +
"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" +
"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" +
"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" +
"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" +
"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" +
"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" +
"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" +
"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" +
"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" +
"15728E5A 8AACAA68 FFFFFFFF FFFFFFFF"; "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF";
public static final String P3072 = public static final String P3072 =
"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" +
"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" +
"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" +
"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" +
"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" +
"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" +
"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" +
"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" +
"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" +
"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" +
"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" +
"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" +
"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" +
"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" +
"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" +
"43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF"; "43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF";
public static final String P4096 = public static final String P4096 =
"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" +
"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" +
"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" +
"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" +
"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" +
"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" +
"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" +
"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" +
"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" +
"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" +
"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" +
"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" +
"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" +
"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" +
"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" +
"43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" + "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" +
"88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" + "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" +
"2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" + "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" +
"287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" + "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" +
"1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" + "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" +
"93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" + "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" +
"FFFFFFFF FFFFFFFF"; "FFFFFFFF FFFFFFFF";
public static final String P6144 = public static final String P6144 =
"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" +
"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" +
"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" +
"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" +
"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" +
"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" +
"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" +
"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" +
"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" +
"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" +
"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" +
"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" +
"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" +
"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" +
"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" +
"43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" + "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" +
"88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" + "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" +
"2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" + "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" +
"287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" + "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" +
"1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" + "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" +
"93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" + "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" +
"36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" + "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" +
"F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" + "F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" +
"179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" + "179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" +
"DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" + "DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" +
"5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" + "5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" +
"D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" + "D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" +
"23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" + "23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" +
"CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" + "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" +
"06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" + "06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" +
"DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" + "DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" +
"12BF2D5B 0B7474D6 E694F91E 6DCC4024 FFFFFFFF FFFFFFFF"; "12BF2D5B 0B7474D6 E694F91E 6DCC4024 FFFFFFFF FFFFFFFF";
public static final String P8192 = public static final String P8192 =
"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" +
"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" +
"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" +
"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" +
"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" +
"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" +
"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" +
"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" +
"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" +
"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" +
"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" +
"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" +
"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" +
"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" +
"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" +
"43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" + "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" +
"88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" + "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" +
"2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" + "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" +
"287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" + "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" +
"1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" + "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" +
"93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" + "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" +
"36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" + "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" +
"F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" + "F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" +
"179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" + "179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" +
"DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" + "DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" +
"5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" + "5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" +
"D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" + "D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" +
"23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" + "23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" +
"CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" + "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" +
"06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" + "06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" +
"DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" + "DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" +
"12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" + "12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" +
"38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" + "38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" +
"741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" + "741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" +
"3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" + "3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" +
"22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" + "22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" +
"4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" + "4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" +
"062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" + "062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" +
"4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" + "4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" +
"B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" + "B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" +
"4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" + "4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" +
"9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" + "9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" +
"60C980DD 98EDD3DF FFFFFFFF FFFFFFFF"; "60C980DD 98EDD3DF FFFFFFFF FFFFFFFF";
public static BigInteger getBestPrime(int keySize) { public static BigInteger getBestPrime(int keySize) {
String primeString; String primeString;
if (keySize >= (8192 + 6144) / 2) { if (keySize >= (8192 + 6144) / 2) {
primeString = P8192; primeString = P8192;
} else if (keySize >= (6144 + 4096) / 2) { } else if (keySize >= (6144 + 4096) / 2) {
primeString = P6144; primeString = P6144;
} else if (keySize >= (4096 + 3072) / 2) { } else if (keySize >= (4096 + 3072) / 2) {
primeString = P4096; primeString = P4096;
} else if (keySize >= (3072 + 2048) / 2) { } else if (keySize >= (3072 + 2048) / 2) {
primeString = P3072; primeString = P3072;
} else if (keySize >= (2048 + 1536) / 2) { } else if (keySize >= (2048 + 1536) / 2) {
primeString = P2048; primeString = P2048;
} else { } else {
primeString = P1536; primeString = P1536;
} }
return new BigInteger(primeString.replaceAll(" ", ""), 16); return new BigInteger(primeString.replaceAll(" ", ""), 16);
} }
} }

View File

@@ -1,23 +1,23 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.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);
} }

View File

@@ -1,62 +1,62 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu; import android.view.Menu;
import android.view.View; import android.view.View;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
public class PublicKeyListActivity extends KeyListActivity { public class PublicKeyListActivity extends KeyListActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
mExportFilename = Constants.path.app_dir + "/pubexport.asc"; mExportFilename = Constants.path.app_dir + "/pubexport.asc";
mKeyType = Id.type.public_key; mKeyType = Id.type.public_key;
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.import_keys, 0, R.string.menu_importKeys) menu.add(0, Id.menu.option.import_keys, 0, R.string.menu_importKeys)
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
menu.add(0, Id.menu.option.export_keys, 1, R.string.menu_exportKeys) menu.add(0, Id.menu.option.export_keys, 1, R.string.menu_exportKeys)
.setIcon(android.R.drawable.ic_menu_save); .setIcon(android.R.drawable.ic_menu_save);
menu.add(1, Id.menu.option.search, 2, R.string.menu_search) menu.add(1, Id.menu.option.search, 2, R.string.menu_search)
.setIcon(android.R.drawable.ic_menu_search); .setIcon(android.R.drawable.ic_menu_search);
menu.add(1, Id.menu.option.preferences, 3, R.string.menu_preferences) menu.add(1, Id.menu.option.preferences, 3, R.string.menu_preferences)
.setIcon(android.R.drawable.ic_menu_preferences); .setIcon(android.R.drawable.ic_menu_preferences);
menu.add(1, Id.menu.option.about, 4, R.string.menu_about) menu.add(1, Id.menu.option.about, 4, R.string.menu_about)
.setIcon(android.R.drawable.ic_menu_info_details); .setIcon(android.R.drawable.ic_menu_info_details);
return true; return true;
} }
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
ExpandableListView.ExpandableListContextMenuInfo info = ExpandableListView.ExpandableListContextMenuInfo info =
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo; (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
int type = ExpandableListView.getPackedPositionType(info.packedPosition); int type = ExpandableListView.getPackedPositionType(info.packedPosition);
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// TODO: user id? menu.setHeaderTitle("Key"); // TODO: user id? menu.setHeaderTitle("Key");
menu.add(0, Id.menu.export, 0, R.string.menu_exportKey); menu.add(0, Id.menu.export, 0, R.string.menu_exportKey);
menu.add(0, Id.menu.delete, 1, R.string.menu_deleteKey); menu.add(0, Id.menu.delete, 1, R.string.menu_deleteKey);
} }
} }
} }

View File

@@ -1,180 +1,180 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import android.app.Dialog; import android.app.Dialog;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ExpandableListView.OnChildClickListener;
public class SecretKeyListActivity extends KeyListActivity implements OnChildClickListener { public class SecretKeyListActivity extends KeyListActivity implements OnChildClickListener {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
mExportFilename = Constants.path.app_dir + "/secexport.asc"; mExportFilename = Constants.path.app_dir + "/secexport.asc";
mKeyType = Id.type.secret_key; mKeyType = Id.type.secret_key;
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mList.setOnChildClickListener(this); mList.setOnChildClickListener(this);
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.import_keys, 0, R.string.menu_importKeys) menu.add(0, Id.menu.option.import_keys, 0, R.string.menu_importKeys)
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
menu.add(0, Id.menu.option.export_keys, 1, R.string.menu_exportKeys) menu.add(0, Id.menu.option.export_keys, 1, R.string.menu_exportKeys)
.setIcon(android.R.drawable.ic_menu_save); .setIcon(android.R.drawable.ic_menu_save);
menu.add(1, Id.menu.option.create, 2, R.string.menu_createKey) menu.add(1, Id.menu.option.create, 2, R.string.menu_createKey)
.setIcon(android.R.drawable.ic_menu_add); .setIcon(android.R.drawable.ic_menu_add);
menu.add(3, Id.menu.option.search, 3, R.string.menu_search) menu.add(3, Id.menu.option.search, 3, R.string.menu_search)
.setIcon(android.R.drawable.ic_menu_search); .setIcon(android.R.drawable.ic_menu_search);
menu.add(3, Id.menu.option.preferences, 4, R.string.menu_preferences) menu.add(3, Id.menu.option.preferences, 4, R.string.menu_preferences)
.setIcon(android.R.drawable.ic_menu_preferences); .setIcon(android.R.drawable.ic_menu_preferences);
menu.add(3, Id.menu.option.about, 5, R.string.menu_about) menu.add(3, Id.menu.option.about, 5, R.string.menu_about)
.setIcon(android.R.drawable.ic_menu_info_details); .setIcon(android.R.drawable.ic_menu_info_details);
return true; return true;
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case Id.menu.option.create: { case Id.menu.option.create: {
createKey(); createKey();
return true; return true;
} }
default: { default: {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
} }
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
ExpandableListView.ExpandableListContextMenuInfo info = ExpandableListView.ExpandableListContextMenuInfo info =
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo; (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
int type = ExpandableListView.getPackedPositionType(info.packedPosition); int type = ExpandableListView.getPackedPositionType(info.packedPosition);
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// TODO: user id? menu.setHeaderTitle("Key"); // TODO: user id? menu.setHeaderTitle("Key");
menu.add(0, Id.menu.edit, 0, R.string.menu_editKey); menu.add(0, Id.menu.edit, 0, R.string.menu_editKey);
menu.add(0, Id.menu.export, 1, R.string.menu_exportKey); menu.add(0, Id.menu.export, 1, R.string.menu_exportKey);
menu.add(0, Id.menu.delete, 2, R.string.menu_deleteKey); menu.add(0, Id.menu.delete, 2, R.string.menu_deleteKey);
} }
} }
@Override @Override
public boolean onContextItemSelected(MenuItem menuItem) { public boolean onContextItemSelected(MenuItem menuItem) {
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo(); ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
int type = ExpandableListView.getPackedPositionType(info.packedPosition); int type = ExpandableListView.getPackedPositionType(info.packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition); int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) { if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
return super.onContextItemSelected(menuItem); return super.onContextItemSelected(menuItem);
} }
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case Id.menu.edit: { case Id.menu.edit: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
checkPassPhraseAndEdit(); checkPassPhraseAndEdit();
return true; return true;
} }
default: { default: {
return super.onContextItemSelected(menuItem); return super.onContextItemSelected(menuItem);
} }
} }
} }
@Override @Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) { int childPosition, long id) {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
checkPassPhraseAndEdit(); checkPassPhraseAndEdit();
return true; return true;
} }
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { switch (id) {
case Id.dialog.pass_phrase: { case Id.dialog.pass_phrase: {
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
return AskForSecretKeyPassPhrase.createDialog(this, keyId, this); return AskForSecretKeyPassPhrase.createDialog(this, keyId, this);
} }
default: { default: {
return super.onCreateDialog(id); return super.onCreateDialog(id);
} }
} }
} }
public void checkPassPhraseAndEdit() { public void checkPassPhraseAndEdit() {
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
String passPhrase = Apg.getCachedPassPhrase(keyId); String passPhrase = Apg.getCachedPassPhrase(keyId);
if (passPhrase == null) { if (passPhrase == null) {
showDialog(Id.dialog.pass_phrase); showDialog(Id.dialog.pass_phrase);
} else { } else {
Apg.setEditPassPhrase(passPhrase); Apg.setEditPassPhrase(passPhrase);
editKey(); editKey();
} }
} }
@Override @Override
public void passPhraseCallback(long keyId, String passPhrase) { public void passPhraseCallback(long keyId, String passPhrase) {
super.passPhraseCallback(keyId, passPhrase); super.passPhraseCallback(keyId, passPhrase);
Apg.setEditPassPhrase(passPhrase); Apg.setEditPassPhrase(passPhrase);
editKey(); editKey();
} }
private void createKey() { private void createKey() {
Apg.setEditPassPhrase(""); Apg.setEditPassPhrase("");
Intent intent = new Intent(this, EditKeyActivity.class); Intent intent = new Intent(this, EditKeyActivity.class);
startActivityForResult(intent, Id.message.create_key); startActivityForResult(intent, Id.message.create_key);
} }
private void editKey() { private void editKey() {
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
Intent intent = new Intent(this, EditKeyActivity.class); Intent intent = new Intent(this, EditKeyActivity.class);
intent.putExtra(Apg.EXTRA_KEY_ID, keyId); intent.putExtra(Apg.EXTRA_KEY_ID, keyId);
startActivityForResult(intent, Id.message.edit_key); startActivityForResult(intent, Id.message.edit_key);
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case Id.message.create_key: // intentionally no break case Id.message.create_key: // intentionally no break
case Id.message.edit_key: { case Id.message.edit_key: {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
refreshList(); refreshList();
} }
break; break;
} }
default: { default: {
break; break;
} }
} }
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
} }

View File

@@ -1,225 +1,225 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.util.Date; import java.util.Date;
import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds; import org.thialfihar.android.apg.provider.UserIds;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.DatabaseUtils; import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
public class SelectPublicKeyListAdapter extends BaseAdapter { public class SelectPublicKeyListAdapter extends BaseAdapter {
protected LayoutInflater mInflater; protected LayoutInflater mInflater;
protected ListView mParent; protected ListView mParent;
protected SQLiteDatabase mDatabase; protected SQLiteDatabase mDatabase;
protected Cursor mCursor; protected Cursor mCursor;
protected String mSearchString; protected String mSearchString;
protected Activity mActivity; protected Activity mActivity;
public SelectPublicKeyListAdapter(Activity activity, ListView parent, public SelectPublicKeyListAdapter(Activity activity, ListView parent,
String searchString, long selectedKeyIds[]) { String searchString, long selectedKeyIds[]) {
mSearchString = searchString; mSearchString = searchString;
mActivity = activity; mActivity = activity;
mParent = parent; mParent = parent;
mDatabase = Apg.getDatabase().db(); mDatabase = Apg.getDatabase().db();
mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
long now = new Date().getTime() / 1000; long now = new Date().getTime() / 1000;
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " +
"(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " +
Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " +
Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" +
") " + ") " +
" INNER JOIN " + UserIds.TABLE_NAME + " ON " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " +
"(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " +
UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " +
UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') ");
String inIdList = null; String inIdList = null;
if (selectedKeyIds != null && selectedKeyIds.length > 0) { if (selectedKeyIds != null && selectedKeyIds.length > 0) {
inIdList = KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID + " IN ("; inIdList = KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID + " IN (";
for (int i = 0; i < selectedKeyIds.length; ++i) { for (int i = 0; i < selectedKeyIds.length; ++i) {
if (i != 0) { if (i != 0) {
inIdList += ", "; inIdList += ", ";
} }
inIdList += DatabaseUtils.sqlEscapeString("" + selectedKeyIds[i]); inIdList += DatabaseUtils.sqlEscapeString("" + selectedKeyIds[i]);
} }
inIdList += ")"; inIdList += ")";
} }
if (searchString != null && searchString.trim().length() > 0) { if (searchString != null && searchString.trim().length() > 0) {
String[] chunks = searchString.trim().split(" +"); String[] chunks = searchString.trim().split(" +");
qb.appendWhere("(EXISTS (SELECT tmp." + UserIds._ID + " FROM " + qb.appendWhere("(EXISTS (SELECT tmp." + UserIds._ID + " FROM " +
UserIds.TABLE_NAME + " AS tmp WHERE " + UserIds.TABLE_NAME + " AS tmp WHERE " +
"tmp." + UserIds.KEY_ID + " = " + "tmp." + UserIds.KEY_ID + " = " +
Keys.TABLE_NAME + "." + Keys._ID); Keys.TABLE_NAME + "." + Keys._ID);
for (int i = 0; i < chunks.length; ++i) { for (int i = 0; i < chunks.length; ++i) {
qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE "); qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE ");
qb.appendWhereEscapeString("%" + chunks[i] + "%"); qb.appendWhereEscapeString("%" + chunks[i] + "%");
} }
qb.appendWhere("))"); qb.appendWhere("))");
if (inIdList != null) { if (inIdList != null) {
qb.appendWhere(" OR (" + inIdList + ")"); qb.appendWhere(" OR (" + inIdList + ")");
} }
} }
String orderBy = UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC"; String orderBy = UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC";
if (inIdList != null) { if (inIdList != null) {
orderBy = inIdList + " DESC, " + orderBy; orderBy = inIdList + " DESC, " + orderBy;
} }
mCursor = qb.query(mDatabase, mCursor = qb.query(mDatabase,
new String[] { new String[] {
KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0 KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0
KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1 KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2 UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2
"(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " + "(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " +
"tmp." + Keys.KEY_RING_ID + " = " + "tmp." + Keys.KEY_RING_ID + " = " +
KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " + KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " +
"tmp." + Keys.IS_REVOKED + " = '0' AND " + "tmp." + Keys.IS_REVOKED + " = '0' AND " +
"tmp." + Keys.CAN_ENCRYPT + " = '1')", // 3 "tmp." + Keys.CAN_ENCRYPT + " = '1')", // 3
"(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " + "(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " +
"tmp." + Keys.KEY_RING_ID + " = " + "tmp." + Keys.KEY_RING_ID + " = " +
KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " + KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " +
"tmp." + Keys.IS_REVOKED + " = '0' AND " + "tmp." + Keys.IS_REVOKED + " = '0' AND " +
"tmp." + Keys.CAN_ENCRYPT + " = '1' AND " + "tmp." + Keys.CAN_ENCRYPT + " = '1' AND " +
"tmp." + Keys.CREATION + " <= '" + now + "' AND " + "tmp." + Keys.CREATION + " <= '" + now + "' AND " +
"(tmp." + Keys.EXPIRY + " IS NULL OR " + "(tmp." + Keys.EXPIRY + " IS NULL OR " +
"tmp." + Keys.EXPIRY + " >= '" + now + "'))", // 4 "tmp." + Keys.EXPIRY + " >= '" + now + "'))", // 4
}, },
KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?",
new String[] { "" + Id.database.type_public }, new String[] { "" + Id.database.type_public },
null, null, orderBy); null, null, orderBy);
activity.startManagingCursor(mCursor); activity.startManagingCursor(mCursor);
} }
public void cleanup() { public void cleanup() {
if (mCursor != null) { if (mCursor != null) {
mActivity.stopManagingCursor(mCursor); mActivity.stopManagingCursor(mCursor);
mCursor.close(); mCursor.close();
} }
} }
@Override @Override
public boolean isEnabled(int position) { public boolean isEnabled(int position) {
mCursor.moveToPosition(position); mCursor.moveToPosition(position);
return mCursor.getInt(4) > 0; // valid CAN_ENCRYPT return mCursor.getInt(4) > 0; // valid CAN_ENCRYPT
} }
@Override @Override
public boolean hasStableIds() { public boolean hasStableIds() {
return true; return true;
} }
@Override @Override
public int getCount() { public int getCount() {
return mCursor.getCount(); return mCursor.getCount();
} }
@Override @Override
public Object getItem(int position) { public Object getItem(int position) {
return position; return position;
} }
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
mCursor.moveToPosition(position); mCursor.moveToPosition(position);
return mCursor.getLong(1); // MASTER_KEY_ID return mCursor.getLong(1); // MASTER_KEY_ID
} }
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
mCursor.moveToPosition(position); mCursor.moveToPosition(position);
View view = mInflater.inflate(R.layout.select_public_key_item, null); View view = mInflater.inflate(R.layout.select_public_key_item, null);
boolean enabled = isEnabled(position); boolean enabled = isEnabled(position);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId); mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText(""); mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.keyId); TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(R.string.noKey); keyId.setText(R.string.noKey);
TextView status = (TextView) view.findViewById(R.id.status); TextView status = (TextView) view.findViewById(R.id.status);
status.setText(R.string.unknownStatus); status.setText(R.string.unknownStatus);
String userId = mCursor.getString(2); // USER_ID String userId = mCursor.getString(2); // USER_ID
if (userId != null) { if (userId != null) {
String chunks[] = userId.split(" <", 2); String chunks[] = userId.split(" <", 2);
userId = chunks[0]; userId = chunks[0];
if (chunks.length > 1) { if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]); mainUserIdRest.setText("<" + chunks[1]);
} }
mainUserId.setText(userId); mainUserId.setText(userId);
} }
long masterKeyId = mCursor.getLong(1); // MASTER_KEY_ID long masterKeyId = mCursor.getLong(1); // MASTER_KEY_ID
keyId.setText("" + Long.toHexString(masterKeyId & 0xffffffffL)); keyId.setText("" + Long.toHexString(masterKeyId & 0xffffffffL));
if (mainUserIdRest.getText().length() == 0) { if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE); mainUserIdRest.setVisibility(View.GONE);
} }
if (enabled) { if (enabled) {
status.setText(R.string.canEncrypt); status.setText(R.string.canEncrypt);
} else { } else {
if (mCursor.getInt(3) > 0) { if (mCursor.getInt(3) > 0) {
// has some CAN_ENCRYPT keys, but col(4) = 0, so must be revoked or expired // has some CAN_ENCRYPT keys, but col(4) = 0, so must be revoked or expired
status.setText(R.string.expired); status.setText(R.string.expired);
} else { } else {
status.setText(R.string.noKey); status.setText(R.string.noKey);
} }
} }
status.setText(status.getText() + " "); status.setText(status.getText() + " ");
CheckBox selected = (CheckBox) view.findViewById(R.id.selected); CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
if (!enabled) { if (!enabled) {
mParent.setItemChecked(position, false); mParent.setItemChecked(position, false);
} }
selected.setChecked(mParent.isItemChecked(position)); selected.setChecked(mParent.isItemChecked(position));
view.setEnabled(enabled); view.setEnabled(enabled);
mainUserId.setEnabled(enabled); mainUserId.setEnabled(enabled);
mainUserIdRest.setEnabled(enabled); mainUserIdRest.setEnabled(enabled);
keyId.setEnabled(enabled); keyId.setEnabled(enabled);
selected.setEnabled(enabled); selected.setEnabled(enabled);
status.setEnabled(enabled); status.setEnabled(enabled);
return view; return view;
} }
} }

View File

@@ -1,175 +1,175 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.util.Date; import java.util.Date;
import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds; import org.thialfihar.android.apg.provider.UserIds;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
public class SelectSecretKeyListAdapter extends BaseAdapter { public class SelectSecretKeyListAdapter extends BaseAdapter {
protected LayoutInflater mInflater; protected LayoutInflater mInflater;
protected ListView mParent; protected ListView mParent;
protected SQLiteDatabase mDatabase; protected SQLiteDatabase mDatabase;
protected Cursor mCursor; protected Cursor mCursor;
protected String mSearchString; protected String mSearchString;
protected Activity mActivity; protected Activity mActivity;
public SelectSecretKeyListAdapter(Activity activity, ListView parent, String searchString) { public SelectSecretKeyListAdapter(Activity activity, ListView parent, String searchString) {
mSearchString = searchString; mSearchString = searchString;
mActivity = activity; mActivity = activity;
mParent = parent; mParent = parent;
mDatabase = Apg.getDatabase().db(); mDatabase = Apg.getDatabase().db();
mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
long now = new Date().getTime() / 1000; long now = new Date().getTime() / 1000;
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " +
"(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " +
Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " +
Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" +
") " + ") " +
" INNER JOIN " + UserIds.TABLE_NAME + " ON " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " +
"(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " +
UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " +
UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') ");
if (searchString != null && searchString.trim().length() > 0) { if (searchString != null && searchString.trim().length() > 0) {
String[] chunks = searchString.trim().split(" +"); String[] chunks = searchString.trim().split(" +");
qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " + qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " +
UserIds.TABLE_NAME + " AS tmp WHERE " + UserIds.TABLE_NAME + " AS tmp WHERE " +
"tmp." + UserIds.KEY_ID + " = " + "tmp." + UserIds.KEY_ID + " = " +
Keys.TABLE_NAME + "." + Keys._ID); Keys.TABLE_NAME + "." + Keys._ID);
for (int i = 0; i < chunks.length; ++i) { for (int i = 0; i < chunks.length; ++i) {
qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE "); qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE ");
qb.appendWhereEscapeString("%" + chunks[i] + "%"); qb.appendWhereEscapeString("%" + chunks[i] + "%");
} }
qb.appendWhere(")"); qb.appendWhere(")");
} }
mCursor = qb.query(mDatabase, mCursor = qb.query(mDatabase,
new String[] { new String[] {
KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0 KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0
KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1 KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2 UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2
"(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " + "(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " +
"tmp." + Keys.KEY_RING_ID + " = " + "tmp." + Keys.KEY_RING_ID + " = " +
KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " + KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " +
"tmp." + Keys.IS_REVOKED + " = '0' AND " + "tmp." + Keys.IS_REVOKED + " = '0' AND " +
"tmp." + Keys.CAN_SIGN + " = '1')", // 3, "tmp." + Keys.CAN_SIGN + " = '1')", // 3,
"(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " + "(SELECT COUNT(tmp." + Keys._ID + ") FROM " + Keys.TABLE_NAME + " AS tmp WHERE " +
"tmp." + Keys.KEY_RING_ID + " = " + "tmp." + Keys.KEY_RING_ID + " = " +
KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " + KeyRings.TABLE_NAME + "." + KeyRings._ID + " AND " +
"tmp." + Keys.IS_REVOKED + " = '0' AND " + "tmp." + Keys.IS_REVOKED + " = '0' AND " +
"tmp." + Keys.CAN_SIGN + " = '1' AND " + "tmp." + Keys.CAN_SIGN + " = '1' AND " +
"tmp." + Keys.CREATION + " <= '" + now + "' AND " + "tmp." + Keys.CREATION + " <= '" + now + "' AND " +
"(tmp." + Keys.EXPIRY + " IS NULL OR " + "(tmp." + Keys.EXPIRY + " IS NULL OR " +
"tmp." + Keys.EXPIRY + " >= '" + now + "'))", // 4 "tmp." + Keys.EXPIRY + " >= '" + now + "'))", // 4
}, },
KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?",
new String[] { "" + Id.database.type_secret }, new String[] { "" + Id.database.type_secret },
null, null, UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC"); null, null, UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC");
activity.startManagingCursor(mCursor); activity.startManagingCursor(mCursor);
} }
public void cleanup() { public void cleanup() {
if (mCursor != null) { if (mCursor != null) {
mActivity.stopManagingCursor(mCursor); mActivity.stopManagingCursor(mCursor);
mCursor.close(); mCursor.close();
} }
} }
@Override @Override
public boolean isEnabled(int position) { public boolean isEnabled(int position) {
mCursor.moveToPosition(position); mCursor.moveToPosition(position);
return mCursor.getInt(4) > 0; // valid CAN_SIGN return mCursor.getInt(4) > 0; // valid CAN_SIGN
} }
@Override @Override
public boolean hasStableIds() { public boolean hasStableIds() {
return true; return true;
} }
@Override @Override
public int getCount() { public int getCount() {
return mCursor.getCount(); return mCursor.getCount();
} }
@Override @Override
public Object getItem(int position) { public Object getItem(int position) {
return position; return position;
} }
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
mCursor.moveToPosition(position); mCursor.moveToPosition(position);
return mCursor.getLong(1); // MASTER_KEY_ID return mCursor.getLong(1); // MASTER_KEY_ID
} }
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
mCursor.moveToPosition(position); mCursor.moveToPosition(position);
View view = mInflater.inflate(R.layout.select_secret_key_item, null); View view = mInflater.inflate(R.layout.select_secret_key_item, null);
boolean enabled = isEnabled(position); boolean enabled = isEnabled(position);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId); mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText(""); mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.keyId); TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(R.string.noKey); keyId.setText(R.string.noKey);
TextView status = (TextView) view.findViewById(R.id.status); TextView status = (TextView) view.findViewById(R.id.status);
status.setText(R.string.unknownStatus); status.setText(R.string.unknownStatus);
String userId = mCursor.getString(2); // USER_ID String userId = mCursor.getString(2); // USER_ID
if (userId != null) { if (userId != null) {
String chunks[] = userId.split(" <", 2); String chunks[] = userId.split(" <", 2);
userId = chunks[0]; userId = chunks[0];
if (chunks.length > 1) { if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]); mainUserIdRest.setText("<" + chunks[1]);
} }
mainUserId.setText(userId); mainUserId.setText(userId);
} }
long masterKeyId = mCursor.getLong(1); // MASTER_KEY_ID long masterKeyId = mCursor.getLong(1); // MASTER_KEY_ID
keyId.setText("" + Long.toHexString(masterKeyId & 0xffffffffL)); keyId.setText("" + Long.toHexString(masterKeyId & 0xffffffffL));
if (mainUserIdRest.getText().length() == 0) { if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE); mainUserIdRest.setVisibility(View.GONE);
} }
if (enabled) { if (enabled) {
status.setText(R.string.canSign); status.setText(R.string.canSign);
} else { } else {
if (mCursor.getInt(3) > 0) { if (mCursor.getInt(3) > 0) {
// has some CAN_SIGN keys, but col(4) = 0, so must be revoked or expired // has some CAN_SIGN keys, but col(4) = 0, so must be revoked or expired
status.setText(R.string.expired); status.setText(R.string.expired);
} else { } else {
status.setText(R.string.noKey); status.setText(R.string.noKey);
} }
} }
status.setText(status.getText() + " "); status.setText(status.getText() + " ");
view.setEnabled(enabled); view.setEnabled(enabled);
mainUserId.setEnabled(enabled); mainUserId.setEnabled(enabled);
mainUserIdRest.setEnabled(enabled); mainUserIdRest.setEnabled(enabled);
keyId.setEnabled(enabled); keyId.setEnabled(enabled);
status.setEnabled(enabled); status.setEnabled(enabled);
return view; return view;
} }
} }

View File

@@ -1,78 +1,78 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import android.content.Intent; import android.content.Intent;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
public class Service extends android.app.Service { public class Service extends android.app.Service {
private final IBinder mBinder = new LocalBinder(); private final IBinder mBinder = new LocalBinder();
public static final String EXTRA_TTL = "ttl"; public static final String EXTRA_TTL = "ttl";
private int mPassPhraseCacheTtl = 15; private int mPassPhraseCacheTtl = 15;
private Handler mCacheHandler = new Handler(); private Handler mCacheHandler = new Handler();
private Runnable mCacheTask = new Runnable() { private Runnable mCacheTask = new Runnable() {
public void run() { public void run() {
// check every ttl/2 seconds, which shouldn't be heavy on the device (even if ttl = 15), // check every ttl/2 seconds, which shouldn't be heavy on the device (even if ttl = 15),
// and makes sure the longest a pass phrase survives in the cache is 1.5 * ttl // and makes sure the longest a pass phrase survives in the cache is 1.5 * ttl
int delay = mPassPhraseCacheTtl * 1000 / 2; int delay = mPassPhraseCacheTtl * 1000 / 2;
// also make sure the delay is not longer than one minute // also make sure the delay is not longer than one minute
if (delay > 60000) { if (delay > 60000) {
delay = 60000; delay = 60000;
} }
delay = Apg.cleanUpCache(mPassPhraseCacheTtl, delay); delay = Apg.cleanUpCache(mPassPhraseCacheTtl, delay);
// don't check too often, even if we were close // don't check too often, even if we were close
if (delay < 5000) { if (delay < 5000) {
delay = 5000; delay = 5000;
} }
mCacheHandler.postDelayed(this, delay); mCacheHandler.postDelayed(this, delay);
} }
}; };
static private boolean mIsRunning = false; static private boolean mIsRunning = false;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
mIsRunning = true; mIsRunning = true;
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mIsRunning = false; mIsRunning = false;
} }
@Override @Override
public void onStart(Intent intent, int startId) { public void onStart(Intent intent, int startId) {
super.onStart(intent, startId); super.onStart(intent, startId);
if (intent != null) { if (intent != null) {
mPassPhraseCacheTtl = intent.getIntExtra(EXTRA_TTL, 15); mPassPhraseCacheTtl = intent.getIntExtra(EXTRA_TTL, 15);
} }
if (mPassPhraseCacheTtl < 15) { if (mPassPhraseCacheTtl < 15) {
mPassPhraseCacheTtl = 15; mPassPhraseCacheTtl = 15;
} }
mCacheHandler.removeCallbacks(mCacheTask); mCacheHandler.removeCallbacks(mCacheTask);
mCacheHandler.postDelayed(mCacheTask, 1000); mCacheHandler.postDelayed(mCacheTask, 1000);
} }
static public boolean isRunning() { static public boolean isRunning() {
return mIsRunning; return mIsRunning;
} }
public class LocalBinder extends Binder { public class LocalBinder extends Binder {
Service getService() { Service getService() {
return Service.this; return Service.this;
} }
} }
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return mBinder; return mBinder;
} }
} }

View File

@@ -1,27 +1,27 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.provider; package org.thialfihar.android.apg.provider;
import android.provider.BaseColumns; import android.provider.BaseColumns;
public class Accounts implements BaseColumns { public class Accounts implements BaseColumns {
public static final String TABLE_NAME = "accounts"; public static final String TABLE_NAME = "accounts";
public static final String _ID_type = "INTEGER PRIMARY KEY"; public static final String _ID_type = "INTEGER PRIMARY KEY";
public static final String NAME = "c_name"; public static final String NAME = "c_name";
public static final String NAME_type = "TEXT"; public static final String NAME_type = "TEXT";
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,33 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.provider; package org.thialfihar.android.apg.provider;
import android.provider.BaseColumns; import android.provider.BaseColumns;
public class KeyRings implements BaseColumns { public class KeyRings implements BaseColumns {
public static final String TABLE_NAME = "key_rings"; public static final String TABLE_NAME = "key_rings";
public static final String _ID_type = "INTEGER PRIMARY KEY"; public static final String _ID_type = "INTEGER PRIMARY KEY";
public static final String MASTER_KEY_ID = "c_master_key_id"; public static final String MASTER_KEY_ID = "c_master_key_id";
public static final String MASTER_KEY_ID_type = "INT64"; public static final String MASTER_KEY_ID_type = "INT64";
public static final String TYPE = "c_type"; public static final String TYPE = "c_type";
public static final String TYPE_type = "INTEGER"; public static final String TYPE_type = "INTEGER";
public static final String WHO_ID = "c_who_id"; public static final String WHO_ID = "c_who_id";
public static final String WHO_ID_type = "INTEGER"; public static final String WHO_ID_type = "INTEGER";
public static final String KEY_RING_DATA = "c_key_ring_data"; public static final String KEY_RING_DATA = "c_key_ring_data";
public static final String KEY_RING_DATA_type = "BLOB"; public static final String KEY_RING_DATA_type = "BLOB";
} }

View File

@@ -1,31 +1,31 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.provider; package org.thialfihar.android.apg.provider;
import android.provider.BaseColumns; import android.provider.BaseColumns;
public class UserIds implements BaseColumns { public class UserIds implements BaseColumns {
public static final String TABLE_NAME = "user_ids"; public static final String TABLE_NAME = "user_ids";
public static final String _ID_type = "INTEGER PRIMARY KEY"; public static final String _ID_type = "INTEGER PRIMARY KEY";
public static final String KEY_ID = "c_key_id"; public static final String KEY_ID = "c_key_id";
public static final String KEY_ID_type = "INTEGER"; public static final String KEY_ID_type = "INTEGER";
public static final String USER_ID = "c_user_id"; public static final String USER_ID = "c_user_id";
public static final String USER_ID_type = "TEXT"; public static final String USER_ID_type = "TEXT";
public static final String RANK = "c_rank"; public static final String RANK = "c_rank";
public static final String RANK_type = "INTEGER"; public static final String RANK_type = "INTEGER";
} }

View File

@@ -1,25 +1,25 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.ui.widget; package org.thialfihar.android.apg.ui.widget;
public interface Editor { public interface Editor {
public interface EditorListener { public interface EditorListener {
public void onDeleted(Editor editor); public void onDeleted(Editor editor);
} }
public void setEditorListener(EditorListener listener); public void setEditorListener(EditorListener listener);
} }

View File

@@ -1,242 +1,242 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.ui.widget; package org.thialfihar.android.apg.ui.widget;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.Vector; import java.util.Vector;
import org.bouncycastle2.openpgp.PGPPublicKey; import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.utils.Choice; import org.thialfihar.android.apg.utils.Choice;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.DatePicker; import android.widget.DatePicker;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
public class KeyEditor extends LinearLayout implements Editor, OnClickListener { public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private PGPSecretKey mKey; private PGPSecretKey mKey;
private EditorListener mEditorListener = null; private EditorListener mEditorListener = null;
private boolean mIsMasterKey; private boolean mIsMasterKey;
ImageButton mDeleteButton; ImageButton mDeleteButton;
TextView mAlgorithm; TextView mAlgorithm;
TextView mKeyId; TextView mKeyId;
Spinner mUsage; Spinner mUsage;
TextView mCreationDate; TextView mCreationDate;
Button mExpiryDateButton; Button mExpiryDateButton;
GregorianCalendar mExpiryDate; GregorianCalendar mExpiryDate;
private DatePickerDialog.OnDateSetListener mExpiryDateSetListener = private DatePickerDialog.OnDateSetListener mExpiryDateSetListener =
new DatePickerDialog.OnDateSetListener() { new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
GregorianCalendar date = new GregorianCalendar(year, monthOfYear, dayOfMonth); GregorianCalendar date = new GregorianCalendar(year, monthOfYear, dayOfMonth);
setExpiryDate(date); setExpiryDate(date);
} }
}; };
public KeyEditor(Context context) { public KeyEditor(Context context) {
super(context); super(context);
} }
public KeyEditor(Context context, AttributeSet attrs) { public KeyEditor(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
setDrawingCacheEnabled(true); setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true); setAlwaysDrawnWithCacheEnabled(true);
mAlgorithm = (TextView) findViewById(R.id.algorithm); mAlgorithm = (TextView) findViewById(R.id.algorithm);
mKeyId = (TextView) findViewById(R.id.keyId); mKeyId = (TextView) findViewById(R.id.keyId);
mCreationDate = (TextView) findViewById(R.id.creation); mCreationDate = (TextView) findViewById(R.id.creation);
mExpiryDateButton = (Button) findViewById(R.id.expiry); mExpiryDateButton = (Button) findViewById(R.id.expiry);
mUsage = (Spinner) findViewById(R.id.usage); mUsage = (Spinner) findViewById(R.id.usage);
Choice choices[] = { Choice choices[] = {
new Choice(Id.choice.usage.sign_only, new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.choice_signOnly)), getResources().getString(R.string.choice_signOnly)),
new Choice(Id.choice.usage.encrypt_only, new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.choice_encryptOnly)), getResources().getString(R.string.choice_encryptOnly)),
new Choice(Id.choice.usage.sign_and_encrypt, new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.choice_signAndEncrypt)), getResources().getString(R.string.choice_signAndEncrypt)),
}; };
ArrayAdapter<Choice> adapter = ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(), new ArrayAdapter<Choice>(getContext(),
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);
mUsage.setAdapter(adapter); mUsage.setAdapter(adapter);
mDeleteButton = (ImageButton) findViewById(R.id.delete); mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this); mDeleteButton.setOnClickListener(this);
setExpiryDate(null); setExpiryDate(null);
mExpiryDateButton.setOnClickListener(new OnClickListener() { mExpiryDateButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
GregorianCalendar date = mExpiryDate; GregorianCalendar date = mExpiryDate;
if (date == null) { if (date == null) {
date = new GregorianCalendar(); date = new GregorianCalendar();
} }
DatePickerDialog dialog = DatePickerDialog dialog =
new DatePickerDialog(getContext(), mExpiryDateSetListener, new DatePickerDialog(getContext(), mExpiryDateSetListener,
date.get(Calendar.YEAR), date.get(Calendar.YEAR),
date.get(Calendar.MONTH), date.get(Calendar.MONTH),
date.get(Calendar.DAY_OF_MONTH)); date.get(Calendar.DAY_OF_MONTH));
dialog.setCancelable(true); dialog.setCancelable(true);
dialog.setButton(Dialog.BUTTON_NEGATIVE, dialog.setButton(Dialog.BUTTON_NEGATIVE,
getContext().getString(R.string.btn_noDate), getContext().getString(R.string.btn_noDate),
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
setExpiryDate(null); setExpiryDate(null);
} }
}); });
dialog.show(); dialog.show();
} }
}); });
super.onFinishInflate(); super.onFinishInflate();
} }
public void setValue(PGPSecretKey key, boolean isMasterKey) { public void setValue(PGPSecretKey key, boolean isMasterKey) {
mKey = key; mKey = key;
mIsMasterKey = isMasterKey; mIsMasterKey = isMasterKey;
if (mIsMasterKey) { if (mIsMasterKey) {
mDeleteButton.setVisibility(View.INVISIBLE); mDeleteButton.setVisibility(View.INVISIBLE);
} }
mAlgorithm.setText(Apg.getAlgorithmInfo(key)); mAlgorithm.setText(Apg.getAlgorithmInfo(key));
String keyId1Str = Long.toHexString((key.getKeyID() >> 32) & 0xffffffffL); String keyId1Str = Long.toHexString((key.getKeyID() >> 32) & 0xffffffffL);
while (keyId1Str.length() < 8) { while (keyId1Str.length() < 8) {
keyId1Str = "0" + keyId1Str; keyId1Str = "0" + keyId1Str;
} }
String keyId2Str = Long.toHexString(key.getKeyID() & 0xffffffffL); String keyId2Str = Long.toHexString(key.getKeyID() & 0xffffffffL);
while (keyId2Str.length() < 8) { while (keyId2Str.length() < 8) {
keyId2Str = "0" + keyId2Str; keyId2Str = "0" + keyId2Str;
} }
mKeyId.setText(keyId1Str + " " + keyId2Str); mKeyId.setText(keyId1Str + " " + keyId2Str);
Vector<Choice> choices = new Vector<Choice>(); Vector<Choice> choices = new Vector<Choice>();
boolean isElGamalKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT); boolean isElGamalKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT);
if (!isElGamalKey) { if (!isElGamalKey) {
choices.add(new Choice(Id.choice.usage.sign_only, choices.add(new Choice(Id.choice.usage.sign_only,
getResources().getString(R.string.choice_signOnly))); getResources().getString(R.string.choice_signOnly)));
} }
if (!mIsMasterKey) { if (!mIsMasterKey) {
choices.add(new Choice(Id.choice.usage.encrypt_only, choices.add(new Choice(Id.choice.usage.encrypt_only,
getResources().getString(R.string.choice_encryptOnly))); getResources().getString(R.string.choice_encryptOnly)));
} }
if (!isElGamalKey) { if (!isElGamalKey) {
choices.add(new Choice(Id.choice.usage.sign_and_encrypt, choices.add(new Choice(Id.choice.usage.sign_and_encrypt,
getResources().getString(R.string.choice_signAndEncrypt))); getResources().getString(R.string.choice_signAndEncrypt)));
} }
ArrayAdapter<Choice> adapter = ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(), new ArrayAdapter<Choice>(getContext(),
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);
mUsage.setAdapter(adapter); mUsage.setAdapter(adapter);
int selectId = 0; int selectId = 0;
if (Apg.isEncryptionKey(key)) { if (Apg.isEncryptionKey(key)) {
if (Apg.isSigningKey(key)) { if (Apg.isSigningKey(key)) {
selectId = Id.choice.usage.sign_and_encrypt; selectId = Id.choice.usage.sign_and_encrypt;
} else { } else {
selectId = Id.choice.usage.encrypt_only; selectId = Id.choice.usage.encrypt_only;
} }
} else { } else {
selectId = Id.choice.usage.sign_only; selectId = Id.choice.usage.sign_only;
} }
for (int i = 0; i < choices.size(); ++i) { for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == selectId) { if (choices.get(i).getId() == selectId) {
mUsage.setSelection(i); mUsage.setSelection(i);
break; break;
} }
} }
GregorianCalendar cal = new GregorianCalendar(); GregorianCalendar cal = new GregorianCalendar();
cal.setTime(Apg.getCreationDate(key)); cal.setTime(Apg.getCreationDate(key));
mCreationDate.setText(DateFormat.getDateInstance().format(cal.getTime())); mCreationDate.setText(DateFormat.getDateInstance().format(cal.getTime()));
cal = new GregorianCalendar(); cal = new GregorianCalendar();
Date date = Apg.getExpiryDate(key); Date date = Apg.getExpiryDate(key);
if (date == null) { if (date == null) {
setExpiryDate(null); setExpiryDate(null);
} else { } else {
cal.setTime(Apg.getExpiryDate(key)); cal.setTime(Apg.getExpiryDate(key));
setExpiryDate(cal); setExpiryDate(cal);
} }
} }
public PGPSecretKey getValue() { public PGPSecretKey getValue() {
return mKey; return mKey;
} }
@Override @Override
public void onClick(View v) { public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent(); final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) { if (v == mDeleteButton) {
parent.removeView(this); parent.removeView(this);
if (mEditorListener != null) { if (mEditorListener != null) {
mEditorListener.onDeleted(this); mEditorListener.onDeleted(this);
} }
} }
} }
@Override @Override
public void setEditorListener(EditorListener listener) { public void setEditorListener(EditorListener listener) {
mEditorListener = listener; mEditorListener = listener;
} }
private void setExpiryDate(GregorianCalendar date) { private void setExpiryDate(GregorianCalendar date) {
mExpiryDate = date; mExpiryDate = date;
if (date == null) { if (date == null) {
mExpiryDateButton.setText(R.string.none); mExpiryDateButton.setText(R.string.none);
} else { } else {
mExpiryDateButton.setText(DateFormat.getDateInstance().format(date.getTime())); mExpiryDateButton.setText(DateFormat.getDateInstance().format(date.getTime()));
} }
} }
public GregorianCalendar getExpiryDate() { public GregorianCalendar getExpiryDate() {
return mExpiryDate; return mExpiryDate;
} }
public int getUsage() { public int getUsage() {
return ((Choice) mUsage.getSelectedItem()).getId(); return ((Choice) mUsage.getSelectedItem()).getId();
} }
} }

View File

@@ -1,337 +1,337 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.ui.widget; package org.thialfihar.android.apg.ui.widget;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException; import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.util.Vector; import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener; import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.utils.Choice; import org.thialfihar.android.apg.utils.Choice;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Runnable { public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Runnable {
private LayoutInflater mInflater; private LayoutInflater mInflater;
private View mAdd; private View mAdd;
private ViewGroup mEditors; private ViewGroup mEditors;
private TextView mTitle; private TextView mTitle;
private int mType = 0; private int mType = 0;
private Choice mNewKeyAlgorithmChoice; private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize; private int mNewKeySize;
volatile private PGPSecretKey mNewKey; volatile private PGPSecretKey mNewKey;
private ProgressDialog mProgressDialog; private ProgressDialog mProgressDialog;
private Thread mRunningThread = null; private Thread mRunningThread = null;
private Handler mHandler = new Handler() { private Handler mHandler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
Bundle data = msg.getData(); Bundle data = msg.getData();
if (data != null) { if (data != null) {
boolean closeProgressDialog = data.getBoolean("closeProgressDialog"); boolean closeProgressDialog = data.getBoolean("closeProgressDialog");
if (closeProgressDialog) { if (closeProgressDialog) {
if (mProgressDialog != null) { if (mProgressDialog != null) {
mProgressDialog.dismiss(); mProgressDialog.dismiss();
mProgressDialog = null; mProgressDialog = null;
} }
} }
String error = data.getString(Apg.EXTRA_ERROR); String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) { if (error != null) {
Toast.makeText(getContext(), Toast.makeText(getContext(),
getContext().getString(R.string.errorMessage, error), getContext().getString(R.string.errorMessage, error),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
boolean gotNewKey = data.getBoolean("gotNewKey"); boolean gotNewKey = data.getBoolean("gotNewKey");
if (gotNewKey) { if (gotNewKey) {
KeyEditor view = KeyEditor view =
(KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item,
mEditors, false); mEditors, false);
view.setEditorListener(SectionView.this); view.setEditorListener(SectionView.this);
boolean isMasterKey = (mEditors.getChildCount() == 0); boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(mNewKey, isMasterKey); view.setValue(mNewKey, isMasterKey);
mEditors.addView(view); mEditors.addView(view);
SectionView.this.updateEditorsVisible(); SectionView.this.updateEditorsVisible();
} }
} }
} }
}; };
public SectionView(Context context) { public SectionView(Context context) {
super(context); super(context);
} }
public SectionView(Context context, AttributeSet attrs) { public SectionView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
public ViewGroup getEditors() { public ViewGroup getEditors() {
return mEditors; return mEditors;
} }
public void setType(int type) { public void setType(int type) {
mType = type; mType = type;
switch (type) { switch (type) {
case Id.type.user_id: { case Id.type.user_id: {
mTitle.setText(R.string.section_userIds); mTitle.setText(R.string.section_userIds);
break; break;
} }
case Id.type.key: { case Id.type.key: {
mTitle.setText(R.string.section_keys); mTitle.setText(R.string.section_keys);
break; break;
} }
default: { default: {
break; break;
} }
} }
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setDrawingCacheEnabled(true); setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true); setAlwaysDrawnWithCacheEnabled(true);
mAdd = findViewById(R.id.header); mAdd = findViewById(R.id.header);
mAdd.setOnClickListener(this); mAdd.setOnClickListener(this);
mEditors = (ViewGroup) findViewById(R.id.editors); mEditors = (ViewGroup) findViewById(R.id.editors);
mTitle = (TextView) findViewById(R.id.title); mTitle = (TextView) findViewById(R.id.title);
updateEditorsVisible(); updateEditorsVisible();
super.onFinishInflate(); super.onFinishInflate();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void onDeleted(Editor editor) { public void onDeleted(Editor editor) {
this.updateEditorsVisible(); this.updateEditorsVisible();
} }
protected void updateEditorsVisible() { protected void updateEditorsVisible() {
final boolean hasChildren = mEditors.getChildCount() > 0; final boolean hasChildren = mEditors.getChildCount() > 0;
mEditors.setVisibility(hasChildren ? View.VISIBLE : View.GONE); mEditors.setVisibility(hasChildren ? View.VISIBLE : View.GONE);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void onClick(View v) { public void onClick(View v) {
switch (mType) { switch (mType) {
case Id.type.user_id: { case Id.type.user_id: {
UserIdEditor view = UserIdEditor view =
(UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item,
mEditors, false); mEditors, false);
view.setEditorListener(this); view.setEditorListener(this);
if (mEditors.getChildCount() == 0) { if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true); view.setIsMainUserId(true);
} }
mEditors.addView(view); mEditors.addView(view);
break; break;
} }
case Id.type.key: { case Id.type.key: {
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
View view = mInflater.inflate(R.layout.create_key, null); View view = mInflater.inflate(R.layout.create_key, null);
dialog.setView(view); dialog.setView(view);
dialog.setTitle(R.string.title_createKey); dialog.setTitle(R.string.title_createKey);
dialog.setMessage(R.string.keyCreationElGamalInfo); dialog.setMessage(R.string.keyCreationElGamalInfo);
boolean wouldBeMasterKey = (mEditors.getChildCount() == 0); boolean wouldBeMasterKey = (mEditors.getChildCount() == 0);
final Spinner algorithm = (Spinner) view.findViewById(R.id.algorithm); final Spinner algorithm = (Spinner) view.findViewById(R.id.algorithm);
Vector<Choice> choices = new Vector<Choice>(); Vector<Choice> choices = new Vector<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa, choices.add(new Choice(Id.choice.algorithm.dsa,
getResources().getString(R.string.dsa))); getResources().getString(R.string.dsa)));
if (!wouldBeMasterKey) { if (!wouldBeMasterKey) {
choices.add(new Choice(Id.choice.algorithm.elgamal, choices.add(new Choice(Id.choice.algorithm.elgamal,
getResources().getString(R.string.elgamal))); getResources().getString(R.string.elgamal)));
} }
choices.add(new Choice(Id.choice.algorithm.rsa, choices.add(new Choice(Id.choice.algorithm.rsa,
getResources().getString(R.string.rsa))); getResources().getString(R.string.rsa)));
ArrayAdapter<Choice> adapter = ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(getContext(), new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item,
choices); choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
algorithm.setAdapter(adapter); algorithm.setAdapter(adapter);
// make RSA the default // make RSA the default
for (int i = 0; i < choices.size(); ++i) { for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == Id.choice.algorithm.rsa) { if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
algorithm.setSelection(i); algorithm.setSelection(i);
break; break;
} }
} }
final EditText keySize = (EditText) view.findViewById(R.id.size); final EditText keySize = (EditText) view.findViewById(R.id.size);
dialog.setPositiveButton(android.R.string.ok, dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface di, int id) { public void onClick(DialogInterface di, int id) {
di.dismiss(); di.dismiss();
try { try {
mNewKeySize = Integer.parseInt("" + keySize.getText()); mNewKeySize = Integer.parseInt("" + keySize.getText());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
mNewKeySize = 0; mNewKeySize = 0;
} }
mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem(); mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
createKey(); createKey();
} }
}); });
dialog.setCancelable(true); dialog.setCancelable(true);
dialog.setNegativeButton(android.R.string.cancel, dialog.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface di, int id) { public void onClick(DialogInterface di, int id) {
di.dismiss(); di.dismiss();
} }
}); });
dialog.create().show(); dialog.create().show();
break; break;
} }
default: { default: {
break; break;
} }
} }
this.updateEditorsVisible(); this.updateEditorsVisible();
} }
public void setUserIds(Vector<String> list) { public void setUserIds(Vector<String> list) {
if (mType != Id.type.user_id) { if (mType != Id.type.user_id) {
return; return;
} }
mEditors.removeAllViews(); mEditors.removeAllViews();
for (String userId : list) { for (String userId : list) {
UserIdEditor view = UserIdEditor view =
(UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, mEditors, false); (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, mEditors, false);
view.setEditorListener(this); view.setEditorListener(this);
view.setValue(userId); view.setValue(userId);
if (mEditors.getChildCount() == 0) { if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true); view.setIsMainUserId(true);
} }
mEditors.addView(view); mEditors.addView(view);
} }
this.updateEditorsVisible(); this.updateEditorsVisible();
} }
public void setKeys(Vector<PGPSecretKey> list) { public void setKeys(Vector<PGPSecretKey> list) {
if (mType != Id.type.key) { if (mType != Id.type.key) {
return; return;
} }
mEditors.removeAllViews(); mEditors.removeAllViews();
for (PGPSecretKey key : list) { for (PGPSecretKey key : list) {
KeyEditor view = KeyEditor view =
(KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, mEditors, false); (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, mEditors, false);
view.setEditorListener(this); view.setEditorListener(this);
boolean isMasterKey = (mEditors.getChildCount() == 0); boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(key, isMasterKey); view.setValue(key, isMasterKey);
mEditors.addView(view); mEditors.addView(view);
} }
this.updateEditorsVisible(); this.updateEditorsVisible();
} }
private void createKey() { private void createKey() {
mProgressDialog = new ProgressDialog(getContext()); mProgressDialog = new ProgressDialog(getContext());
mProgressDialog.setMessage(getContext().getString(R.string.progress_generating)); mProgressDialog.setMessage(getContext().getString(R.string.progress_generating));
mProgressDialog.setCancelable(false); mProgressDialog.setCancelable(false);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.show(); mProgressDialog.show();
mRunningThread = new Thread(this); mRunningThread = new Thread(this);
mRunningThread.start(); mRunningThread.start();
} }
public void run() { public void run() {
String error = null; String error = null;
try { try {
PGPSecretKey masterKey = null; PGPSecretKey masterKey = null;
String passPhrase; String passPhrase;
if (mEditors.getChildCount() > 0) { if (mEditors.getChildCount() > 0) {
masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID()); passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID());
} else { } else {
passPhrase = ""; passPhrase = "";
} }
mNewKey = Apg.createKey(getContext(), mNewKey = Apg.createKey(getContext(),
mNewKeyAlgorithmChoice.getId(), mNewKeyAlgorithmChoice.getId(),
mNewKeySize, passPhrase, mNewKeySize, passPhrase,
masterKey); masterKey);
} catch (NoSuchProviderException e) { } catch (NoSuchProviderException e) {
error = "" + e; error = "" + e;
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
error = "" + e; error = "" + e;
} catch (PGPException e) { } catch (PGPException e) {
error = "" + e; error = "" + e;
} catch (InvalidParameterException e) { } catch (InvalidParameterException e) {
error = "" + e; error = "" + e;
} catch (InvalidAlgorithmParameterException e) { } catch (InvalidAlgorithmParameterException e) {
error = "" + e; error = "" + e;
} catch (Apg.GeneralException e) { } catch (Apg.GeneralException e) {
error = "" + e; error = "" + e;
} }
Message message = new Message(); Message message = new Message();
Bundle data = new Bundle(); Bundle data = new Bundle();
data.putBoolean("closeProgressDialog", true); data.putBoolean("closeProgressDialog", true);
if (error != null) { if (error != null) {
data.putString(Apg.EXTRA_ERROR, error); data.putString(Apg.EXTRA_ERROR, error);
} else { } else {
data.putBoolean("gotNewKey", true); data.putBoolean("gotNewKey", true);
} }
message.setData(data); message.setData(data);
mHandler.sendMessage(message); mHandler.sendMessage(message);
} }
} }

View File

@@ -1,194 +1,194 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.ui.widget; package org.thialfihar.android.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.thialfihar.android.apg.R;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioButton; import android.widget.RadioButton;
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener { public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null; private EditorListener mEditorListener = null;
private ImageButton mDeleteButton; private ImageButton mDeleteButton;
private RadioButton mIsMainUserId; private RadioButton mIsMainUserId;
private EditText mName; private EditText mName;
private EditText mEmail; private EditText mEmail;
private EditText mComment; private EditText mComment;
private static final Pattern EMAIL_PATTERN = private static final Pattern EMAIL_PATTERN =
Pattern.compile("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+[.]([a-zA-Z])+([a-zA-Z])+", Pattern.compile("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+[.]([a-zA-Z])+([a-zA-Z])+",
Pattern.CASE_INSENSITIVE); Pattern.CASE_INSENSITIVE);
public static class NoNameException extends Exception { public static class NoNameException extends Exception {
static final long serialVersionUID = 0xf812773343L; static final long serialVersionUID = 0xf812773343L;
public NoNameException(String message) { public NoNameException(String message) {
super(message); super(message);
} }
} }
public static class NoEmailException extends Exception { public static class NoEmailException extends Exception {
static final long serialVersionUID = 0xf812773344L; static final long serialVersionUID = 0xf812773344L;
public NoEmailException(String message) { public NoEmailException(String message) {
super(message); super(message);
} }
} }
public static class InvalidEmailException extends Exception { public static class InvalidEmailException extends Exception {
static final long serialVersionUID = 0xf812773345L; static final long serialVersionUID = 0xf812773345L;
public InvalidEmailException(String message) { public InvalidEmailException(String message) {
super(message); super(message);
} }
} }
public UserIdEditor(Context context) { public UserIdEditor(Context context) {
super(context); super(context);
} }
public UserIdEditor(Context context, AttributeSet attrs) { public UserIdEditor(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
setDrawingCacheEnabled(true); setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true); setAlwaysDrawnWithCacheEnabled(true);
mDeleteButton = (ImageButton) findViewById(R.id.delete); mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this); mDeleteButton.setOnClickListener(this);
mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId); mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId);
mIsMainUserId.setOnClickListener(this); mIsMainUserId.setOnClickListener(this);
mName = (EditText) findViewById(R.id.name); mName = (EditText) findViewById(R.id.name);
mEmail = (EditText) findViewById(R.id.email); mEmail = (EditText) findViewById(R.id.email);
mComment = (EditText) findViewById(R.id.comment); mComment = (EditText) findViewById(R.id.comment);
super.onFinishInflate(); super.onFinishInflate();
} }
public void setValue(String userId) { public void setValue(String userId) {
mName.setText(""); mName.setText("");
mComment.setText(""); mComment.setText("");
mEmail.setText(""); mEmail.setText("");
Pattern withComment = Pattern.compile("^(.*) [(](.*)[)] <(.*)>$"); Pattern withComment = Pattern.compile("^(.*) [(](.*)[)] <(.*)>$");
Matcher matcher = withComment.matcher(userId); Matcher matcher = withComment.matcher(userId);
if (matcher.matches()) { if (matcher.matches()) {
mName.setText(matcher.group(1)); mName.setText(matcher.group(1));
mComment.setText(matcher.group(2)); mComment.setText(matcher.group(2));
mEmail.setText(matcher.group(3)); mEmail.setText(matcher.group(3));
return; return;
} }
Pattern withoutComment = Pattern.compile("^(.*) <(.*)>$"); Pattern withoutComment = Pattern.compile("^(.*) <(.*)>$");
matcher = withoutComment.matcher(userId); matcher = withoutComment.matcher(userId);
if (matcher.matches()) { if (matcher.matches()) {
mName.setText(matcher.group(1)); mName.setText(matcher.group(1));
mEmail.setText(matcher.group(2)); mEmail.setText(matcher.group(2));
return; return;
} }
} }
public String getValue() throws NoNameException, NoEmailException, InvalidEmailException { public String getValue() throws NoNameException, NoEmailException, InvalidEmailException {
String name = ("" + mName.getText()).trim(); String name = ("" + mName.getText()).trim();
String email = ("" + mEmail.getText()).trim(); String email = ("" + mEmail.getText()).trim();
String comment = ("" + mComment.getText()).trim(); String comment = ("" + mComment.getText()).trim();
if (email.length() > 0) { if (email.length() > 0) {
Matcher emailMatcher = EMAIL_PATTERN.matcher(email); Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
if (!emailMatcher.matches()) { if (!emailMatcher.matches()) {
throw new InvalidEmailException( throw new InvalidEmailException(
getContext().getString(R.string.error_invalidEmail, email)); getContext().getString(R.string.error_invalidEmail, email));
} }
} }
String userId = name; String userId = name;
if (comment.length() > 0) { if (comment.length() > 0) {
userId += " (" + comment + ")"; userId += " (" + comment + ")";
} }
if (email.length() > 0) { if (email.length() > 0) {
userId += " <" + email + ">"; userId += " <" + email + ">";
} }
if (userId.equals("")) { if (userId.equals("")) {
// ok, empty one... // ok, empty one...
return userId; return userId;
} }
// otherwise make sure that name and email exist // otherwise make sure that name and email exist
if (name.equals("")) { if (name.equals("")) {
throw new NoNameException("need a name"); throw new NoNameException("need a name");
} }
if (email.equals("")) { if (email.equals("")) {
throw new NoEmailException("need an email"); throw new NoEmailException("need an email");
} }
return userId; return userId;
} }
@Override @Override
public void onClick(View v) { public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent(); final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) { if (v == mDeleteButton) {
boolean wasMainUserId = mIsMainUserId.isChecked(); boolean wasMainUserId = mIsMainUserId.isChecked();
parent.removeView(this); parent.removeView(this);
if (mEditorListener != null) { if (mEditorListener != null) {
mEditorListener.onDeleted(this); mEditorListener.onDeleted(this);
} }
if (wasMainUserId && parent.getChildCount() > 0) { if (wasMainUserId && parent.getChildCount() > 0) {
UserIdEditor editor = (UserIdEditor) parent.getChildAt(0); UserIdEditor editor = (UserIdEditor) parent.getChildAt(0);
editor.setIsMainUserId(true); editor.setIsMainUserId(true);
} }
} else if (v == mIsMainUserId) { } else if (v == mIsMainUserId) {
for (int i = 0; i < parent.getChildCount(); ++i) { for (int i = 0; i < parent.getChildCount(); ++i) {
UserIdEditor editor = (UserIdEditor) parent.getChildAt(i); UserIdEditor editor = (UserIdEditor) parent.getChildAt(i);
if (editor == this) { if (editor == this) {
editor.setIsMainUserId(true); editor.setIsMainUserId(true);
} else { } else {
editor.setIsMainUserId(false); editor.setIsMainUserId(false);
} }
} }
} }
} }
public void setIsMainUserId(boolean value) { public void setIsMainUserId(boolean value) {
mIsMainUserId.setChecked(value); mIsMainUserId.setChecked(value);
} }
public boolean isMainUserId() { public boolean isMainUserId() {
return mIsMainUserId.isChecked(); return mIsMainUserId.isChecked();
} }
@Override @Override
public void setEditorListener(EditorListener listener) { public void setEditorListener(EditorListener listener) {
mEditorListener = listener; mEditorListener = listener;
} }
} }

View File

@@ -1,44 +1,44 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.utils; package org.thialfihar.android.apg.utils;
public class Choice { public class Choice {
private String mName; private String mName;
private int mId; private int mId;
public Choice() { public Choice() {
mId = -1; mId = -1;
mName = ""; mName = "";
} }
public Choice(int id, String name) { public Choice(int id, String name) {
mId = id; mId = id;
mName = name; mName = name;
} }
public int getId() { public int getId() {
return mId; return mId;
} }
public String getName() { public String getName() {
return mName; return mName;
} }
public String toString() { public String toString() {
return mName; return mName;
} }
} }

View File

@@ -1,31 +1,31 @@
/* /*
* 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.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thialfihar.android.apg.utils; package org.thialfihar.android.apg.utils;
import java.util.Iterator; import java.util.Iterator;
public class IterableIterator<T> implements Iterable<T> { public class IterableIterator<T> implements Iterable<T> {
private Iterator<T> mIter; private Iterator<T> mIter;
public IterableIterator(Iterator<T> iter) { public IterableIterator(Iterator<T> iter) {
mIter = iter; mIter = iter;
} }
public Iterator<T> iterator() { public Iterator<T> iterator() {
return mIter; return mIter;
} }
} }