Permalink
Browse files

address book workflow is coming along

  • Loading branch information...
1 parent 90f0732 commit 632aba254c29d4c035fd146ced6ceb397c65a9f9 LvH committed Jul 25, 2012
Showing with 1,492 additions and 153 deletions.
  1. +1 −0 AndroidManifest.xml
  2. BIN assets/icudt46l.zip
  3. +187 −0 assets/installedKeys/harlo_holmes.asc
  4. +1 −1 assets/wizard/choose_encryption
  5. +0 −1 assets/wizard/encrypt_routine.wizard
  6. +1 −1 assets/wizard/generating_device_signature
  7. +1 −1 assets/wizard/order.wizard
  8. +1 −1 assets/wizard/take_a_picture
  9. +2 −0 assets/wizard/what_should_we_call_you
  10. +7 −5 res/layout/addressbookchooseractivity.xml
  11. +12 −0 res/layout/choosablealert_listadapter.xml
  12. +31 −0 res/layout/choosablealert_listview.xml
  13. +22 −0 res/layout/selection_display.xml
  14. +6 −0 res/values/arrays.xml
  15. +12 −2 res/values/strings.xml
  16. +2 −1 res/values/styles.xml
  17. +117 −5 src/org/witness/informacam/app/AddressBookActivity.java
  18. +209 −10 src/org/witness/informacam/app/AddressBookChooserActivity.java
  19. +2 −3 src/org/witness/informacam/app/MainRouter.java
  20. +1 −0 src/org/witness/informacam/app/MediaManagerActivity.java
  21. +1 −0 src/org/witness/informacam/app/MessageCenterActivity.java
  22. +121 −17 src/org/witness/informacam/app/WizardActivity.java
  23. +82 −0 src/org/witness/informacam/app/adapters/AddressBookAdapter.java
  24. +97 −0 src/org/witness/informacam/app/mods/InformaChoosableAlert.java
  25. +42 −0 src/org/witness/informacam/app/mods/SelectionDisplay.java
  26. +3 −5 src/org/witness/informacam/app/mods/Selections.java
  27. +299 −0 src/org/witness/informacam/crypto/KeyUtility.java
  28. +10 −3 src/org/witness/informacam/storage/DatabaseHelper.java
  29. +43 −18 src/org/witness/informacam/transport/HttpUtility.java
  30. +126 −76 src/org/witness/informacam/utils/AddressBookUtil.java
  31. +42 −3 src/org/witness/informacam/utils/Constants.java
  32. +11 −0 src/org/witness/informacam/utils/IOUtility.java
View
1 AndroidManifest.xml
@@ -39,6 +39,7 @@
android:theme="@style/Theme.CustomDialog"
android:configChanges="orientation|keyboardHidden" />
<activity android:name=".app.AddressBookChooserActivity"
+ android:configChanges="orientation|keyboardHidden"
android:theme="@style/Theme.CustomDialog" />
View
BIN assets/icudt46l.zip
Binary file not shown.
View
187 assets/installedKeys/harlo_holmes.asc
@@ -0,0 +1,187 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.1.3
+
+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
+SYKxz3W14OjsibgWd97Ru0menUY=
+=HuPZ
+-----END PGP PUBLIC KEY BLOCK-----
View
2 assets/wizard/choose_encryption
@@ -1,3 +1,3 @@
-InformaCam can give you the option of signing and encrypting your metadata to Trusted Destinations. Would you like to enable this feature?
+InformaCam can give you the option of signing and encrypting your metadata to Trusted Contacts in your Address Book. Would you like to enable this feature?
If you choose "no," you can take advantage of this feature at any time in the app's preferences.
{$ value=enable_encryption; type=select_one; values=#getEncryptionValues; callback=setEncryptionValues;}
View
1 assets/wizard/encrypt_routine.wizard
@@ -1 +0,0 @@
-register_the_app,add_trusted_destinations,all_done,
View
2 assets/wizard/generating_device_signature
@@ -1,3 +1,3 @@
Please wait while we generate your device's signature.
This may take up to 1 minute to complete...
-{$ type=spinner; callback=registerDeviceKeys;}
+{$ type=spinner; callback=registerDeviceKey;}
View
2 assets/wizard/order.wizard
@@ -1 +1 @@
-introduction,setup_database,login_options,take_a_picture,generating_device_signature,choose_encryption,original_image_options,all_done,
+introduction,what_should_we_call_you,setup_database,login_options,take_a_picture,generating_device_signature,choose_encryption,original_image_options,all_done,
View
2 assets/wizard/take_a_picture
@@ -1,3 +1,3 @@
Next, we'll need a photo taken by your camera in order to link this device to your identity.
We suggest taking a "boring" picture: a white wall will do just fine.
-{$ type=button; text=Take a Photo; callback=getDeviceId; mandatory=true;}
+{$ type=button; text=Take a Photo; callback=initDeviceKey; mandatory=true;}
View
2 assets/wizard/what_should_we_call_you
@@ -0,0 +1,2 @@
+Choose a name to identify yourself. It does NOT have to be your real name.
+{$ type=input; callback=setUserAlias; mandatory=false;}
View
12 res/layout/addressbookchooseractivity.xml
@@ -26,7 +26,7 @@
<TextView style="@style/P"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/address_book_directions" />
+ android:id="@+id/choose_instructions" />
<LinearLayout
android:layout_marginTop="10dip"
android:orientation="horizontal"
@@ -39,7 +39,8 @@
android:layout_weight="0.8"
android:id="@+id/input_contact_text"
android:hint="@string/address_book_enter_email_address" />
- <Button style="@style/Button_standard"
+ <org.witness.informacam.app.mods.InformaButton style="@style/Button_standard"
+ android:id="@+id/input_contact"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.2"
@@ -51,13 +52,13 @@
android:layout_height="wrap_content"
android:weightSum="1.0"
android:layout_marginTop="10dip">
- <Button style="@style/Button_standard"
+ <org.witness.informacam.app.mods.InformaButton style="@style/Button_standard"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="@string/address_book_pick_from_contacts"
android:id="@+id/pick_contact" />
- <Button style="@style/Button_standard"
+ <org.witness.informacam.app.mods.InformaButton style="@style/Button_standard"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.5"
@@ -70,11 +71,12 @@
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:id="@+id/contact_info" />
- <Button style="@style/Button_standard"
+ <org.witness.informacam.app.mods.InformaButton style="@style/Button_standard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/done"
android:layout_marginTop="10dip"
+ android:visibility="gone"
android:id="@+id/address_book_done" />
</LinearLayout>
</LinearLayout>
View
12 res/layout/choosablealert_listadapter.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+ <TextView android:id="@+id/choice_text"
+ android:layout_width="match_parent"
+ android:layout_height="40dip"
+ style="@style/P" />
+
+
+</LinearLayout>
View
31 res/layout/choosablealert_listview.xml
@@ -0,0 +1,31 @@
+<LinearLayout style="@style/OverlayActivity"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:weightSum="1.0" >
+ <LinearLayout style="@style/H1Holder"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="0.15">
+ <org.witness.informacam.app.mods.InformaHeaderTextView style="@style/H1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/choice_title" />
+ </LinearLayout>
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="0.25"
+ android:paddingTop="10dip"
+ android:paddingBottom="10dip"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip" >
+ <ListView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/choice_list"
+ android:padding="0dip" />
+ </LinearLayout>
+</LinearLayout>
View
22 res/layout/selection_display.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ style="@style/OverlayActivity" >
+
+ <ListView
+ android:id="@+id/selection_display"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_above="@+id/selection_commit" />
+
+ <Button style="@style/Button_standard"
+ android:id="@+id/selection_commit"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:text="@string/ok"
+ android:paddingBottom="10dip" />
+
+</RelativeLayout>
View
6 res/values/arrays.xml
@@ -54,4 +54,10 @@
<item>Rename</item>
<item>Get Info</item>
</string-array>
+
+ <string-array name="address_book_actions">
+ <item>View Details\u2026</item>
+ <item>Refresh Key</item>
+ <item>Delete Contact</item>
+ </string-array>
</resources>
View
14 res/values/strings.xml
@@ -32,13 +32,23 @@
<!-- ERRORS -->
<string name="error_media_mounted">Please insert an SD card to save media!</string>
+ <string name="error_no_key_found_for_email">Sorry! No public key found for </string>
+ <string name="error_cannot_delete_contact">This contact cannot be deleted.</string>
<!-- ADDRESS BOOK AND CHOOSER -->
<string name="address_book_new_contact">Add new contact\u2026</string>
<string name="address_book_directions">You can add a new contact by either typing in the email address, picking from your contact list, or by importing a public key (.asc) from storage.</string>
- <string name="address_book_pick_from_contacts">Pick from contacts</string>
- <string name="address_book_enter_email_address">Enter email address</string>
+ <string name="address_book_pick_from_contacts">Pick contact</string>
+ <string name="address_book_enter_email_address">email@example.com</string>
<string name="address_book_import_key">Import Key</string>
+ <string name="address_book_multiple_email">Multiple email addresses were found for this contact. Which one would you like to use?</string>
+ <string name="address_book_querying_keyserver_wait">Querying keyservers\u2026</string>
+ <string name="address_book_keyserver_result">Would you like to add the following key to your Address Book?\n\nPLEASE CHECK THE FINGERPRINT BEFORE ADDING!</string>
+ <string name="address_book_email">Email:</string>
+ <string name="address_book_fingerprint">Fingerprint:</string>
+ <string name="address_book_creation_date">Created on:</string>
+ <string name="address_book_expiry_date">Expires on:</string>
+
<!-- LOG IN ACTIVITY -->
<string name="login">Log In</string>
View
3 res/values/styles.xml
@@ -90,6 +90,7 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">bottom</item>
<item name="android:padding">4dip</item>
+ <item name="android:textSize">18dip</item>
</style>
<style name="ListView_augmented_text">
@@ -169,6 +170,6 @@
<style name="EditText_standard">
<item name="android:background">@drawable/edit_text_background</item>
<item name="android:textColor">#ffffffff</item>
- <item name="android:textColorHint">#ccffffff</item>
+ <item name="android:textColorHint">#aaffffff</item>
</style>
</resources>
View
122 src/org/witness/informacam/app/AddressBookActivity.java
@@ -1,30 +1,61 @@
package org.witness.informacam.app;
+import java.util.ArrayList;
+
+import net.sqlcipher.database.SQLiteDatabase;
+
+import org.json.JSONException;
import org.witness.informacam.R;
import org.witness.informacam.app.MainRouter.OnRoutedListener;
+import org.witness.informacam.app.adapters.AddressBookAdapter;
+import org.witness.informacam.app.adapters.AddressBookAdapter.OnAddressFocusedListener;
+import org.witness.informacam.app.mods.InformaChoosableAlert;
+import org.witness.informacam.app.mods.InformaChoosableAlert.OnChoosableChosenListener;
+import org.witness.informacam.storage.DatabaseHelper;
+import org.witness.informacam.utils.AddressBookUtil;
+import org.witness.informacam.utils.AddressBookUtil.AddressBookDisplay;
+import org.witness.informacam.utils.Constants.AddressBook;
import org.witness.informacam.utils.Constants.App;
+import org.witness.informacam.utils.Constants.Mods.Selections;
+import org.witness.informacam.utils.Constants.Settings;
+import org.witness.informacam.utils.Constants.TrustedDestination;
+import org.witness.informacam.utils.Constants.Storage.Tables;
import android.app.Activity;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.provider.BaseColumns;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
+import android.widget.ListView;
+import android.widget.Toast;
-public class AddressBookActivity extends Activity implements OnClickListener, OnRoutedListener {
+public class AddressBookActivity extends Activity implements OnClickListener, OnRoutedListener, OnAddressFocusedListener, OnChoosableChosenListener {
Handler h;
ImageButton navigation;
Button new_contact;
+ ListView address_list;
+
+ SQLiteDatabase db;
+ DatabaseHelper dh;
+
+ SharedPreferences sp;
+
+ ArrayList<AddressBookDisplay> addresses;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initLayout();
-
MainRouter.show(this);
}
@@ -36,10 +67,52 @@ private void initLayout() {
new_contact = (Button) findViewById(R.id.new_contact_button);
new_contact.setOnClickListener(this);
+
+ address_list = (ListView) findViewById(R.id.address_book_list);
}
private void getAddresses() {
-
+ dh.setTable(db, Tables.Keys.TRUSTED_DESTINATIONS);
+ Cursor a = dh.getValue(db, AddressBook.Projections.LIST_DISPLAY, null, null);
+ Log.d(App.LOG, "a is " + a.getCount());
+ if(a != null && a.getCount() > 0) {
+ addresses = new ArrayList<AddressBookDisplay>();
+ a.moveToFirst();
+ while(!a.isAfterLast()) {
+ AddressBookDisplay abd = new AddressBookDisplay(
+ AddressBookActivity.this, 0L,
+ a.getString(a.getColumnIndex(TrustedDestination.Keys.DISPLAY_NAME)),
+ a.getString(a.getColumnIndex(TrustedDestination.Keys.EMAIL)),
+ a.getBlob(a.getColumnIndex(TrustedDestination.Keys.CONTACT_PHOTO)),
+ Boolean.parseBoolean(a.getString(a.getColumnIndex(TrustedDestination.Keys.IS_DELETABLE)))
+ );
+
+ try {
+ Log.d(App.LOG, abd.toString());
+ abd.remove(AddressBook.Keys.CONTACT_ID);
+ abd.put(TrustedDestination.Keys.KEYRING_ID, a.getLong(a.getColumnIndex(TrustedDestination.Keys.KEYRING_ID)));
+ abd.put(BaseColumns._ID, a.getLong(a.getColumnIndex(BaseColumns._ID)));
+ } catch(JSONException e) {}
+
+ addresses.add(abd);
+ a.moveToNext();
+ }
+
+ a.close();
+ address_list.setAdapter(new AddressBookAdapter(AddressBookActivity.this, addresses));
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if(db != null) {
+ db.close();
+ dh.close();
+
+ db = null;
+ dh = null;
+ }
}
@Override
@@ -56,13 +129,19 @@ else if(v == new_contact) {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == Activity.RESULT_OK && requestCode == App.AddressBook.FROM_CONTACT_CHOOSER) {
- // TODO: handle the addition
+ Log.d(App.LOG, "coming back from contacts");
+ getAddresses();
}
-
}
@Override
public void onRouted() {
+ h = new Handler();
+ sp = PreferenceManager.getDefaultSharedPreferences(this);
+
+ dh = new DatabaseHelper(this);
+ db = dh.getWritableDatabase(sp.getString(Settings.Keys.CURRENT_LOGIN, ""));
+
h.post(new Runnable() {
@Override
public void run() {
@@ -71,5 +150,38 @@ public void run() {
});
}
+
+ @Override
+ public void onAddressFocusedListener(int which) {
+ Log.d(App.LOG, "i pressed on " + which);
+ InformaChoosableAlert alert = new InformaChoosableAlert(AddressBookActivity.this, getResources().getStringArray(R.array.address_book_actions), addresses.get(which));
+ try {
+ alert.setTitle(addresses.get(which).getString(AddressBook.Keys.CONTACT_NAME));
+ } catch (JSONException e) {}
+ alert.show();
+ }
+
+ @Override
+ public void onChoice(int which, Object obj) {
+ AddressBookDisplay abd = (AddressBookDisplay) obj;
+ switch(which) {
+ case AddressBook.Actions.DELETE_CONTACT:
+ try {
+ if(abd.getBoolean(TrustedDestination.Keys.IS_DELETABLE)) {
+ AddressBookUtil.deleteContact(abd.getLong(BaseColumns._ID), abd.getString(AddressBook.Keys.CONTACT_EMAIL));
+ getAddresses();
+ } else {
+ Toast.makeText(this, getString(R.string.error_cannot_delete_contact), Toast.LENGTH_LONG).show();
+ }
+ } catch (JSONException e) {}
+ break;
+ case AddressBook.Actions.REFRESH_KEY:
+ break;
+ case AddressBook.Actions.VIEW_DETAILS:
+ break;
+
+ }
+
+ }
}
View
219 src/org/witness/informacam/app/AddressBookChooserActivity.java
@@ -1,19 +1,54 @@
package org.witness.informacam.app;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.json.JSONException;
import org.witness.informacam.R;
+import org.witness.informacam.app.mods.InformaButton;
import org.witness.informacam.app.mods.InformaEditText;
+import org.witness.informacam.app.mods.SelectionDisplay;
+import org.witness.informacam.app.mods.Selections;
+import org.witness.informacam.crypto.KeyUtility;
+import org.witness.informacam.crypto.KeyUtility.KeyFoundListener;
+import org.witness.informacam.crypto.KeyUtility.KeyServerResponse;
+import org.witness.informacam.utils.AddressBookUtil;
+import org.witness.informacam.utils.AddressBookUtil.AddressBookDisplay;
+import org.witness.informacam.utils.AddressBookUtil.AddressBookListener;
+import org.witness.informacam.utils.Constants.AddressBook;
+import org.witness.informacam.utils.Constants.App;
+import org.witness.informacam.utils.Constants.Crypto.PGP;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
+import android.os.Handler;
+import android.provider.ContactsContract.Contacts;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
-public class AddressBookChooserActivity extends Activity implements OnClickListener {
- Button input_contact, pick_contact, import_contact, done;
+public class AddressBookChooserActivity extends Activity implements OnClickListener, TextWatcher, AddressBookListener, KeyFoundListener {
+ InformaButton input_contact, pick_contact, import_contact, done;
InformaEditText input_contact_text;
LinearLayout contact_info;
+ TextView choose_instructions;
+
+ String queryEmail;
+ long queryId;
+
+ KeyServerResponse ksr;
+ AddressBookDisplay abd;
+
+ Handler h;
+
+ int stage = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -24,27 +59,191 @@ public void onCreate(Bundle savedInstanceState) {
private void initLayout() {
setContentView(R.layout.addressbookchooseractivity);
- input_contact = (Button) findViewById(R.id.import_contact);
- pick_contact = (Button) findViewById(R.id.pick_contact);
- import_contact = (Button) findViewById(R.id.import_contact);
- done = (Button) findViewById(R.id.address_book_done);
+ choose_instructions = (TextView) findViewById(R.id.choose_instructions);
+
+ input_contact = (InformaButton) findViewById(R.id.input_contact);
+ input_contact.setOnClickListener(this);
+ disableAction(input_contact);
+
+ pick_contact = (InformaButton) findViewById(R.id.pick_contact);
+ pick_contact.setOnClickListener(this);
+
+ import_contact = (InformaButton) findViewById(R.id.import_contact);
+ import_contact.setOnClickListener(this);
+
+ done = (InformaButton) findViewById(R.id.address_book_done);
+ done.setOnClickListener(this);
+ disableAction(done);
input_contact_text = (InformaEditText) findViewById(R.id.input_contact_text);
+ input_contact_text.addTextChangedListener(this);
+
contact_info = (LinearLayout) findViewById(R.id.contact_info);
+ reloadViews(stage);
+ }
+
+ private void reloadViews(int stage) {
+ contact_info.removeAllViews();
+
+ switch(stage) {
+ case 0:
+ choose_instructions.setText(R.string.address_book_directions);
+ input_contact_text.setVisibility(View.VISIBLE);
+ input_contact.setVisibility(View.VISIBLE);
+ import_contact.setVisibility(View.VISIBLE);
+ pick_contact.setVisibility(View.VISIBLE);
+ done.setVisibility(View.GONE);
+ break;
+ case 1:
+ choose_instructions.setText(R.string.address_book_multiple_email);
+ input_contact_text.setVisibility(View.GONE);
+ input_contact.setVisibility(View.GONE);
+ import_contact.setVisibility(View.GONE);
+ pick_contact.setVisibility(View.GONE);
+ done.setVisibility(View.GONE);
+ break;
+ case 2:
+ choose_instructions.setText(R.string.address_book_querying_keyserver_wait);
+ input_contact_text.setVisibility(View.GONE);
+ input_contact.setVisibility(View.GONE);
+ import_contact.setVisibility(View.GONE);
+ pick_contact.setVisibility(View.GONE);
+ done.setVisibility(View.GONE);
+ break;
+ case 3:
+ choose_instructions.setText(R.string.address_book_keyserver_result);
+ input_contact_text.setVisibility(View.GONE);
+ input_contact.setVisibility(View.GONE);
+ import_contact.setVisibility(View.GONE);
+ pick_contact.setVisibility(View.GONE);
+ done.setVisibility(View.VISIBLE);
+ enableAction(done);
+ }
+ }
+
+ private void enableAction(View v) {
+ ((InformaButton) v).getBackground().setAlpha(255);
+ ((InformaButton) v).setClickable(true);
+ }
+
+ private void disableAction(View v) {
+ ((InformaButton) v).getBackground().setAlpha(100);
+ ((InformaButton) v).setClickable(false);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if(resultCode == Activity.RESULT_OK) {
+ switch(requestCode) {
+ case App.AddressBook.FROM_CONTACT_CHOOSER:
+ queryId = Long.parseLong(data.getData().getLastPathSegment());
+ AddressBookUtil.getEmailAddressFromLookup(AddressBookChooserActivity.this, queryId);
+ break;
+ case App.AddressBook.FROM_ASC_IMPORT:
+ // TODO: this.
+ break;
+ }
+ }
}
@Override
public void onClick(View v) {
if(v == input_contact) {
-
+ queryEmail = input_contact_text.getText().toString();
+ AddressBookUtil.getLookupFromEmailAddress(AddressBookChooserActivity.this, queryEmail);
} else if(v == pick_contact) {
-
+ Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
+ startActivityForResult(intent, App.AddressBook.FROM_CONTACT_CHOOSER);
} else if(v == import_contact) {
-
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("*/*");
+ startActivityForResult(intent, App.AddressBook.FROM_ASC_IMPORT);
} else if(v == done) {
-
+ KeyUtility.installNewKey(AddressBookChooserActivity.this, ksr, abd);
+ finish();
+ }
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable e) {
+ if(e.length() >= 5 && e.toString().contains("@")) {
+ enableAction(input_contact);
+ } else
+ disableAction(input_contact);
+
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void receiveNewAddresses(AddressBookDisplay abd) {
+ this.abd = abd;
+ try {
+ stage = 2;
+ reloadViews(stage);
+ KeyUtility.queryKeyserverByEmail(AddressBookChooserActivity.this, abd.getString(AddressBook.Keys.CONTACT_NAME), abd.getString(AddressBook.Keys.CONTACT_EMAIL));
+ } catch (JSONException e) {
+ e.printStackTrace();
}
}
+ @Override
+ public void onNoResultFound(String emailAddress) {
+ Toast.makeText(this, getString(R.string.error_no_key_found_for_email) + " " + emailAddress, Toast.LENGTH_LONG).show();
+
+ }
+
+ @Override
+ public void onMultipleChoicesFound(ArrayList<Selections> choices) {
+ reloadViews(++stage);
+ final SelectionDisplay sd = new SelectionDisplay(this, choices);
+ contact_info.addView(sd);
+
+ sd.ok.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ for(int i=0; i<sd.selectionsList.getAdapter().getCount(); i++) {
+ Selections s = (Selections) sd.selectionsList.getAdapter().getItem(i);
+ if(s.getSelected())
+ AddressBookUtil.getEmailAddressFromLookup(AddressBookChooserActivity.this, queryId, i);
+ reloadViews(++stage);
+ }
+
+ }
+ });
+ }
+
+ @Override
+ public void onBackPressed() {
+ if(stage == 0)
+ finish();
+ else {
+ stage = 0;
+ reloadViews(stage);
+ }
+ }
+
+ @Override
+ public void onKeyFound(KeyServerResponse ksr) {
+ this.ksr = ksr;
+ stage = 3;
+ reloadViews(stage);
+ TextView confirmation = new TextView(this);
+ try {
+ confirmation.setText(
+ ksr.getString(PGP.Keys.PGP_DISPLAY_NAME) + "\n" +
+ getString(R.string.address_book_email) + " " + ksr.getString(PGP.Keys.PGP_EMAIL_ADDRESS) + "\n" +
+ getString(R.string.address_book_fingerprint) + "\n" + ksr.getString(PGP.Keys.PGP_FINGERPRINT)
+ );
+ } catch(JSONException e) {}
+
+ contact_info.addView(confirmation);
+ }
}
View
5 src/org/witness/informacam/app/MainRouter.java
@@ -19,9 +19,8 @@ static boolean show(final Activity activity) {
if(!preferences.getBoolean(Settings.Keys.SETTINGS_VIEWED, false)) {
Log.d(App.LOG, "virgin user, EULA accepted. launching wizard");
- //Intent intent = new Intent(activity, WizardActivity.class);
- //activity.startActivity(intent);
-
+ Intent intent = new Intent(activity, WizardActivity.class);
+ activity.startActivity(intent);
return false;
} else if(preferences.getString(Settings.Keys.CURRENT_LOGIN, "").compareTo(Settings.Login.PW_EXPIRY) == 0) {
Log.d(App.LOG, "user\'s password expired. must log in again.");
View
1 src/org/witness/informacam/app/MediaManagerActivity.java
@@ -44,6 +44,7 @@ public void onClick(View v) {
@Override
public void onRouted() {
+ h = new Handler();
h.post(new Runnable() {
@Override
public void run() {
View
1 src/org/witness/informacam/app/MessageCenterActivity.java
@@ -44,6 +44,7 @@ public void onClick(View v) {
@Override
public void onRouted() {
+ h = new Handler();
h.post(new Runnable() {
@Override
public void run() {
View
138 src/org/witness/informacam/app/WizardActivity.java
@@ -5,8 +5,14 @@
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
+import net.sqlcipher.database.SQLiteDatabase;
+
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPPublicKey;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -17,16 +23,28 @@
import org.witness.informacam.app.mods.InformaSpinner;
import org.witness.informacam.app.mods.InformaTextView;
import org.witness.informacam.app.mods.Selections;
+import org.witness.informacam.crypto.KeyUtility;
+import org.witness.informacam.crypto.KeyUtility.KeyServerResponse;
+import org.witness.informacam.storage.DatabaseHelper;
import org.witness.informacam.utils.AddressBookUtil;
+import org.witness.informacam.utils.AddressBookUtil.AddressBookDisplay;
import org.witness.informacam.utils.AddressBookUtil.AddressBookListener;
import org.witness.informacam.utils.Constants.App;
+import org.witness.informacam.utils.Constants.Crypto;
+import org.witness.informacam.utils.Constants.Informa;
+import org.witness.informacam.utils.Constants.TrustedDestination;
import org.witness.informacam.utils.Constants.App.Wizard;
+import org.witness.informacam.utils.Constants.Crypto.PGP;
+import org.witness.informacam.utils.Constants.Settings.Device;
+import org.witness.informacam.utils.Constants.Storage.Tables;
import org.witness.informacam.utils.Constants.Settings;
import android.app.Activity;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.preference.PreferenceManager;
@@ -56,6 +74,9 @@
WizardForm wizardForm;
+ private DatabaseHelper dh;
+ private SQLiteDatabase db;
+
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sp = PreferenceManager.getDefaultSharedPreferences(this);
@@ -65,6 +86,8 @@ public void onCreate(Bundle savedInstanceState) {
wizardForm = new WizardForm(this);
+ SQLiteDatabase.loadLibs(this);
+
initLayout();
}
@@ -131,6 +154,11 @@ public void initFrame() throws JSONException {
}
@SuppressWarnings("unused")
+ private void setUserAlias(String alias) {
+ ed.putString(Informa.Keys.Device.DISPLAY_NAME, alias).commit();
+ }
+
+ @SuppressWarnings("unused")
private void saveDBPW(String pw) {
ed.putString(Settings.Keys.CURRENT_LOGIN, pw).commit();
}
@@ -143,15 +171,48 @@ private void setDBPWCache(ArrayList<Selections> cacheSelection) {
}
}
- private void setDeviceId(Bitmap bitmap) {
- // TODO
- passThrough();
+ private void storeDeviceKey(Bitmap baseImage) {
+ ByteBuffer b = ByteBuffer.allocate(baseImage.getRowBytes() * baseImage.getHeight());
+ baseImage.copyPixelsToBuffer(b);
+
+ byte[] imageBytes = new byte[b.capacity()];
+ try {
+ b.get(imageBytes, 0, imageBytes.length);
+ } catch(BufferUnderflowException e) {
+ Log.d(Crypto.LOG, "buffer underflow!" + e.toString());
+ }
+
+ ContentValues cv = new ContentValues();
+ cv.put(Device.Keys.BASE_IMAGE, imageBytes);
+ cv.put(Informa.Keys.Device.DISPLAY_NAME, sp.getString(Informa.Keys.Device.DISPLAY_NAME, ""));
+
+ dh = new DatabaseHelper(this);
+ db = dh.getWritableDatabase(sp.getString(Settings.Keys.CURRENT_LOGIN, ""));
+
+ dh.setTable(db, Tables.Keys.SETUP);
+
+ long insert = db.insert(dh.getTable(), null, cv);
+ db.close();
+ dh.close();
+
+ if(insert > 0)
+ passThrough();
}
@SuppressWarnings("unused")
- private void registerDeviceKeys() {
- // TODO
- passThrough();
+ private void registerDeviceKey() {
+ try {
+ if(KeyUtility.generateNewKeyFromImage(WizardActivity.this)) {
+ initInstalledKeys();
+ passThrough();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (PGPException e) {
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
}
@SuppressWarnings("unused")
@@ -161,11 +222,6 @@ private void setEncryptionValues(ArrayList<Selections> encryptionSelection) {
if(s.getSelected())
ed.putBoolean(Settings.Keys.USE_ENCRYPTION, Boolean.parseBoolean(encryptionValues[encryptionSelection.indexOf(s)])).commit();
}
-
- if(sp.getBoolean(Settings.Keys.USE_ENCRYPTION, false)) {
- Intent intent = new Intent(this, AddressBookChooserActivity.class);
- startActivityForResult(intent, Wizard.FROM_ADDRESSBOOK_CHOOSER);
- }
}
@SuppressWarnings("unused")
@@ -176,6 +232,35 @@ private void setDefaultImageHandling(ArrayList<Selections> imageHandlingSelectio
}
}
+ private void initInstalledKeys() throws IOException, PGPException, JSONException {
+
+ String[] allKeys = getAssets().list("installedKeys");
+ for(String keyFile : allKeys) {
+ BufferedReader br = new BufferedReader(new InputStreamReader(getAssets().open("installedKeys/" + keyFile)));
+
+ String line;
+ StringBuilder sb = new StringBuilder();
+
+ char[] buf = new char[1024];
+ int numRead = 0;
+
+ while((numRead = br.read(buf)) != -1) {
+ line = String.valueOf(buf, 0, numRead);
+ sb.append(line);
+ buf = new char[1024];
+ }
+
+ br.close();
+
+ PGPPublicKey key = KeyUtility.extractPublicKeyFromBytes(sb.toString().getBytes());
+ KeyServerResponse ksr = new KeyUtility.KeyServerResponse(key);
+ AddressBookDisplay abd = new AddressBookDisplay(WizardActivity.this, 0L, ksr.getString(PGP.Keys.PGP_DISPLAY_NAME), ksr.getString(PGP.Keys.PGP_EMAIL_ADDRESS), false);
+ KeyUtility.installNewKey(WizardActivity.this, ksr, abd);
+
+ Log.d(App.LOG, abd.toString());
+ }
+ }
+
@SuppressWarnings("unused")
private String[] getDefaultImageHandlingOptions() {
return getResources().getStringArray(R.array.default_image_handling);
@@ -192,7 +277,7 @@ private void setDefaultImageHandling(ArrayList<Selections> imageHandlingSelectio
}
@SuppressWarnings("unused")
- private void getDeviceId() {
+ private void initDeviceKey() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 60000L);
startActivityForResult(intent, App.Wizard.FROM_BASE_IMAGE_CAPTURE);
@@ -247,10 +332,8 @@ private void passThrough() {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == Activity.RESULT_OK) {
switch(requestCode) {
- case Wizard.FROM_ADDRESSBOOK_CHOOSER:
- break;
case Wizard.FROM_BASE_IMAGE_CAPTURE:
- setDeviceId((Bitmap) data.getExtras().get("data"));
+ storeDeviceKey((Bitmap) data.getExtras().get("data"));
break;
}
}
@@ -430,6 +513,7 @@ public void onLayoutChange(View v, int left,
}
});
+
views.add(edittext);
} else if(type.compareTo("password") == 0) {
InformaEditText edittext = new InformaEditText(_c);
@@ -466,14 +550,14 @@ public void onTextChanged(CharSequence s,
});
views.add(edittext);
- } else if(type.compareTo("select_one") == 0 || type.compareTo("select_multi") == 0) {
+ } else if(type.equals("select_one") || type.equals("select_multi")) {
ArrayList<Selections> selections = new ArrayList<Selections>();
ListView lv = new ListView(_c);
for(String option : findKey(s, "values").split(",")) {
Log.d(App.LOG, "this option: " + option);
- if(Character.toString(option.charAt(0)).compareTo("#") == 0) {
+ if(Character.toString(option.charAt(0)).equals("#")) {
// populate from callback
Callback populate = new Callback(option.substring(1), null);
@@ -495,6 +579,26 @@ public void onTextChanged(CharSequence s,
callbacks.add(new Callback(callback, new Object[] {selections}));
lv.setAdapter(new SelectionsAdapter(_c, selections, type));
views.add(lv);
+ } else if(type.equals("simple_list")) {
+ ArrayList<String> list = new ArrayList<String>();
+ ListView lv = new ListView(_c);
+
+ for(String option : findKey(s, "values").split(",")) {
+ Log.d(App.LOG, "this option: " + option);
+ if(Character.toString(option.charAt(0)).equals("#")) {
+ Callback populate = new Callback(option.substring(1), null);
+ try {
+ for(String res : (String[]) populate.doCallback())
+ list.add(res);
+ } catch (IllegalAccessException e) {
+ Log.d(App.LOG, "wizard error", e);
+ } catch (NoSuchMethodException e) {
+ Log.d(App.LOG, "wizard error", e);
+ } catch (InvocationTargetException e) {
+ Log.d(App.LOG, "wizard error", e);
+ }
+ }
+ }
}
} else {
View
82 src/org/witness/informacam/app/adapters/AddressBookAdapter.java
@@ -0,0 +1,82 @@
+package org.witness.informacam.app.adapters;
+
+import java.util.ArrayList;
+
+import org.json.JSONException;
+import org.witness.informacam.R;
+import org.witness.informacam.utils.Constants.AddressBook;
+import org.witness.informacam.utils.Constants.App;
+import org.witness.informacam.utils.IOUtility;
+import org.witness.informacam.utils.AddressBookUtil.AddressBookDisplay;
+import org.witness.informacam.utils.Constants.TrustedDestination;
+
+import android.app.Activity;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class AddressBookAdapter extends BaseAdapter {
+ ArrayList<AddressBookDisplay> addresses;
+ Activity a;
+
+ public interface OnAddressFocusedListener {
+ public void onAddressFocusedListener(int which);
+ }
+
+ public AddressBookAdapter(Activity a, ArrayList<AddressBookDisplay> addresses) {
+ this.addresses = addresses;
+ this.a = a;
+ }
+
+ @Override
+ public int getCount() {
+ return addresses.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return addresses.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ convertView = LayoutInflater.from(a.getApplicationContext()).inflate(R.layout.addressbook_listadapter, null);
+
+ try {
+ ImageButton contactThumb = (ImageButton) convertView.findViewById(R.id.contact_thumb);
+ contactThumb.setImageBitmap(IOUtility.getBitmapFromBytes(addresses.get(position).getString(TrustedDestination.Keys.CONTACT_PHOTO).getBytes(), true));
+
+ StringBuilder details = new StringBuilder();
+ details.append(addresses.get(position).getString(AddressBook.Keys.CONTACT_NAME) + "\n");
+ details.append(addresses.get(position).getString(AddressBook.Keys.CONTACT_EMAIL));
+
+ TextView contactDetails = (TextView) convertView.findViewById(R.id.contact_details);
+ contactDetails.setText(details.toString());
+ Log.d(App.LOG, details.toString());
+
+ LinearLayout contactDetailsHolder = (LinearLayout) convertView.findViewById(R.id.contact_details_holder);
+ contactDetailsHolder.setOnLongClickListener(new OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ ((OnAddressFocusedListener) a).onAddressFocusedListener(position);
+ return false;
+ }
+
+ });
+ } catch (JSONException e) {}
+
+ return convertView;
+ }
+}
View
97 src/org/witness/informacam/app/mods/InformaChoosableAlert.java
@@ -0,0 +1,97 @@
+package org.witness.informacam.app.mods;
+
+import org.witness.informacam.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+public class InformaChoosableAlert extends AlertDialog {
+ Context context;
+ LayoutInflater li;
+ String[] choices;
+ View inner;
+ ListView choiceList;
+ TextView choiceTitle;
+
+ Object obj;
+ InformaChoosableAlert ica;
+
+ public interface OnChoosableChosenListener {
+ public void onChoice(int which, Object obj);
+ }
+
+ public InformaChoosableAlert(Activity context, String[] choices, Object obj) {
+ super(context);
+ this.context = context;
+ this.choices = choices;
+ this.obj = obj;
+
+ li = LayoutInflater.from(context);
+ inner = li.inflate(R.layout.choosablealert_listview, null);
+ this.setView(inner);
+
+ choiceList = (ListView) inner.findViewById(R.id.choice_list);
+ choiceList.setAdapter(new ChoiceAdapter());
+
+ choiceTitle = (TextView) inner.findViewById(R.id.choice_title);
+ ica = this;
+ }
+
+
+ public InformaChoosableAlert(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+
+ choiceTitle.setText(title);
+ choiceTitle.setVisibility(View.VISIBLE);
+
+ }
+
+ public class ChoiceAdapter extends BaseAdapter {
+ @Override
+ public int getCount() {
+ return choices.length;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return choices[position];
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ convertView = li.inflate(R.layout.choosablealert_listadapter, null);
+ TextView choice = (TextView) convertView.findViewById(R.id.choice_text);
+ choice.setText(choices[position]);
+
+ convertView.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ ((OnChoosableChosenListener) context).onChoice(position, obj);
+ ica.dismiss();
+ }
+
+ });
+
+ return convertView;
+ }
+
+ }
+
+}
View
42 src/org/witness/informacam/app/mods/SelectionDisplay.java
@@ -0,0 +1,42 @@
+package org.witness.informacam.app.mods;
+
+import java.util.ArrayList;
+
+import org.witness.informacam.R;
+import org.witness.informacam.app.adapters.SelectionsAdapter;
+import org.witness.informacam.utils.Constants;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
+public class SelectionDisplay extends LinearLayout {
+ ArrayList<Selections> selections;
+ public ListView selectionsList;
+ public Button ok;
+
+ public SelectionDisplay(Context context) {
+ super(context);
+ }
+
+ public SelectionDisplay(Context context, ArrayList<Selections> selections) {
+ super(context);
+ this.selections = selections;
+
+ View inner = LayoutInflater.from(context).inflate(R.layout.selection_display, null);
+ selectionsList = (ListView) inner.findViewById(R.id.selection_display);
+ selectionsList.setAdapter(new SelectionsAdapter(context, selections, Constants.Mods.Selections.SELECT_ONE));
+
+ ok = (Button) inner.findViewById(R.id.selection_commit);
+
+ this.addView(inner);
+
+
+ }
+
+
+
+}
View
8 src/org/witness/informacam/app/mods/Selections.java
@@ -1,17 +1,15 @@
package org.witness.informacam.app.mods;
-import org.json.JSONObject;
-
public class Selections {
public String _optionValue;
boolean _selected;
- private JSONObject _extras;
+ private Object _extras;
public Selections(String optionValue, boolean selectDefault) {
this(optionValue, selectDefault, null);
}
- public Selections(String optionValue, boolean selectDefault, JSONObject extras) {
+ public Selections(String optionValue, boolean selectDefault, Object extras) {
_optionValue = optionValue;
_selected = selectDefault;
_extras = extras;
@@ -25,7 +23,7 @@ public void setSelected(boolean selected) {
_selected = selected;
}
- public JSONObject getExtras() {
+ public Object getExtras() {
return _extras;
}
}
View
299 src/org/witness/informacam/crypto/KeyUtility.java
@@ -1,5 +1,304 @@
package org.witness.informacam.crypto;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.concurrent.ExecutionException;
+
+import net.sqlcipher.database.SQLiteDatabase;
+
+import org.apache.http.client.ClientProtocolException;
+import org.bouncycastle.bcpg.CompressionAlgorithmTags;
+import org.bouncycastle.bcpg.HashAlgorithmTags;
+import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
+import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
+import org.bouncycastle.bcpg.sig.KeyFlags;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.bouncycastle.util.encoders.Hex;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.witness.informacam.storage.DatabaseHelper;
+import org.witness.informacam.transport.HttpUtility;
+import org.witness.informacam.utils.AddressBookUtil.AddressBookDisplay;
+import org.witness.informacam.utils.Constants.AddressBook;
+import org.witness.informacam.utils.Constants.Crypto;
+import org.witness.informacam.utils.Constants.Settings;
+import org.witness.informacam.utils.Constants.TrustedDestination;
+import org.witness.informacam.utils.Constants.Crypto.PGP;
+import org.witness.informacam.utils.Constants.Settings.Device;
+import org.witness.informacam.utils.Constants.Storage.Tables;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.preference.PreferenceManager;
+import android.provider.BaseColumns;
+import android.util.Base64;
+import android.util.Log;
+
public class KeyUtility {
+ public interface KeyFoundListener {
+ public void onKeyFound(KeyServerResponse keyServerResponse);
+ }
+
+ public final static class KeyServerResponse extends JSONObject {
+ public KeyServerResponse(PGPPublicKey key, String displayName, String email) {
+ if(email == null) {
+ Log.d(Crypto.LOG, "no display name or email");
+ Iterator<String> uIt = key.getUserIDs();
+ while(uIt.hasNext()) {
+ String[] id = uIt.next().split("<");
+ displayName = id[0].substring(0, id[0].indexOf(" ("));
+ email = id[1].substring(0, id[1].length() - 1);
+ }
+ }
+
+ try {
+ this.put(PGP.Keys.PGP_DISPLAY_NAME, displayName);
+ this.put(PGP.Keys.PGP_EMAIL_ADDRESS, email);
+ this.put(PGP.Keys.PGP_CREATION_DATE, key.getCreationTime().getTime());
+ this.put(PGP.Keys.PGP_EXPIRY_DATE, key.getCreationTime().getTime() + key.getValidSeconds());
+ this.put(PGP.Keys.PGP_FINGERPRINT, new String(Hex.encode(key.getFingerprint())));
+ this.put(PGP.Keys.PGP_KEY_ID, key.getKeyID());
+ this.put(Crypto.Keyring.Keys.PUBLIC_KEY, new String(key.getEncoded()));
+ } catch (JSONException e) {}
+ catch (IOException e) {}
+ }
+
+ public KeyServerResponse(PGPPublicKey key) {
+ this(key, null, null);
+ }
+ }
+
+ private static String parseKeyserverQuery(String rawdata) {
+ String keyblock = null;
+ String bodyContents = rawdata.substring(rawdata.indexOf("<body>"), rawdata.indexOf("</html>"));
+
+ if(bodyContents.contains(PGP.beginKeyBlock[0])) {
+ keyblock = bodyContents.substring(bodyContents.indexOf(PGP.beginKeyBlock[0]), bodyContents.indexOf(PGP.endKeyBlock[0]) + PGP.endKeyBlock[0].length());
+ }
+ return keyblock;
+ }
+
+ public static void queryKeyserverByEmail(Activity c, String displayName, String email) {
+ try {
+ String keyblock = parseKeyserverQuery(HttpUtility.executeHttpGet(PGP.keyserverUrl[0] + email));
+ if(keyblock != null) {
+ PGPPublicKey key = extractPublicKeyFromBytes(keyblock.getBytes());
+ KeyServerResponse keyServerResponse = new KeyServerResponse(key, displayName, email);
+ ((KeyFoundListener) c).onKeyFound(keyServerResponse);
+ }
+
+
+ } catch (ClientProtocolException e) {}
+ catch (URISyntaxException e) {}
+ catch (IOException e) {}
+ catch (InterruptedException e) {}
+ catch (ExecutionException e) {}
+ catch (PGPException e) {}
+ }
+
+ @SuppressWarnings("unchecked")
+ public static PGPPublicKey extractPublicKeyFromBytes(byte[] keyBlock) throws IOException, PGPException {
+ PGPPublicKeyRingCollection keyringCol = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(new ByteArrayInputStream(keyBlock)));
+ PGPPublicKey key = null;
+ Iterator<PGPPublicKeyRing> rIt = keyringCol.getKeyRings();
+ while(key == null && rIt.hasNext()) {
+ PGPPublicKeyRing keyring = (PGPPublicKeyRing) rIt.next();
+ Iterator<PGPPublicKey> kIt = keyring.getPublicKeys();
+ while(key == null && kIt.hasNext()) {
+ PGPPublicKey k = (PGPPublicKey) kIt.next();
+ if(k.isEncryptionKey())
+ key = k;
+ }
+ }
+ if(key == null)
+ throw new IllegalArgumentException("there isn't an encryption key here.");
+
+ return key;
+ }
+
+ public static boolean installNewKey(Activity c, KeyServerResponse ksr, AddressBookDisplay abd) {
+ ContentValues key = new ContentValues();
+ Iterator<String> kIt = ksr.keys();
+ while(kIt.hasNext()) {
+ String k = kIt.next();
+ try {
+ key.put(k, ksr.getString(k));
+ } catch(ClassCastException e) {
+ try {
+ key.put(k, ksr.getLong(k));
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ DatabaseHelper dh = new DatabaseHelper(c);
+ SQLiteDatabase db = dh.getWritableDatabase(PreferenceManager.getDefaultSharedPreferences(c).getString(Settings.Keys.CURRENT_LOGIN, ""));
+
+ dh.setTable(db, Tables.Keys.KEYRING);
+ db.insert(dh.getTable(), null, key);
+
+ if(abd != null) {
+ dh.setTable(db, Tables.Keys.TRUSTED_DESTINATIONS);
+ ContentValues td = new ContentValues();
+ try {
+ td.put(TrustedDestination.Keys.DISPLAY_NAME, key.getAsString(PGP.Keys.PGP_DISPLAY_NAME));
+ td.put(TrustedDestination.Keys.EMAIL, key.getAsString(PGP.Keys.PGP_EMAIL_ADDRESS));
+ td.put(TrustedDestination.Keys.KEYRING_ID, key.getAsLong(PGP.Keys.PGP_KEY_ID));
+ td.put(TrustedDestination.Keys.CONTACT_PHOTO, abd.getString(AddressBook.Keys.CONTACT_PHOTO));
+
+ Log.d(Crypto.LOG, td.toString());
+ db.insert(dh.getTable(), null, td);
+ } catch(JSONException e){}
+ }
+
+ db.close();
+ dh.close();
+ return true;
+ }
+
+ private static String generatePassword(byte[] baseImage) throws NoSuchAlgorithmException {
+ // initialize random bytes
+ byte[] randomBytes = new byte[baseImage.length];
+ SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
+ sr.nextBytes(randomBytes);
+
+ // xor by baseImage
+ byte[] product = new byte[baseImage.length];
+ for(int b = 0; b < baseImage.length; b++) {
+ product[b] = (byte) (baseImage[b] ^ randomBytes[b]);
+ }
+
+ // digest to SHA1 string, voila password.
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ return Base64.encodeToString(md.digest(product), Base64.DEFAULT);
+ }
+
+ @SuppressWarnings("deprecation")
+ public static boolean generateNewKeyFromImage(Activity c) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
+ DatabaseHelper dh = new DatabaseHelper(c);
+ SQLiteDatabase db = dh.getWritableDatabase(sp.getString(Settings.Keys.CURRENT_LOGIN, ""));
+
+ byte[] baseImage;
+
+ dh.setTable(db, Tables.Keys.SETUP);
+ Cursor b = dh.getValue(db, new String[] {Device.Keys.BASE_IMAGE}, BaseColumns._ID, 1);
+ if(b != null && b.moveToFirst()) {
+ baseImage = b.getBlob(0);
+ b.close();
+
+ Security.addProvider(new BouncyCastleProvider());
+ KeyPairGenerator kpg;
+
+ try {
+ String pwd = generatePassword(baseImage);
+ kpg = KeyPairGenerator.getInstance("RSA","BC");
+ kpg.initialize(4096);
+ KeyPair keyPair = kpg.generateKeyPair();
+
+ PGPSignatureSubpacketGenerator hashedGen = new PGPSignatureSubpacketGenerator();
+ hashedGen.setKeyFlags(true, KeyFlags.ENCRYPT_STORAGE);
+ hashedGen.setPreferredCompressionAlgorithms(false, new int[] {
+ CompressionAlgorithmTags.ZLIB,
+ CompressionAlgorithmTags.ZIP
+ });
+ hashedGen.setPreferredHashAlgorithms(false, new int[] {
+ HashAlgorithmTags.SHA256,
+ HashAlgorithmTags.SHA384,
+ HashAlgorithmTags.SHA512
+ });
+ hashedGen.setPreferredSymmetricAlgorithms(false, new int[] {
+ SymmetricKeyAlgorithmTags.AES_256,
+ SymmetricKeyAlgorithmTags.AES_192,
+ SymmetricKeyAlgorithmTags.AES_128,
+ SymmetricKeyAlgorithmTags.CAST5,
+ SymmetricKeyAlgorithmTags.DES
+ });
+
+ PGPSecretKey secret = new PGPSecretKey(
+ PGPSignature.DEFAULT_CERTIFICATION,
+ PublicKeyAlgorithmTags.RSA_GENERAL,
+ keyPair.getPublic(),
+ keyPair.getPrivate(),
+ new Date(),
+ "InformaCam OpenPGP Key",
+ SymmetricKeyAlgorithmTags.AES_256,
+ pwd.toCharArray(),
+ hashedGen.generate(),
+ null,
+ new SecureRandom(),
+ "BC");
+
+ ContentValues cv = new ContentValues();
+ cv.put(Settings.Device.Keys.SECRET_KEY, secret.getEncoded());
+ cv.put(Settings.Device.Keys.AUTH_KEY, pwd);
+ cv.put(Settings.Device.Keys.KEYRING_ID, secret.getPublicKey().getKeyID());
+
+ Log.d(Crypto.LOG, cv.toString());
+ db.update(dh.getTable(), cv, BaseColumns._ID + " = ?", new String[] {Integer.toString(1)});
+ db.close();
+ dh.close();
+
+ KeyServerResponse ksr = new KeyServerResponse(
+ secret.getPublicKey(),
+ sp.getString(Settings.Keys.DISPLAY_NAME, sp.getString(Settings.Keys.DISPLAY_NAME, "")),
+ sp.getString(Settings.Keys.DISPLAY_NAME, sp.getString(Settings.Keys.DISPLAY_NAME, ""))
+ );
+
+ installNewKey(c, ksr, null);
+
+ return true;
+ } catch (NoSuchAlgorithmException e) {
+ Log.e(Crypto.LOG, "key error: " + e.toString());
+ db.close();
+ dh.close();
+ return false;
+ } catch (NoSuchProviderException e) {
+ Log.e(Crypto.LOG, "key error: " + e.toString());
+ db.close();
+ dh.close();
+ return false;
+ } catch (PGPException e) {
+ Log.e(Crypto.LOG, "key error: " + e.toString());
+ db.close();
+ dh.close();
+ return false;
+ } catch (IOException e) {
+ Log.e(Crypto.LOG, "key error: " + e.toString());
+ db.close();
+ dh.close();
+ return false;
+ }
+ }
+
+ db.close();
+ dh.close();
+ return false;
+ }
}
View
13 src/org/witness/informacam/storage/DatabaseHelper.java
@@ -6,6 +6,7 @@
import org.witness.informacam.utils.Constants.Informa;
import org.witness.informacam.utils.Constants.Media;
import org.witness.informacam.utils.Constants.Settings;
+import org.witness.informacam.utils.Constants.Crypto.PGP;
import org.witness.informacam.utils.Constants.Storage.Tables;
import org.witness.informacam.utils.Constants.TrustedDestination;
@@ -46,23 +47,29 @@
TrustedDestination.Keys.DISPLAY_NAME + " text, " +
TrustedDestination.Keys.EMAIL + " text, " +
TrustedDestination.Keys.KEYRING_ID + " integer, " +
- TrustedDestination.Keys.URL + " text" +
+ TrustedDestination.Keys.URL + " text, " +
+ TrustedDestination.Keys.IS_DELETABLE + " integer, " +
+ TrustedDestination.Keys.CONTACT_PHOTO + " blob" +
")",
"CREATE TABLE " + Tables.Keys.SETUP + " (" + BaseColumns._ID + " " +
"integer primary key autoincrement," +
Informa.Keys.Device.LOCAL_TIMESTAMP + " integer, " +
Informa.Keys.Device.PUBLIC_TIMESTAMP + " integer, " +
Informa.Keys.Device.DISPLAY_NAME + " text, " +
Settings.Device.Keys.KEYRING_ID + " integer, " +
- Settings.Device.Keys.PRIVATE_KEY + " blob, " +
+ Settings.Device.Keys.SECRET_KEY + " blob, " +
Settings.Device.Keys.AUTH_KEY + " text, " +
- Settings.Device.Keys.BASE_IMAGE_PATH + " text" +
+ Settings.Device.Keys.BASE_IMAGE + " text" +
")",
"CREATE TABLE " + Tables.Keys.KEYRING + " (" + BaseColumns._ID + " " +
"integer primary key autoincrement," +
Crypto.Keyring.Keys.ID + " integer, " +
Crypto.Keyring.Keys.PUBLIC_KEY + " blob, " +
Crypto.Keyring.Keys.FINGERPRINT + " text, " +
+ PGP.Keys.PGP_CREATION_DATE + " integer, " +
+ PGP.Keys.PGP_EXPIRY_DATE + " integer, " +
+ PGP.Keys.PGP_DISPLAY_NAME + " text, " +
+ PGP.Keys.PGP_EMAIL_ADDRESS + " text, " +
Crypto.Keyring.Keys.TRUSTED_DESTINATION_ID + " integer" +
")",
"CREATE TABLE " + Tables.Keys.KEYSTORE + " (" + BaseColumns._ID + " " +
View
61 src/org/witness/informacam/transport/HttpUtility.java
@@ -12,6 +12,13 @@
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@@ -32,26 +39,44 @@
import android.util.Log;
public class HttpUtility {
- public static String executeHttpGet(String url, boolean proxy) throws URISyntaxException, ClientProtocolException, IOException {
- HttpClient client = new DefaultHttpClient();
-
- if(proxy) {
- HttpHost host = new HttpHost("localhost", 8118);
- client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, host);
- }
+
+ public static String executeHttpGet(String url) throws ClientProtocolException, URISyntaxException, IOException, InterruptedException, ExecutionException {
+ return HttpUtility.executeHttpGet(url, false);
+ }
+
+ public static String executeHttpGet(final String url, final boolean proxy) throws URISyntaxException, ClientProtocolException, IOException, InterruptedException, ExecutionException {
+ ExecutorService ex = Executors.newFixedThreadPool(100);
+ Future<String> future = ex.submit(new Callable<String>() {
+
+ @Override
+ public String call() throws Exception {
+ HttpClient client = new DefaultHttpClient();
+
+ if(proxy) {
+ HttpHost host = new HttpHost("localhost", 8118);
+ client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, host);
+ }
+
+ HttpGet request = new HttpGet();
+ request.setURI(new URI(url));
+ HttpResponse res = client.execute(request);
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
+ StringBuffer sb = new StringBuffer();
+ String line = "";
+ while((line = br.readLine()) != null)
+ sb.append(line + "\r\n");
+ br.close();
+
+ return sb.toString();
+ }
+
+ });
- HttpGet request = new HttpGet();
- request.setURI(new URI(url));
- HttpResponse res = client.execute(request);
+ String res = future.get();
+ ex.shutdown();
- BufferedReader br = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
- StringBuffer sb = new StringBuffer();
- String line = "";
- while((line = br.readLine()) != null)
- sb.append(line + "\r\n");
- br.close();
-
- return sb.toString();
+ return res;
}
public static HttpsURLConnection initHttpsConnection(Context c, String urlString, boolean useProxy) {
View
202 src/org/witness/informacam/utils/AddressBookUtil.java
@@ -9,6 +9,7 @@
import org.witness.informacam.app.mods.Selections;
import org.witness.informacam.utils.Constants.AddressBook;
import org.witness.informacam.utils.Constants.App;
+import org.witness.informacam.utils.Constants.TrustedDestination;
import android.app.Activity;
import android.content.ContentUris;
@@ -24,90 +25,139 @@
public class AddressBookUtil {
public interface AddressBookListener {
- public void receiveNewAddresses(ArrayList<Selections> s);
- public void receiveNewAddresses(JSONObject address);
+ public void receiveNewAddresses(AddressBookDisplay address);
+ public void onNoResultFound(String emailAddress);
+ public void onMultipleChoicesFound(ArrayList<Selections> choices);
}
+ public static void getLookupFromEmailAddress(final Activity c, String lookup) {
+ String[] projection = new String[] {
+ Contacts.DISPLAY_NAME,
+ Email.CONTACT_ID
+ };
+
+ AddressBookDisplay abd = null;
+ long contactId = 0L;
+ String contactDisplayName = null;
+
+ Cursor a = c.getContentResolver().query(Email.CONTENT_URI, projection, Email.DATA + "=?", new String[] {lookup}, null);
+ if(a != null && a.moveToFirst()) {
+ contactId = a.getLong(a.getColumnIndex(Email.CONTACT_ID));
+ contactDisplayName = a.getString(a.getColumnIndex(Contacts.DISPLAY_NAME));
+
+ String photoQuery = Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'";
+ Cursor b = c.getContentResolver().query(Data.CONTENT_URI, null, photoQuery, null, null);
+
+ abd = new AddressBookDisplay(c, contactId, contactDisplayName, lookup, true);
+ if(b != null) {
+ if(b.moveToFirst()) {
+ Uri contact = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+ Uri photoUri = Uri.withAppendedPath(contact, Contacts.Photo.CONTENT_DIRECTORY);
+
+ Cursor p = c.getContentResolver().query(photoUri, new String[] {Contacts.Photo.PHOTO}, null, null, null);
+ if(p != null) {
+ if(p.moveToFirst())
+ abd = new AddressBookDisplay(c, contactId, contactDisplayName, lookup, Base64.encode(p.getBlob(0)), true);
+ p.close();
+ }
+
+ }
+ b.close();
+ }
+ a.close();
+ }
+
+ if(abd != null)
+ ((AddressBookListener) c).receiveNewAddresses(abd);
+ else
+ ((AddressBookListener) c).onNoResultFound(lookup);
+
+ }
- public static void getAddressList(final Activity c, String[] emailAddresses) {
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- ArrayList<Selections> s = new ArrayList<Selections>();
- String[] projection = new String[] {
- Email.DATA,
- Contacts.DISPLAY_NAME,
- Email.CONTACT_ID
- };
-
- Cursor a = c.getContentResolver().query(Email.CONTENT_URI, projection, null, null, Contacts.DISPLAY_NAME + " ASC");
-
-
- if(a != null) {
- Log.d(App.LOG, "TOTAL: " + a.getCount());
+ public static void getEmailAddressFromLookup(final Activity c, long lookup) {
+ AddressBookUtil.getEmailAddressFromLookup(c, lookup, -1);
+ }
+
+ public static void getEmailAddressFromLookup(final Activity c, long lookup, int certainChoice) {
+ String[] projection = new String[] {
+ Email.DATA,
+ Contacts.DISPLAY_NAME,
+ };
+
+ Log.d(App.LOG, "looking up " + lookup);
+
+ AddressBookDisplay abd = null;
+ String contactEmail = "email";
+ String contactDisplayName = null;
+
+ int choice = 0;
+
+ Cursor a = c.getContentResolver().query(Email.CONTENT_URI, projection, Email.CONTACT_ID + "=?", new String[] {Long.toString(lookup)}, null);
+ if(a != null && a.moveToFirst()) {
+ Log.d(App.LOG, "found " + a.getCount() + " results");
+ if(a.getCount() > 1) {
+ if(certainChoice == -1) {
+ ArrayList<Selections> choices = new ArrayList<Selections>();
+ choices.add(new Selections(a.getString(a.getColumnIndex(Email.DATA)), false));
+ while(a.moveToNext())
+ choices.add(new Selections(a.getString(a.getColumnIndex(Email.DATA)), false));
+ ((AddressBookListener) c).onMultipleChoicesFound(choices);
- int batchNum = 1;
- int dispatchNum = 0;
- int threshold = 10;
- if(a.getCount() >= threshold)
- batchNum = Math.round(a.getCount()/threshold) + 1;
+ return;
+ } else
+ choice = certainChoice;
+ }
+
+ a.moveToPosition(choice);
+ contactEmail = a.getString(a.getColumnIndex(Email.DATA));
+ contactDisplayName = a.getString(a.getColumnIndex(Contacts.DISPLAY_NAME));
+
+ String photoQuery = Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'";
+ Cursor b = c.getContentResolver().query(Data.CONTENT_URI, null, photoQuery, null, null);
+
+ abd = new AddressBookDisplay(c, lookup, contactDisplayName, contactEmail, true);
+ if(b != null) {
+ if(b.moveToFirst()) {
+ Uri contact = ContentUris.withAppendedId(Contacts.CONTENT_URI, lookup);
+ Uri photoUri = Uri.withAppendedPath(contact, Contacts.Photo.CONTENT_DIRECTORY);
- a.moveToFirst();
- while(a.moveToNext()) {
- if(dispatchNum != threshold) {
- boolean isSelected = false;
- String contactEmail = a.getString(a.getColumnIndex(Email.DATA));
- String contactDisplayName = a.getString(a.getColumnIndex(Contacts.DISPLAY_NAME));
- long contactId = a.getLong(a.getColumnIndex(Email.CONTACT_ID));
-
- byte[] contactPhoto = Base64.encode(IOUtility.getBytesFromBitmap(((BitmapDrawable) c.getResources().getDrawable(R.drawable.ic_blank_person)).getBitmap(), 10));
-
- try {
- String photoQuery = Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'";
- Cursor b = c.getContentResolver().query(Data.CONTENT_URI, null, photoQuery, null, null);
-
- if(b != null) {
- if(b.moveToFirst()) {
- Uri contact = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
- Uri photoUri = Uri.withAppendedPath(contact, Contacts.Photo.CONTENT_DIRECTORY);
-
- Cursor p = c.getContentResolver().query(photoUri, new String[] {Contacts.Photo.PHOTO}, null, null, null);
- if(p != null) {
- if(p.moveToFirst())
- contactPhoto = Base64.encode(p.getBlob(0));
- p.close();
- }
- }
- b.close();
- }
-
-
- JSONObject contactExtras = new JSONObject();
- contactExtras.put(AddressBook.Keys.CONTACT_EMAIL, contactEmail);
- contactExtras.put(AddressBook.Keys.CONTACT_NAME, contactDisplayName.equals(contactEmail) ? "" : contactDisplayName);
- contactExtras.put(AddressBook.Keys.CONTACT_PHOTO, new String(contactPhoto));
-
- s.add(new Selections(contactDisplayName + "\n" + contactEmail, isSelected, contactExtras));
- } catch(JSONException e) {}
- dispatchNum++;
- } else {
- // dispatch some results
- ((AddressBookListener) c).receiveNewAddresses(s);
- s.clear();
- dispatchNum = 0;
- }
-
- }
- a.close();
+ Cursor p = c.getContentResolver().query(photoUri, new String[] {Contacts.Photo.PHOTO}, null, null, null);
+ if(p != null) {
+ if(p.moveToFirst())
+ abd = new AddressBookDisplay(c, lookup, contactDisplayName, contactEmail, Base64.encode(p.getBlob(0)), true);
+ p.close();
+ }
+
}
-
+ b.close();
}
-
- }).start();
+ a.close();
+ }
+
+ if(abd != null)
+ ((AddressBookListener) c).receiveNewAddresses(abd);
+ else
+ ((AddressBookListener) c).onNoResultFound(contactEmail);
+ }
+
+ public static void deleteContact(long tdId, String email) {
+
}
- public static void getAddressList(Activity c) {
- getAddressList(c, null);
+ public final static class AddressBookDisplay extends JSONObject {
+ public AddressBookDisplay(Activity c, long id, String displayName, String emailAddress, byte[] photo, boolean isDeletable) {
+ try {
+ this.put(AddressBook.Keys.CONTACT_NAME, displayName);
+ this.put(AddressBook.Keys.CONTACT_EMAIL, emailAddress);
+ this.put(AddressBook.Keys.CONTACT_ID, id);
+ this.put(AddressBook.Keys.CONTACT_PHOTO, new String(photo));
+ this.put(TrustedDestination.Keys.IS_DELETABLE, isDeletable);
+ } catch (JSONException e) {}
+ }
+
+ public AddressBookDisplay(Activity c, long id, String displayName, String emailAddress, boolean isDeletable) {