more work on content provider

This commit is contained in:
Dominik 2012-10-28 23:51:03 +01:00
parent d24bbdc6a1
commit 4704e2faf4
37 changed files with 4075 additions and 1220 deletions

View File

View File

@ -81,7 +81,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".ui.PublicKeyListActivity" android:name=".ui.KeyListPublicActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_managePublicKeys" android:label="@string/title_managePublicKeys"
android:launchMode="singleTop" android:launchMode="singleTop"
@ -146,7 +146,7 @@
android:resource="@xml/searchable_public_keys" /> android:resource="@xml/searchable_public_keys" />
</activity> </activity>
<activity <activity
android:name=".ui.SecretKeyListActivity" android:name=".ui.KeyListSecretActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_manageSecretKeys" android:label="@string/title_manageSecretKeys"
android:launchMode="singleTop" android:launchMode="singleTop"
@ -340,35 +340,35 @@
<provider <provider
android:name=".provider.ApgProvider" android:name=".provider.ApgProvider"
android:authorities="org.thialfihar.android.apg.provider" android:authorities="org.thialfihar.android.apg"
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" /> android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
<!-- DEPRECATED: --> <!-- DEPRECATED: -->
<provider <!-- <provider -->
android:name=".deprecated.DataProvider" <!-- android:name=".deprecated.DataProvider" -->
android:authorities="org.thialfihar.android.apg.provider" <!-- android:authorities="org.thialfihar.android.apg.provider" -->
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" /> <!-- android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" /> -->
<!-- TODO: need to be moved into new service model --> <!-- TODO: need to be moved into new service model -->
<service <!-- <service -->
android:name=".deprecated.ApgService2" <!-- android:name=".deprecated.ApgService2" -->
android:enabled="true" <!-- android:enabled="true" -->
android:exported="true" <!-- android:exported="true" -->
android:permission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" <!-- android:permission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" -->
android:process=":remote" > <!-- android:process=":remote" > -->
<intent-filter> <!-- <intent-filter> -->
<action android:name="org.thialfihar.android.apg.service.IApgService2" /> <!-- <action android:name="org.thialfihar.android.apg.service.IApgService2" /> -->
</intent-filter> <!-- </intent-filter> -->
<meta-data <!-- <meta-data -->
android:name="api_version" <!-- android:name="api_version" -->
android:value="2" /> <!-- android:value="2" /> -->
</service> <!-- </service> -->
<provider <!-- <provider -->
android:name=".deprecated.ApgServiceBlobProvider" <!-- android:name=".deprecated.ApgServiceBlobProvider" -->
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider" <!-- android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider" -->
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" /> <!-- android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" /> -->
</application> </application>
</manifest> </manifest>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org> <!--
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,40 +15,26 @@
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:layout_marginRight="?android:attr/scrollbarSize"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"> android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_marginRight="?android:attr/scrollbarSize"
android:orientation="vertical"
android:paddingLeft="36dip"
android:singleLine="true" >
<LinearLayout <TextView
android:orientation="vertical" android:id="@+id/mainUserId"
android:layout_width="fill_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="36dip"> android:text="Main User ID"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView <TextView
android:id="@+id/mainUserId" android:id="@+id/mainUserIdRest"
android:text="Main User ID" android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:text="&lt;user@example.com>"
android:layout_height="wrap_content"/> android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView </LinearLayout>
android:id="@+id/mainUserIdRest"
android:text="&lt;user@somewhere.com&gt;"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,13 @@
<?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:layout_centerHorizontal="true" >
<fragment
android:id="@+id/public_key_list_fragment"
android:name="org.thialfihar.android.apg.ui.KeyListPublicFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

View File

@ -0,0 +1,13 @@
<?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:layout_centerHorizontal="true" >
<fragment
android:id="@+id/secret_key_list_fragment"
android:name="org.thialfihar.android.apg.ui.KeyListSecretFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:singleLine="true"
android:paddingLeft="3dip"
android:layout_marginRight="?android:attr/scrollbarSize"
android:paddingTop="3dip"
android:paddingBottom="3dip"
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent">
<ImageView
android:id="@+id/ic_status"
android:src="@drawable/encrypted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<LinearLayout
android:orientation="vertical"
android:paddingLeft="5dip"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/subject"
android:text="Subject"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/emailAddress"
android:text="user@somewhere.com"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,13 @@
<?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:layout_centerHorizontal="true" >
<fragment
android:id="@+id/select_public_key_fragment"
android:name="org.thialfihar.android.apg.ui.SelectPublicKeyListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

View File

@ -24,7 +24,7 @@ import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.helper.Preferences; import org.thialfihar.android.apg.helper.Preferences;
import org.thialfihar.android.apg.ui.MainActivity; import org.thialfihar.android.apg.ui.MainActivity;
import org.thialfihar.android.apg.ui.SelectSecretKeyListActivity; import org.thialfihar.android.apg.ui.SelectSecretKeyListActivityOld;
import org.thialfihar.android.apg.util.ProgressDialogUpdater; import org.thialfihar.android.apg.util.ProgressDialogUpdater;
import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar;
@ -263,7 +263,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
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(SelectSecretKeyListActivity.RESULT_EXTRA_KEY_ID)); setSecretKeyId(bundle.getLong(SelectSecretKeyListActivityOld.RESULT_EXTRA_KEY_ID));
} else { } else {
setSecretKeyId(Id.key.none); setSecretKeyId(Id.key.none);
} }

View File

@ -0,0 +1,767 @@
///*
// * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
// * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package org.thialfihar.android.apg.deprecated;
//
//import org.thialfihar.android.apg.Constants;
//import org.thialfihar.android.apg.Id;
//import org.thialfihar.android.apg.helper.OtherHelper;
//import org.thialfihar.android.apg.helper.PGPHelper;
//import org.thialfihar.android.apg.helper.PGPMain;
//import org.thialfihar.android.apg.provider.KeyRings;
//import org.thialfihar.android.apg.provider.Keys;
//import org.thialfihar.android.apg.provider.UserIds;
//import org.thialfihar.android.apg.service.ApgServiceHandler;
//import org.thialfihar.android.apg.service.ApgService;
//import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
//import org.thialfihar.android.apg.ui.dialog.DeleteKeyDialogFragment;
//import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
//import org.thialfihar.android.apg.R;
//
//import com.actionbarsherlock.app.SherlockFragmentActivity;
//import com.actionbarsherlock.view.MenuItem;
//
//import android.app.AlertDialog;
//import android.app.ProgressDialog;
//import android.app.SearchManager;
//import android.content.Context;
//import android.content.DialogInterface;
//import android.content.Intent;
//import android.database.Cursor;
//import android.database.sqlite.SQLiteDatabase;
//import android.database.sqlite.SQLiteQueryBuilder;
//import android.os.Bundle;
//import android.os.Handler;
//import android.os.Message;
//import android.os.Messenger;
//import org.thialfihar.android.apg.util.Log;
//import android.view.LayoutInflater;
//import android.view.View;
//import android.view.View.OnClickListener;
//import android.view.ViewGroup;
//import android.widget.BaseExpandableListAdapter;
//import android.widget.Button;
//import android.widget.ExpandableListView;
//import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
//import android.widget.ImageView;
//import android.widget.TextView;
//import android.widget.Toast;
//
//import java.util.Vector;
//
//public class KeyListActivity extends SherlockFragmentActivity {
//
// public static final String ACTION_IMPORT = Constants.INTENT_PREFIX + "IMPORT";
//
// public static final String EXTRA_TEXT = "text";
//
// protected ExpandableListView mList;
// protected KeyListAdapter mListAdapter;
// protected View mFilterLayout;
// protected Button mClearFilterButton;
// protected TextView mFilterInfo;
//
// protected int mSelectedItem = -1;
// protected int mTask = 0;
//
// protected String mImportFilename = Constants.path.APP_DIR + "/";
// protected String mExportFilename = Constants.path.APP_DIR + "/";
//
// protected String mImportData;
// protected boolean mDeleteAfterImport = false;
//
// protected int mKeyType = Id.type.public_key;
//
// FileDialogFragment mFileDialog;
//
// @Override
// public void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.key_list);
//
// // set actionbar without home button if called from another app
// OtherHelper.setActionBarBackButton(this);
//
// setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
//
// mList = (ExpandableListView) findViewById(R.id.list);
// registerForContextMenu(mList);
//
// mFilterLayout = findViewById(R.id.layout_filter);
// mFilterInfo = (TextView) mFilterLayout.findViewById(R.id.filterInfo);
// mClearFilterButton = (Button) mFilterLayout.findViewById(R.id.btn_clear);
//
// mClearFilterButton.setOnClickListener(new OnClickListener() {
// public void onClick(View v) {
// handleIntent(new Intent());
// }
// });
//
// handleIntent(getIntent());
// }
//
// @Override
// protected void onNewIntent(Intent intent) {
// super.onNewIntent(intent);
// handleIntent(intent);
// }
//
// protected void handleIntent(Intent intent) {
// String searchString = null;
// if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// searchString = intent.getStringExtra(SearchManager.QUERY);
// if (searchString != null && searchString.trim().length() == 0) {
// searchString = null;
// }
// }
//
// if (searchString == null) {
// mFilterLayout.setVisibility(View.GONE);
// } else {
// mFilterLayout.setVisibility(View.VISIBLE);
// mFilterInfo.setText(getString(R.string.filterInfo, searchString));
// }
//
// if (mListAdapter != null) {
// mListAdapter.cleanup();
// }
// mListAdapter = new KeyListAdapter(this, searchString);
// mList.setAdapter(mListAdapter);
//
// // Get intent, action
// // Intent intent = getIntent();
// String action = intent.getAction();
//
// if (Intent.ACTION_VIEW.equals(action)) {
// // Android's Action when opening file associated to APG (see AndroidManifest.xml)
//
// handleActionImport(intent);
// } else if (ACTION_IMPORT.equals(action)) {
// // APG's own Actions
//
// handleActionImport(intent);
// }
// }
//
// /**
// * Handles import action
// *
// * @param intent
// */
// private void handleActionImport(Intent intent) {
// if ("file".equals(intent.getScheme()) && intent.getDataString() != null) {
// mImportFilename = intent.getData().getPath();
// } else {
// mImportData = intent.getStringExtra(EXTRA_TEXT);
// }
// importKeys();
// }
//
// @Override
// public boolean onOptionsItemSelected(MenuItem item) {
// switch (item.getItemId()) {
//
// case android.R.id.home:
// // app icon in Action Bar clicked; go home
// Intent intent = new Intent(this, MainActivity.class);
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// startActivity(intent);
// return true;
//
// case Id.menu.option.import_keys: {
// showImportKeysDialog();
// return true;
// }
//
// case Id.menu.option.export_keys: {
// showExportKeysDialog(false);
// return true;
// }
//
// case Id.menu.option.search:
// startSearch("", false, null, false);
// return true;
//
// default: {
// return super.onOptionsItemSelected(item);
// }
// }
// }
//
// private void showImportKeysDialog() {
// // Message is received after file is selected
// Handler returnHandler = new Handler() {
// @Override
// public void handleMessage(Message message) {
// if (message.what == FileDialogFragment.MESSAGE_OKAY) {
// Bundle data = message.getData();
// mImportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
//
// mDeleteAfterImport = data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED);
// importKeys();
// }
// }
// };
//
// // Create a new Messenger for the communication back
// Messenger messenger = new Messenger(returnHandler);
//
// mFileDialog = FileDialogFragment.newInstance(messenger,
// getString(R.string.title_importKeys), getString(R.string.specifyFileToImportFrom),
// mImportFilename, null, Id.request.filename);
//
// mFileDialog.show(getSupportFragmentManager(), "fileDialog");
// }
//
// private void showExportKeysDialog(boolean singleKeyExport) {
// String title = (singleKeyExport ? getString(R.string.title_exportKey)
// : getString(R.string.title_exportKeys));
// String message = getString(mKeyType == Id.type.public_key ? R.string.specifyFileToExportTo
// : R.string.specifyFileToExportSecretKeysTo);
//
// // Message is received after file is selected
// Handler returnHandler = new Handler() {
// @Override
// public void handleMessage(Message message) {
// if (message.what == FileDialogFragment.MESSAGE_OKAY) {
// Bundle data = message.getData();
// mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
//
// exportKeys();
// }
// }
// };
//
// // Create a new Messenger for the communication back
// Messenger messenger = new Messenger(returnHandler);
//
// mFileDialog = FileDialogFragment.newInstance(messenger, title, message, mExportFilename,
// null, Id.request.filename);
//
// mFileDialog.show(getSupportFragmentManager(), "fileDialog");
// }
//
// @Override
// public boolean onContextItemSelected(android.view.MenuItem menuItem) {
// ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
// int type = ExpandableListView.getPackedPositionType(info.packedPosition);
// int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
//
// if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// return super.onContextItemSelected(menuItem);
// }
//
// switch (menuItem.getItemId()) {
// case Id.menu.export: {
// mSelectedItem = groupPosition;
// showExportKeysDialog(true);
// return true;
// }
//
// case Id.menu.delete: {
// mSelectedItem = groupPosition;
// showDeleteKeyDialog();
// return true;
// }
//
// default: {
// return super.onContextItemSelected(menuItem);
// }
// }
// }
//
// private void showDeleteKeyDialog() {
// final int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
// mSelectedItem = -1;
//
// // Message is received after key is deleted
// Handler returnHandler = new Handler() {
// @Override
// public void handleMessage(Message message) {
// if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
// refreshList();
// }
// }
// };
//
// // Create a new Messenger for the communication back
// Messenger messenger = new Messenger(returnHandler);
//
// DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
// keyRingId, mKeyType);
//
// deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
// }
//
// public void importKeys() {
// Log.d(Constants.TAG, "importKeys started");
//
// // Send all information needed to service to import key in other thread
// Intent intent = new Intent(this, ApgService.class);
//
// intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_IMPORT_KEY);
//
// // fill values for this action
// Bundle data = new Bundle();
//
// data.putInt(ApgService.IMPORT_KEY_TYPE, mKeyType);
//
// if (mImportData != null) {
// data.putInt(ApgService.TARGET, ApgService.TARGET_BYTES);
// data.putByteArray(ApgService.IMPORT_BYTES, mImportData.getBytes());
// } else {
// data.putInt(ApgService.TARGET, ApgService.TARGET_FILE);
// data.putString(ApgService.IMPORT_FILENAME, mImportFilename);
// }
//
// intent.putExtra(ApgService.EXTRA_DATA, data);
//
// // Message is received after importing is done in ApgService
// ApgServiceHandler saveHandler = new ApgServiceHandler(this, R.string.progress_importing,
// ProgressDialog.STYLE_HORIZONTAL) {
// public void handleMessage(Message message) {
// // handle messages by standard ApgHandler first
// super.handleMessage(message);
//
// if (message.arg1 == ApgServiceHandler.MESSAGE_OKAY) {
// // get returned data bundle
// Bundle returnData = message.getData();
//
// int added = returnData.getInt(ApgService.RESULT_IMPORT_ADDED);
// int updated = returnData.getInt(ApgService.RESULT_IMPORT_UPDATED);
// int bad = returnData.getInt(ApgService.RESULT_IMPORT_BAD);
// String toastMessage;
// if (added > 0 && updated > 0) {
// toastMessage = getString(R.string.keysAddedAndUpdated, added, updated);
// } else if (added > 0) {
// toastMessage = getString(R.string.keysAdded, added);
// } else if (updated > 0) {
// toastMessage = getString(R.string.keysUpdated, updated);
// } else {
// toastMessage = getString(R.string.noKeysAddedOrUpdated);
// }
// Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
// if (bad > 0) {
// AlertDialog.Builder alert = new AlertDialog.Builder(KeyListActivity.this);
//
// alert.setIcon(android.R.drawable.ic_dialog_alert);
// alert.setTitle(R.string.warning);
// alert.setMessage(KeyListActivity.this.getString(
// R.string.badKeysEncountered, bad));
//
// alert.setPositiveButton(android.R.string.ok,
// new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int id) {
// dialog.cancel();
// }
// });
// alert.setCancelable(true);
// alert.create().show();
// } else if (mDeleteAfterImport) {
// // everything went well, so now delete, if that was turned on
// DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment
// .newInstance(mImportFilename);
// deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog");
// }
// refreshList();
//
// }
// };
// };
//
// // Create a new Messenger for the communication back
// Messenger messenger = new Messenger(saveHandler);
// intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
//
// // show progress dialog
// saveHandler.showProgressDialog(this);
//
// // start service with intent
// startService(intent);
// }
//
// public void exportKeys() {
// Log.d(Constants.TAG, "exportKeys started");
//
// // Send all information needed to service to export key in other thread
// Intent intent = new Intent(this, ApgService.class);
//
// intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_EXPORT_KEY);
//
// // fill values for this action
// Bundle data = new Bundle();
//
// data.putString(ApgService.EXPORT_FILENAME, mExportFilename);
// data.putInt(ApgService.EXPORT_KEY_TYPE, mKeyType);
//
// if (mSelectedItem == -1) {
// data.putBoolean(ApgService.EXPORT_ALL, true);
// } else {
// int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
// data.putInt(ApgService.EXPORT_KEY_RING_ID, keyRingId);
// mSelectedItem = -1;
// }
//
// intent.putExtra(ApgService.EXTRA_DATA, data);
//
// // Message is received after exporting is done in ApgService
// ApgServiceHandler exportHandler = new ApgServiceHandler(this, R.string.progress_exporting,
// ProgressDialog.STYLE_HORIZONTAL) {
// public void handleMessage(Message message) {
// // handle messages by standard ApgHandler first
// super.handleMessage(message);
//
// if (message.arg1 == ApgServiceHandler.MESSAGE_OKAY) {
// // get returned data bundle
// Bundle returnData = message.getData();
//
// int exported = returnData.getInt(ApgService.RESULT_EXPORT);
// String toastMessage;
// if (exported == 1) {
// toastMessage = getString(R.string.keyExported);
// } else if (exported > 0) {
// toastMessage = getString(R.string.keysExported, exported);
// } else {
// toastMessage = getString(R.string.noKeysExported);
// }
// Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
//
// }
// };
// };
//
// // Create a new Messenger for the communication back
// Messenger messenger = new Messenger(exportHandler);
// intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
//
// // show progress dialog
// exportHandler.showProgressDialog(this);
//
// // start service with intent
// startService(intent);
// }
//
// protected void refreshList() {
// mListAdapter.rebuild(true);
// mListAdapter.notifyDataSetChanged();
// }
//
// protected class KeyListAdapter extends BaseExpandableListAdapter {
// private LayoutInflater mInflater;
// private Vector<Vector<KeyChild>> mChildren;
// private SQLiteDatabase mDatabase;
// private Cursor mCursor;
// private String mSearchString;
//
// private class KeyChild {
// public static final int KEY = 0;
// public static final int USER_ID = 1;
// public static final int FINGER_PRINT = 2;
//
// public int type;
// public String userId;
// public long keyId;
// public boolean isMasterKey;
// public int algorithm;
// public int keySize;
// public boolean canSign;
// public boolean canEncrypt;
// public String fingerPrint;
//
// public KeyChild(long keyId, boolean isMasterKey, int algorithm, int keySize,
// boolean canSign, boolean canEncrypt) {
// this.type = KEY;
// this.keyId = keyId;
// this.isMasterKey = isMasterKey;
// this.algorithm = algorithm;
// this.keySize = keySize;
// this.canSign = canSign;
// this.canEncrypt = canEncrypt;
// }
//
// public KeyChild(String userId) {
// type = USER_ID;
// this.userId = userId;
// }
//
// public KeyChild(String fingerPrint, boolean isFingerPrint) {
// type = FINGER_PRINT;
// this.fingerPrint = fingerPrint;
// }
// }
//
// public KeyListAdapter(Context context, String searchString) {
// mSearchString = searchString;
//
// mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// mDatabase = PGPMain.getDatabase().db();
// SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
// qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
// + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
// + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
// + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
// + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
// + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK
// + " = '0')");
//
// if (searchString != null && searchString.trim().length() > 0) {
// String[] chunks = searchString.trim().split(" +");
// qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " + UserIds.TABLE_NAME
// + " AS tmp WHERE " + "tmp." + UserIds.KEY_ID + " = " + Keys.TABLE_NAME
// + "." + Keys._ID);
// for (int i = 0; i < chunks.length; ++i) {
// qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE ");
// qb.appendWhereEscapeString("%" + chunks[i] + "%");
// }
// qb.appendWhere(")");
// }
//
// mCursor = qb.query(mDatabase, new String[] { KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0
// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1
// UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2
// }, KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", new String[] { ""
// + (mKeyType == Id.type.public_key ? Id.database.type_public
// : Id.database.type_secret) }, null, null, UserIds.TABLE_NAME + "."
// + UserIds.USER_ID + " ASC");
//
// // content provider way for reference, might have to go back to it sometime:
// /*
// * Uri contentUri = null; if (mKeyType == Id.type.secret_key) { contentUri =
// * Apg.CONTENT_URI_SECRET_KEY_RINGS; } else { contentUri =
// * Apg.CONTENT_URI_PUBLIC_KEY_RINGS; } mCursor = getContentResolver().query( contentUri,
// * new String[] { DataProvider._ID, // 0 DataProvider.MASTER_KEY_ID, // 1
// * DataProvider.USER_ID, // 2 }, null, null, null);
// */
//
// startManagingCursor(mCursor);
// rebuild(false);
// }
//
// public void cleanup() {
// if (mCursor != null) {
// stopManagingCursor(mCursor);
// mCursor.close();
// }
// }
//
// public void rebuild(boolean requery) {
// if (requery) {
// mCursor.requery();
// }
// mChildren = new Vector<Vector<KeyChild>>();
// for (int i = 0; i < mCursor.getCount(); ++i) {
// mChildren.add(null);
// }
// }
//
// protected Vector<KeyChild> getChildrenOfGroup(int groupPosition) {
// Vector<KeyChild> children = mChildren.get(groupPosition);
// if (children != null) {
// return children;
// }
//
// mCursor.moveToPosition(groupPosition);
// children = new Vector<KeyChild>();
// Cursor c = mDatabase.query(Keys.TABLE_NAME, new String[] { Keys._ID, // 0
// Keys.KEY_ID, // 1
// Keys.IS_MASTER_KEY, // 2
// Keys.ALGORITHM, // 3
// Keys.KEY_SIZE, // 4
// Keys.CAN_SIGN, // 5
// Keys.CAN_ENCRYPT, // 6
// }, Keys.KEY_RING_ID + " = ?", new String[] { mCursor.getString(0) }, null, null,
// Keys.RANK + " ASC");
//
// int masterKeyId = -1;
// long fingerPrintId = -1;
// for (int i = 0; i < c.getCount(); ++i) {
// c.moveToPosition(i);
// children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4),
// c.getInt(5) == 1, c.getInt(6) == 1));
// if (i == 0) {
// masterKeyId = c.getInt(0);
// fingerPrintId = c.getLong(1);
// }
// }
// c.close();
//
// if (masterKeyId != -1) {
// children.insertElementAt(
// new KeyChild(PGPHelper.getFingerPrint(KeyListActivity.this, fingerPrintId), true), 0);
// c = mDatabase.query(UserIds.TABLE_NAME, new String[] { UserIds.USER_ID, // 0
// }, UserIds.KEY_ID + " = ? AND " + UserIds.RANK + " > 0", new String[] { ""
// + masterKeyId }, null, null, UserIds.RANK + " ASC");
//
// for (int i = 0; i < c.getCount(); ++i) {
// c.moveToPosition(i);
// children.add(new KeyChild(c.getString(0)));
// }
// c.close();
// }
//
// mChildren.set(groupPosition, children);
// return children;
// }
//
// public boolean hasStableIds() {
// return true;
// }
//
// public boolean isChildSelectable(int groupPosition, int childPosition) {
// return true;
// }
//
// public int getGroupCount() {
// return mCursor.getCount();
// }
//
// public Object getChild(int groupPosition, int childPosition) {
// return null;
// }
//
// public long getChildId(int groupPosition, int childPosition) {
// return childPosition;
// }
//
// public int getChildrenCount(int groupPosition) {
// return getChildrenOfGroup(groupPosition).size();
// }
//
// public Object getGroup(int position) {
// return position;
// }
//
// public long getGroupId(int position) {
// mCursor.moveToPosition(position);
// return mCursor.getLong(1); // MASTER_KEY_ID
// }
//
// public int getKeyRingId(int position) {
// mCursor.moveToPosition(position);
// return mCursor.getInt(0); // _ID
// }
//
// public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
// ViewGroup parent) {
// mCursor.moveToPosition(groupPosition);
//
// View view = mInflater.inflate(R.layout.key_list_group_item, null);
// view.setBackgroundResource(android.R.drawable.list_selector_background);
//
// TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
// mainUserId.setText("");
// TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
// mainUserIdRest.setText("");
//
// String userId = mCursor.getString(2); // USER_ID
// if (userId != null) {
// String chunks[] = userId.split(" <", 2);
// userId = chunks[0];
// if (chunks.length > 1) {
// mainUserIdRest.setText("<" + chunks[1]);
// }
// mainUserId.setText(userId);
// }
//
// if (mainUserId.getText().length() == 0) {
// mainUserId.setText(R.string.unknownUserId);
// }
//
// if (mainUserIdRest.getText().length() == 0) {
// mainUserIdRest.setVisibility(View.GONE);
// }
// return view;
// }
//
// public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
// View convertView, ViewGroup parent) {
// mCursor.moveToPosition(groupPosition);
//
// Vector<KeyChild> children = getChildrenOfGroup(groupPosition);
//
// KeyChild child = children.get(childPosition);
// View view = null;
// switch (child.type) {
// case KeyChild.KEY: {
// if (child.isMasterKey) {
// view = mInflater.inflate(R.layout.key_list_child_item_master_key, null);
// } else {
// view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null);
// }
//
// TextView keyId = (TextView) view.findViewById(R.id.keyId);
// String keyIdStr = PGPHelper.getSmallFingerPrint(child.keyId);
// keyId.setText(keyIdStr);
// TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
// String algorithmStr = PGPHelper.getAlgorithmInfo(child.algorithm, child.keySize);
// keyDetails.setText("(" + algorithmStr + ")");
//
// ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
// if (!child.canEncrypt) {
// encryptIcon.setVisibility(View.GONE);
// }
//
// ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
// if (!child.canSign) {
// signIcon.setVisibility(View.GONE);
// }
// break;
// }
//
// case KeyChild.USER_ID: {
// view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
// TextView userId = (TextView) view.findViewById(R.id.userId);
// userId.setText(child.userId);
// break;
// }
//
// case KeyChild.FINGER_PRINT: {
// view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
// TextView userId = (TextView) view.findViewById(R.id.userId);
// userId.setText(getString(R.string.fingerprint) + ":\n"
// + child.fingerPrint.replace(" ", "\n"));
// break;
// }
// }
// return view;
// }
// }
//
// @Override
// protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// switch (requestCode) {
// case Id.request.filename: {
// if (resultCode == RESULT_OK && data != null) {
// try {
// String path = data.getData().getPath();
// Log.d(Constants.TAG, "path=" + path);
//
// mFileDialog.setFilename(path);
// } catch (NullPointerException e) {
// Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
// }
// }
// return;
// }
//
// default: {
// break;
// }
// }
// super.onActivityResult(requestCode, resultCode, data);
// }
//}

View File

@ -131,4 +131,24 @@ public class OtherHelper {
actionBar.setHomeButtonEnabled(false); actionBar.setHomeButtonEnabled(false);
} }
} }
/**
* Splits userId string into naming part and email part
*
* @param userId
* @return array with naming (0) and email (1)
*/
public static String[] splitUserId(String userId) {
String[] output = new String[2];
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
output[1] = "<" + chunks[1];
}
output[0] = userId;
return output;
}
} }

View File

@ -298,6 +298,29 @@ public class ApgProvider extends ContentProvider {
return type; return type;
} }
private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb,
HashMap<String, String> projectionMap, int match, String sortOrder) {
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = ");
qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "."
+ KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "."
+ KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + Tables.USER_IDS
+ " ON " + "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS
+ "." + UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "."
+ UserIdsColumns.RANK + " = '0')");
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
+ KeyRingsColumns.MASTER_KEY_ID);
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID);
qb.setProjectionMap(projectionMap);
return qb;
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
@ -312,40 +335,35 @@ public class ApgProvider extends ContentProvider {
int match = sUriMatcher.match(uri); int match = sUriMatcher.match(uri);
switch (match) { switch (match) {
case PUBLIC_KEY_RING:
case SECRET_KEY_RING:
qb = buildKeyRingQuery(qb, projectionMap, match, sortOrder);
if (TextUtils.isEmpty(sortOrder)) {
sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
}
break;
case PUBLIC_KEY_RING_BY_ROW_ID: case PUBLIC_KEY_RING_BY_ROW_ID:
case SECRET_KEY_RING_BY_ROW_ID: case SECRET_KEY_RING_BY_ROW_ID:
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = " qb = buildKeyRingQuery(qb, projectionMap, match, sortOrder);
+ getKeyType(match));
qb.appendWhere(Tables.KEY_RINGS + "." + BaseColumns._ID + " = "); qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + BaseColumns._ID + " = ");
qb.appendWhereEscapeString(uri.getLastPathSegment()); qb.appendWhereEscapeString(uri.getLastPathSegment());
// break omitted intentionally if (TextUtils.isEmpty(sortOrder)) {
sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
}
break;
case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: case PUBLIC_KEY_RING_BY_MASTER_KEY_ID:
case SECRET_KEY_RING_BY_MASTER_KEY_ID: case SECRET_KEY_RING_BY_MASTER_KEY_ID:
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = "); qb = buildKeyRingQuery(qb, projectionMap, match, sortOrder);
qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getLastPathSegment()); qb.appendWhereEscapeString(uri.getLastPathSegment());
// break omitted intentionally
case PUBLIC_KEY_RING:
case SECRET_KEY_RING:
qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "."
+ KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "."
+ KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN "
+ Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = "
+ Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " AND "
+ Tables.USER_IDS + "." + UserIdsColumns.RANK + " = '0') ");
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
+ KeyRingsColumns.MASTER_KEY_ID);
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "."
+ UserIdsColumns.USER_ID);
if (TextUtils.isEmpty(sortOrder)) { if (TextUtils.isEmpty(sortOrder)) {
sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
} }
@ -354,8 +372,8 @@ public class ApgProvider extends ContentProvider {
case SECRET_KEY_RING_BY_KEY_ID: case SECRET_KEY_RING_BY_KEY_ID:
case PUBLIC_KEY_RING_BY_KEY_ID: case PUBLIC_KEY_RING_BY_KEY_ID:
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = " qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = ");
+ getKeyType(match)); qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
qb.setTables(Tables.KEYS + " AS tmp INNER JOIN " + Tables.KEY_RINGS + " ON (" qb.setTables(Tables.KEYS + " AS tmp INNER JOIN " + Tables.KEY_RINGS + " ON ("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + "tmp." + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + "tmp."
@ -363,9 +381,9 @@ public class ApgProvider extends ContentProvider {
+ "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." + "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "."
+ KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "." + KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "."
+ KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN "
+ Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + " ON " + "(" + Tables.KEY_RINGS + "." + BaseColumns._ID
+ Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " AND " + " = " + Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " AND "
+ Tables.USER_IDS + "." + UserIdsColumns.RANK + " = '0') "); + Tables.USER_IDS + "." + UserIdsColumns.RANK + " = '0')");
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
@ -373,15 +391,17 @@ public class ApgProvider extends ContentProvider {
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "."
+ UserIdsColumns.USER_ID); + UserIdsColumns.USER_ID);
qb.appendWhere("tmp." + KeysColumns.KEY_ID + " = "); qb.setProjectionMap(projectionMap);
qb.appendWhere(" AND tmp." + KeysColumns.KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getLastPathSegment()); qb.appendWhereEscapeString(uri.getLastPathSegment());
break; break;
case SECRET_KEY_RING_BY_EMAILS: case SECRET_KEY_RING_BY_EMAILS:
case PUBLIC_KEY_RING_BY_EMAILS: case PUBLIC_KEY_RING_BY_EMAILS:
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = " qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = ");
+ getKeyType(match)); qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "."
@ -389,7 +409,7 @@ public class ApgProvider extends ContentProvider {
+ KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN "
+ Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = "
+ Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " AND "
+ Tables.USER_IDS + "." + UserIdsColumns.RANK + " = '0') "); + Tables.USER_IDS + "." + UserIdsColumns.RANK + " = '0')");
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
@ -397,6 +417,8 @@ public class ApgProvider extends ContentProvider {
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "."
+ UserIdsColumns.USER_ID); + UserIdsColumns.USER_ID);
qb.setProjectionMap(projectionMap);
String emails = uri.getLastPathSegment(); String emails = uri.getLastPathSegment();
String chunks[] = emails.split(" *, *"); String chunks[] = emails.split(" *, *");
boolean gotCondition = false; boolean gotCondition = false;
@ -415,43 +437,55 @@ public class ApgProvider extends ContentProvider {
} }
if (gotCondition) { if (gotCondition) {
qb.appendWhere("EXISTS (SELECT tmp." + BaseColumns._ID + " FROM " + Tables.USER_IDS qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM "
+ " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID + " = " + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID
+ Tables.KEYS + "." + BaseColumns._ID + " AND (" + emailWhere + "))"); + " = " + Tables.KEYS + "." + BaseColumns._ID + " AND (" + emailWhere
+ "))");
} }
break; break;
case PUBLIC_KEY_RING_KEY:
case SECRET_KEY_RING_KEY:
qb.setTables(Tables.KEYS);
qb.appendWhere(KeysColumns.TYPE + " = ");
qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(2));
break;
case PUBLIC_KEY_RING_KEY_BY_ROW_ID: case PUBLIC_KEY_RING_KEY_BY_ROW_ID:
case SECRET_KEY_RING_KEY_BY_ROW_ID: case SECRET_KEY_RING_KEY_BY_ROW_ID:
String keyRowId = uri.getLastPathSegment();
qb.appendWhere(BaseColumns._ID + " = " + keyRowId);
// break omitted intentionally
case PUBLIC_KEY_RING_KEY:
case SECRET_KEY_RING_KEY:
qb.setTables(Tables.KEYS); qb.setTables(Tables.KEYS);
qb.appendWhere(KeysColumns.TYPE + " = " + getKeyType(match)); qb.appendWhere(KeysColumns.TYPE + " = ");
qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
String foreignKeyRingRowId = uri.getPathSegments().get(2); qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = ");
qb.appendWhere(KeysColumns.KEY_RING_ROW_ID + " = " + foreignKeyRingRowId); qb.appendWhereEscapeString(uri.getPathSegments().get(2));
qb.appendWhere(" AND " + BaseColumns._ID + " = ");
qb.appendWhereEscapeString(uri.getLastPathSegment());
break;
case PUBLIC_KEY_RING_USER_ID:
case SECRET_KEY_RING_USER_ID:
qb.setTables(Tables.USER_IDS);
qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(2));
break; break;
case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID:
case SECRET_KEY_RING_USER_ID_BY_ROW_ID: case SECRET_KEY_RING_USER_ID_BY_ROW_ID:
String userIdRowId = uri.getLastPathSegment();
qb.appendWhere(BaseColumns._ID + " = " + userIdRowId);
// break omitted intentionally
case PUBLIC_KEY_RING_USER_ID:
case SECRET_KEY_RING_USER_ID:
qb.setTables(Tables.USER_IDS); qb.setTables(Tables.USER_IDS);
qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(2));
String foreignKeyRowId = uri.getPathSegments().get(2); qb.appendWhere(" AND " + BaseColumns._ID + " = ");
qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = " + foreignKeyRowId); qb.appendWhereEscapeString(uri.getLastPathSegment());
break; break;
@ -460,8 +494,6 @@ public class ApgProvider extends ContentProvider {
} }
qb.setProjectionMap(projectionMap);
// If no sort order is specified use the default // If no sort order is specified use the default
String orderBy; String orderBy;
if (TextUtils.isEmpty(sortOrder)) { if (TextUtils.isEmpty(sortOrder)) {
@ -474,6 +506,15 @@ public class ApgProvider extends ContentProvider {
// Tell the cursor what uri to watch, so it knows when its source data changes // Tell the cursor what uri to watch, so it knows when its source data changes
c.setNotificationUri(getContext().getContentResolver(), uri); c.setNotificationUri(getContext().getContentResolver(), uri);
if (Constants.DEBUG) {
Log.d(Constants.TAG,
"Query: "
+ qb.buildQuery(projection, selection, selectionArgs, null, null,
orderBy, null));
Log.d(Constants.TAG, "Cursor: " + DatabaseUtils.dumpCursorToString(c));
}
return c; return c;
} }
@ -485,6 +526,7 @@ public class ApgProvider extends ContentProvider {
final SQLiteDatabase db = mApgDatabase.getWritableDatabase(); final SQLiteDatabase db = mApgDatabase.getWritableDatabase();
Uri rowUri = null; Uri rowUri = null;
long rowId = -1;
try { try {
final int match = sUriMatcher.match(uri); final int match = sUriMatcher.match(uri);
@ -492,41 +534,39 @@ public class ApgProvider extends ContentProvider {
case PUBLIC_KEY_RING: case PUBLIC_KEY_RING:
values.put(PublicKeyRings.TYPE, KeyTypes.PUBLIC); values.put(PublicKeyRings.TYPE, KeyTypes.PUBLIC);
db.insertOrThrow(Tables.KEY_RINGS, null, values); rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values);
rowUri = PublicKeyRings.buildPublicKeyRingsUri(values rowUri = PublicKeyRings.buildPublicKeyRingsUri(Long.toString(rowId));
.getAsString(PublicKeyRings._ID));
break; break;
case PUBLIC_KEY_RING_KEY: case PUBLIC_KEY_RING_KEY:
values.put(PublicKeys.TYPE, KeyTypes.PUBLIC); values.put(PublicKeys.TYPE, KeyTypes.PUBLIC);
db.insertOrThrow(Tables.KEYS, null, values); rowId = db.insertOrThrow(Tables.KEYS, null, values);
rowUri = PublicKeys.buildPublicKeysUri(values.getAsString(PublicKeys._ID)); rowUri = PublicKeys.buildPublicKeysUri(Long.toString(rowId));
break; break;
case PUBLIC_KEY_RING_USER_ID: case PUBLIC_KEY_RING_USER_ID:
db.insertOrThrow(Tables.USER_IDS, null, values); rowId = db.insertOrThrow(Tables.USER_IDS, null, values);
rowUri = PublicUserIds.buildPublicUserIdsUri(values.getAsString(PublicUserIds._ID)); rowUri = PublicUserIds.buildPublicUserIdsUri(Long.toString(rowId));
break; break;
case SECRET_KEY_RING: case SECRET_KEY_RING:
values.put(SecretKeyRings.TYPE, KeyTypes.SECRET); values.put(SecretKeyRings.TYPE, KeyTypes.SECRET);
db.insertOrThrow(Tables.KEY_RINGS, null, values); rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values);
rowUri = SecretKeyRings.buildSecretKeyRingsUri(values rowUri = SecretKeyRings.buildSecretKeyRingsUri(Long.toString(rowId));
.getAsString(SecretKeyRings._ID));
break; break;
case SECRET_KEY_RING_KEY: case SECRET_KEY_RING_KEY:
values.put(SecretKeys.TYPE, KeyTypes.SECRET); values.put(SecretKeys.TYPE, KeyTypes.SECRET);
db.insertOrThrow(Tables.KEYS, null, values); rowId = db.insertOrThrow(Tables.KEYS, null, values);
rowUri = SecretKeys.buildSecretKeysUri(values.getAsString(SecretKeys._ID)); rowUri = SecretKeys.buildSecretKeysUri(Long.toString(rowId));
break; break;
case SECRET_KEY_RING_USER_ID: case SECRET_KEY_RING_USER_ID:
db.insertOrThrow(Tables.USER_IDS, null, values); rowId = db.insertOrThrow(Tables.USER_IDS, null, values);
rowUri = SecretUserIds.buildSecretUserIdsUri(values.getAsString(SecretUserIds._ID)); rowUri = SecretUserIds.buildSecretUserIdsUri(Long.toString(rowId));
break; break;
default: default:

View File

@ -215,17 +215,21 @@ public class ProviderHelper {
// delete old version of this keyRing, which also deletes all keys and userIds on cascade // delete old version of this keyRing, which also deletes all keys and userIds on cascade
Uri deleteUri = PublicKeyRings.buildPublicKeyRingsByMasterKeyIdUri(Long Uri deleteUri = PublicKeyRings.buildPublicKeyRingsByMasterKeyIdUri(Long
.toString(masterKeyId)); .toString(masterKeyId));
context.getContentResolver().delete(deleteUri, null, null);
try {
context.getContentResolver().delete(deleteUri, null, null);
} catch (UnsupportedOperationException e) {
Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e);
}
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(PublicKeyRings.MASTER_KEY_ID, masterKeyId); values.put(PublicKeyRings.MASTER_KEY_ID, masterKeyId);
values.put(PublicKeyRings.KEY_RING_DATA, keyRing.getEncoded()); values.put(PublicKeyRings.KEY_RING_DATA, keyRing.getEncoded());
// insert new version of this keyRing // insert new version of this keyRing
Uri uri = PublicKeyRings.buildPublicKeyRingsByMasterKeyIdUri(values Uri uri = PublicKeyRings.buildPublicKeyRingsUri();
.getAsString(PublicKeyRings.MASTER_KEY_ID));
Uri insertedUri = context.getContentResolver().insert(uri, values); Uri insertedUri = context.getContentResolver().insert(uri, values);
long keyRingRowId = Long.getLong(insertedUri.getLastPathSegment()); long keyRingRowId = Long.valueOf(insertedUri.getLastPathSegment());
// save all keys and userIds included in keyRing object in database // save all keys and userIds included in keyRing object in database
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
@ -267,17 +271,21 @@ public class ProviderHelper {
// delete old version of this keyRing, which also deletes all keys and userIds on cascade // delete old version of this keyRing, which also deletes all keys and userIds on cascade
Uri deleteUri = SecretKeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long Uri deleteUri = SecretKeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long
.toString(masterKeyId)); .toString(masterKeyId));
context.getContentResolver().delete(deleteUri, null, null);
try {
context.getContentResolver().delete(deleteUri, null, null);
} catch (UnsupportedOperationException e) {
Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e);
}
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(SecretKeyRings.MASTER_KEY_ID, masterKeyId); values.put(SecretKeyRings.MASTER_KEY_ID, masterKeyId);
values.put(SecretKeyRings.KEY_RING_DATA, keyRing.getEncoded()); values.put(SecretKeyRings.KEY_RING_DATA, keyRing.getEncoded());
// insert new version of this keyRing // insert new version of this keyRing
Uri uri = SecretKeyRings.buildSecretKeyRingsByMasterKeyIdUri(values Uri uri = SecretKeyRings.buildSecretKeyRingsUri();
.getAsString(SecretKeyRings.MASTER_KEY_ID)); Uri insertedUri = context.getContentResolver().insert(uri, values);
Uri insertedUri = context.getContentResolver().insert(uri, values); long keyRingRowId = Long.valueOf(insertedUri.getLastPathSegment());
long keyRingRowId = Long.getLong(insertedUri.getLastPathSegment());
// save all keys and userIds included in keyRing object in database // save all keys and userIds included in keyRing object in database
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

View File

@ -111,7 +111,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
case android.R.id.home: case android.R.id.home:
// app icon in Action Bar clicked; go home // app icon in Action Bar clicked; go home
Intent intent = new Intent(this, SecretKeyListActivity.class); Intent intent = new Intent(this, KeyListSecretActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent); startActivity(intent);
return true; return true;

View File

@ -1001,7 +1001,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
} }
private void selectSecretKey() { private void selectSecretKey() {
Intent intent = new Intent(this, SelectSecretKeyListActivity.class); Intent intent = new Intent(this, SelectSecretKeyListActivityOld.class);
startActivityForResult(intent, Id.request.secret_keys); startActivityForResult(intent, Id.request.secret_keys);
} }
@ -1049,7 +1049,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
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(SelectSecretKeyListActivity.RESULT_EXTRA_KEY_ID)); setSecretKeyId(bundle.getLong(SelectSecretKeyListActivityOld.RESULT_EXTRA_KEY_ID));
} else { } else {
setSecretKeyId(Id.key.none); setSecretKeyId(Id.key.none);
} }

View File

@ -1,67 +1,35 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui; package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.helper.OtherHelper; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.thialfihar.android.apg.service.ApgServiceHandler;
import org.thialfihar.android.apg.service.ApgService; import org.thialfihar.android.apg.service.ApgService;
import org.thialfihar.android.apg.service.ApgServiceHandler;
import org.thialfihar.android.apg.ui.KeyListActivityOld.KeyListAdapter;
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment; import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
import org.thialfihar.android.apg.ui.dialog.DeleteKeyDialogFragment; import org.thialfihar.android.apg.ui.dialog.DeleteKeyDialogFragment;
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment; import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.util.Log;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.app.SearchManager; import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
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.os.Messenger; import android.os.Messenger;
import org.thialfihar.android.apg.util.Log;
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.widget.BaseExpandableListAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import java.util.Vector; import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
public class KeyListActivity extends SherlockFragmentActivity { public class KeyListActivity extends SherlockFragmentActivity {
@ -76,7 +44,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
protected TextView mFilterInfo; protected TextView mFilterInfo;
protected int mSelectedItem = -1; protected int mSelectedItem = -1;
protected int mTask = 0; // protected int mTask = 0;
protected String mImportFilename = Constants.path.APP_DIR + "/"; protected String mImportFilename = Constants.path.APP_DIR + "/";
protected String mExportFilename = Constants.path.APP_DIR + "/"; protected String mExportFilename = Constants.path.APP_DIR + "/";
@ -91,25 +59,9 @@ public class KeyListActivity extends SherlockFragmentActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.key_list);
// set actionbar without home button if called from another app getSupportActionBar().setDisplayHomeAsUpEnabled(true);
OtherHelper.setActionBarBackButton(this); getSupportActionBar().setHomeButtonEnabled(true);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
mList = (ExpandableListView) findViewById(R.id.list);
registerForContextMenu(mList);
mFilterLayout = findViewById(R.id.layout_filter);
mFilterInfo = (TextView) mFilterLayout.findViewById(R.id.filterInfo);
mClearFilterButton = (Button) mFilterLayout.findViewById(R.id.btn_clear);
mClearFilterButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
handleIntent(new Intent());
}
});
handleIntent(getIntent()); handleIntent(getIntent());
} }
@ -129,18 +81,18 @@ public class KeyListActivity extends SherlockFragmentActivity {
} }
} }
if (searchString == null) { // if (searchString == null) {
mFilterLayout.setVisibility(View.GONE); // mFilterLayout.setVisibility(View.GONE);
} else { // } else {
mFilterLayout.setVisibility(View.VISIBLE); // mFilterLayout.setVisibility(View.VISIBLE);
mFilterInfo.setText(getString(R.string.filterInfo, searchString)); // mFilterInfo.setText(getString(R.string.filterInfo, searchString));
} // }
//
if (mListAdapter != null) { // if (mListAdapter != null) {
mListAdapter.cleanup(); // mListAdapter.cleanup();
} // }
mListAdapter = new KeyListAdapter(this, searchString); // mListAdapter = new KeyListAdapter(this, searchString);
mList.setAdapter(mListAdapter); // mList.setAdapter(mListAdapter);
// Get intent, action // Get intent, action
// Intent intent = getIntent(); // Intent intent = getIntent();
@ -192,9 +144,9 @@ public class KeyListActivity extends SherlockFragmentActivity {
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: {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@ -293,7 +245,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) { if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
refreshList(); // refreshList();
} }
} }
}; };
@ -354,7 +306,8 @@ public class KeyListActivity extends SherlockFragmentActivity {
} else { } else {
toastMessage = getString(R.string.noKeysAddedOrUpdated); toastMessage = getString(R.string.noKeysAddedOrUpdated);
} }
Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show(); Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT)
.show();
if (bad > 0) { if (bad > 0) {
AlertDialog.Builder alert = new AlertDialog.Builder(KeyListActivity.this); AlertDialog.Builder alert = new AlertDialog.Builder(KeyListActivity.this);
@ -377,7 +330,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
.newInstance(mImportFilename); .newInstance(mImportFilename);
deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog");
} }
refreshList(); // refreshList();
} }
}; };
@ -438,7 +391,8 @@ public class KeyListActivity extends SherlockFragmentActivity {
} else { } else {
toastMessage = getString(R.string.noKeysExported); toastMessage = getString(R.string.noKeysExported);
} }
Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show(); Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT)
.show();
} }
}; };
@ -454,314 +408,4 @@ public class KeyListActivity extends SherlockFragmentActivity {
// start service with intent // start service with intent
startService(intent); startService(intent);
} }
protected void refreshList() {
mListAdapter.rebuild(true);
mListAdapter.notifyDataSetChanged();
}
protected class KeyListAdapter extends BaseExpandableListAdapter {
private LayoutInflater mInflater;
private Vector<Vector<KeyChild>> mChildren;
private SQLiteDatabase mDatabase;
private Cursor mCursor;
private String mSearchString;
private class KeyChild {
public static final int KEY = 0;
public static final int USER_ID = 1;
public static final int FINGER_PRINT = 2;
public int type;
public String userId;
public long keyId;
public boolean isMasterKey;
public int algorithm;
public int keySize;
public boolean canSign;
public boolean canEncrypt;
public String fingerPrint;
public KeyChild(long keyId, boolean isMasterKey, int algorithm, int keySize,
boolean canSign, boolean canEncrypt) {
this.type = KEY;
this.keyId = keyId;
this.isMasterKey = isMasterKey;
this.algorithm = algorithm;
this.keySize = keySize;
this.canSign = canSign;
this.canEncrypt = canEncrypt;
}
public KeyChild(String userId) {
type = USER_ID;
this.userId = userId;
}
public KeyChild(String fingerPrint, boolean isFingerPrint) {
type = FINGER_PRINT;
this.fingerPrint = fingerPrint;
}
}
public KeyListAdapter(Context context, String searchString) {
mSearchString = searchString;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDatabase = PGPMain.getDatabase().db();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
+ KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
+ Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
+ " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
+ Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
+ UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK
+ " = '0')");
if (searchString != null && searchString.trim().length() > 0) {
String[] chunks = searchString.trim().split(" +");
qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " + UserIds.TABLE_NAME
+ " AS tmp WHERE " + "tmp." + UserIds.KEY_ID + " = " + Keys.TABLE_NAME
+ "." + Keys._ID);
for (int i = 0; i < chunks.length; ++i) {
qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE ");
qb.appendWhereEscapeString("%" + chunks[i] + "%");
}
qb.appendWhere(")");
}
mCursor = qb.query(mDatabase, new String[] { KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0
KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2
}, KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", new String[] { ""
+ (mKeyType == Id.type.public_key ? Id.database.type_public
: Id.database.type_secret) }, null, null, UserIds.TABLE_NAME + "."
+ UserIds.USER_ID + " ASC");
// content provider way for reference, might have to go back to it sometime:
/*
* Uri contentUri = null; if (mKeyType == Id.type.secret_key) { contentUri =
* Apg.CONTENT_URI_SECRET_KEY_RINGS; } else { contentUri =
* Apg.CONTENT_URI_PUBLIC_KEY_RINGS; } mCursor = getContentResolver().query( contentUri,
* new String[] { DataProvider._ID, // 0 DataProvider.MASTER_KEY_ID, // 1
* DataProvider.USER_ID, // 2 }, null, null, null);
*/
startManagingCursor(mCursor);
rebuild(false);
}
public void cleanup() {
if (mCursor != null) {
stopManagingCursor(mCursor);
mCursor.close();
}
}
public void rebuild(boolean requery) {
if (requery) {
mCursor.requery();
}
mChildren = new Vector<Vector<KeyChild>>();
for (int i = 0; i < mCursor.getCount(); ++i) {
mChildren.add(null);
}
}
protected Vector<KeyChild> getChildrenOfGroup(int groupPosition) {
Vector<KeyChild> children = mChildren.get(groupPosition);
if (children != null) {
return children;
}
mCursor.moveToPosition(groupPosition);
children = new Vector<KeyChild>();
Cursor c = mDatabase.query(Keys.TABLE_NAME, new String[] { Keys._ID, // 0
Keys.KEY_ID, // 1
Keys.IS_MASTER_KEY, // 2
Keys.ALGORITHM, // 3
Keys.KEY_SIZE, // 4
Keys.CAN_SIGN, // 5
Keys.CAN_ENCRYPT, // 6
}, Keys.KEY_RING_ID + " = ?", new String[] { mCursor.getString(0) }, null, null,
Keys.RANK + " ASC");
int masterKeyId = -1;
long fingerPrintId = -1;
for (int i = 0; i < c.getCount(); ++i) {
c.moveToPosition(i);
children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4),
c.getInt(5) == 1, c.getInt(6) == 1));
if (i == 0) {
masterKeyId = c.getInt(0);
fingerPrintId = c.getLong(1);
}
}
c.close();
if (masterKeyId != -1) {
children.insertElementAt(
new KeyChild(PGPHelper.getFingerPrint(KeyListActivity.this, fingerPrintId), true), 0);
c = mDatabase.query(UserIds.TABLE_NAME, new String[] { UserIds.USER_ID, // 0
}, UserIds.KEY_ID + " = ? AND " + UserIds.RANK + " > 0", new String[] { ""
+ masterKeyId }, null, null, UserIds.RANK + " ASC");
for (int i = 0; i < c.getCount(); ++i) {
c.moveToPosition(i);
children.add(new KeyChild(c.getString(0)));
}
c.close();
}
mChildren.set(groupPosition, children);
return children;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public int getGroupCount() {
return mCursor.getCount();
}
public Object getChild(int groupPosition, int childPosition) {
return null;
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public int getChildrenCount(int groupPosition) {
return getChildrenOfGroup(groupPosition).size();
}
public Object getGroup(int position) {
return position;
}
public long getGroupId(int position) {
mCursor.moveToPosition(position);
return mCursor.getLong(1); // MASTER_KEY_ID
}
public int getKeyRingId(int position) {
mCursor.moveToPosition(position);
return mCursor.getInt(0); // _ID
}
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
mCursor.moveToPosition(groupPosition);
View view = mInflater.inflate(R.layout.key_list_group_item, null);
view.setBackgroundResource(android.R.drawable.list_selector_background);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText("");
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = mCursor.getString(2); // USER_ID
if (userId != null) {
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]);
}
mainUserId.setText(userId);
}
if (mainUserId.getText().length() == 0) {
mainUserId.setText(R.string.unknownUserId);
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
return view;
}
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
mCursor.moveToPosition(groupPosition);
Vector<KeyChild> children = getChildrenOfGroup(groupPosition);
KeyChild child = children.get(childPosition);
View view = null;
switch (child.type) {
case KeyChild.KEY: {
if (child.isMasterKey) {
view = mInflater.inflate(R.layout.key_list_child_item_master_key, null);
} else {
view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null);
}
TextView keyId = (TextView) view.findViewById(R.id.keyId);
String keyIdStr = PGPHelper.getSmallFingerPrint(child.keyId);
keyId.setText(keyIdStr);
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
String algorithmStr = PGPHelper.getAlgorithmInfo(child.algorithm, child.keySize);
keyDetails.setText("(" + algorithmStr + ")");
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (!child.canEncrypt) {
encryptIcon.setVisibility(View.GONE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (!child.canSign) {
signIcon.setVisibility(View.GONE);
}
break;
}
case KeyChild.USER_ID: {
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(child.userId);
break;
}
case KeyChild.FINGER_PRINT: {
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(getString(R.string.fingerprint) + ":\n"
+ child.fingerPrint.replace(" ", "\n"));
break;
}
}
return view;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) {
try {
String path = data.getData().getPath();
Log.d(Constants.TAG, "path=" + path);
mFileDialog.setFilename(path);
} catch (NullPointerException e) {
Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
}
}
return;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
} }

View File

@ -0,0 +1,767 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.helper.OtherHelper;
import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.service.ApgServiceHandler;
import org.thialfihar.android.apg.service.ApgService;
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
import org.thialfihar.android.apg.ui.dialog.DeleteKeyDialogFragment;
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
import org.thialfihar.android.apg.R;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.MenuItem;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import org.thialfihar.android.apg.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Vector;
public class KeyListActivityOld extends SherlockFragmentActivity {
public static final String ACTION_IMPORT = Constants.INTENT_PREFIX + "IMPORT";
public static final String EXTRA_TEXT = "text";
protected ExpandableListView mList;
protected KeyListAdapter mListAdapter;
protected View mFilterLayout;
protected Button mClearFilterButton;
protected TextView mFilterInfo;
protected int mSelectedItem = -1;
// protected int mTask = 0;
protected String mImportFilename = Constants.path.APP_DIR + "/";
protected String mExportFilename = Constants.path.APP_DIR + "/";
protected String mImportData;
protected boolean mDeleteAfterImport = false;
protected int mKeyType = Id.type.public_key;
FileDialogFragment mFileDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.key_list);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
mList = (ExpandableListView) findViewById(R.id.list);
registerForContextMenu(mList);
mFilterLayout = findViewById(R.id.layout_filter);
mFilterInfo = (TextView) mFilterLayout.findViewById(R.id.filterInfo);
mClearFilterButton = (Button) mFilterLayout.findViewById(R.id.btn_clear);
mClearFilterButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
handleIntent(new Intent());
}
});
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
protected void handleIntent(Intent intent) {
String searchString = null;
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
searchString = intent.getStringExtra(SearchManager.QUERY);
if (searchString != null && searchString.trim().length() == 0) {
searchString = null;
}
}
if (searchString == null) {
mFilterLayout.setVisibility(View.GONE);
} else {
mFilterLayout.setVisibility(View.VISIBLE);
mFilterInfo.setText(getString(R.string.filterInfo, searchString));
}
if (mListAdapter != null) {
mListAdapter.cleanup();
}
mListAdapter = new KeyListAdapter(this, searchString);
mList.setAdapter(mListAdapter);
// Get intent, action
// Intent intent = getIntent();
String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(action)) {
// Android's Action when opening file associated to APG (see AndroidManifest.xml)
handleActionImport(intent);
} else if (ACTION_IMPORT.equals(action)) {
// APG's own Actions
handleActionImport(intent);
}
}
/**
* Handles import action
*
* @param intent
*/
private void handleActionImport(Intent intent) {
if ("file".equals(intent.getScheme()) && intent.getDataString() != null) {
mImportFilename = intent.getData().getPath();
} else {
mImportData = intent.getStringExtra(EXTRA_TEXT);
}
importKeys();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in Action Bar clicked; go home
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
case Id.menu.option.import_keys: {
showImportKeysDialog();
return true;
}
case Id.menu.option.export_keys: {
showExportKeysDialog(false);
return true;
}
case Id.menu.option.search:
startSearch("", false, null, false);
return true;
default: {
return super.onOptionsItemSelected(item);
}
}
}
private void showImportKeysDialog() {
// Message is received after file is selected
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == FileDialogFragment.MESSAGE_OKAY) {
Bundle data = message.getData();
mImportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
mDeleteAfterImport = data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED);
importKeys();
}
}
};
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);
mFileDialog = FileDialogFragment.newInstance(messenger,
getString(R.string.title_importKeys), getString(R.string.specifyFileToImportFrom),
mImportFilename, null, Id.request.filename);
mFileDialog.show(getSupportFragmentManager(), "fileDialog");
}
private void showExportKeysDialog(boolean singleKeyExport) {
String title = (singleKeyExport ? getString(R.string.title_exportKey)
: getString(R.string.title_exportKeys));
String message = getString(mKeyType == Id.type.public_key ? R.string.specifyFileToExportTo
: R.string.specifyFileToExportSecretKeysTo);
// Message is received after file is selected
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == FileDialogFragment.MESSAGE_OKAY) {
Bundle data = message.getData();
mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
exportKeys();
}
}
};
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);
mFileDialog = FileDialogFragment.newInstance(messenger, title, message, mExportFilename,
null, Id.request.filename);
mFileDialog.show(getSupportFragmentManager(), "fileDialog");
}
@Override
public boolean onContextItemSelected(android.view.MenuItem menuItem) {
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
return super.onContextItemSelected(menuItem);
}
switch (menuItem.getItemId()) {
case Id.menu.export: {
mSelectedItem = groupPosition;
showExportKeysDialog(true);
return true;
}
case Id.menu.delete: {
mSelectedItem = groupPosition;
showDeleteKeyDialog();
return true;
}
default: {
return super.onContextItemSelected(menuItem);
}
}
}
private void showDeleteKeyDialog() {
final int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
mSelectedItem = -1;
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
refreshList();
}
}
};
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
keyRingId, mKeyType);
deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
}
public void importKeys() {
Log.d(Constants.TAG, "importKeys started");
// Send all information needed to service to import key in other thread
Intent intent = new Intent(this, ApgService.class);
intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_IMPORT_KEY);
// fill values for this action
Bundle data = new Bundle();
data.putInt(ApgService.IMPORT_KEY_TYPE, mKeyType);
if (mImportData != null) {
data.putInt(ApgService.TARGET, ApgService.TARGET_BYTES);
data.putByteArray(ApgService.IMPORT_BYTES, mImportData.getBytes());
} else {
data.putInt(ApgService.TARGET, ApgService.TARGET_FILE);
data.putString(ApgService.IMPORT_FILENAME, mImportFilename);
}
intent.putExtra(ApgService.EXTRA_DATA, data);
// Message is received after importing is done in ApgService
ApgServiceHandler saveHandler = new ApgServiceHandler(this, R.string.progress_importing,
ProgressDialog.STYLE_HORIZONTAL) {
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);
if (message.arg1 == ApgServiceHandler.MESSAGE_OKAY) {
// get returned data bundle
Bundle returnData = message.getData();
int added = returnData.getInt(ApgService.RESULT_IMPORT_ADDED);
int updated = returnData.getInt(ApgService.RESULT_IMPORT_UPDATED);
int bad = returnData.getInt(ApgService.RESULT_IMPORT_BAD);
String toastMessage;
if (added > 0 && updated > 0) {
toastMessage = getString(R.string.keysAddedAndUpdated, added, updated);
} else if (added > 0) {
toastMessage = getString(R.string.keysAdded, added);
} else if (updated > 0) {
toastMessage = getString(R.string.keysUpdated, updated);
} else {
toastMessage = getString(R.string.noKeysAddedOrUpdated);
}
Toast.makeText(KeyListActivityOld.this, toastMessage, Toast.LENGTH_SHORT).show();
if (bad > 0) {
AlertDialog.Builder alert = new AlertDialog.Builder(KeyListActivityOld.this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning);
alert.setMessage(KeyListActivityOld.this.getString(
R.string.badKeysEncountered, bad));
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
alert.setCancelable(true);
alert.create().show();
} else if (mDeleteAfterImport) {
// everything went well, so now delete, if that was turned on
DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment
.newInstance(mImportFilename);
deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog");
}
refreshList();
}
};
};
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(saveHandler);
intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
// show progress dialog
saveHandler.showProgressDialog(this);
// start service with intent
startService(intent);
}
public void exportKeys() {
Log.d(Constants.TAG, "exportKeys started");
// Send all information needed to service to export key in other thread
Intent intent = new Intent(this, ApgService.class);
intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_EXPORT_KEY);
// fill values for this action
Bundle data = new Bundle();
data.putString(ApgService.EXPORT_FILENAME, mExportFilename);
data.putInt(ApgService.EXPORT_KEY_TYPE, mKeyType);
if (mSelectedItem == -1) {
data.putBoolean(ApgService.EXPORT_ALL, true);
} else {
int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
data.putInt(ApgService.EXPORT_KEY_RING_ID, keyRingId);
mSelectedItem = -1;
}
intent.putExtra(ApgService.EXTRA_DATA, data);
// Message is received after exporting is done in ApgService
ApgServiceHandler exportHandler = new ApgServiceHandler(this, R.string.progress_exporting,
ProgressDialog.STYLE_HORIZONTAL) {
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);
if (message.arg1 == ApgServiceHandler.MESSAGE_OKAY) {
// get returned data bundle
Bundle returnData = message.getData();
int exported = returnData.getInt(ApgService.RESULT_EXPORT);
String toastMessage;
if (exported == 1) {
toastMessage = getString(R.string.keyExported);
} else if (exported > 0) {
toastMessage = getString(R.string.keysExported, exported);
} else {
toastMessage = getString(R.string.noKeysExported);
}
Toast.makeText(KeyListActivityOld.this, toastMessage, Toast.LENGTH_SHORT).show();
}
};
};
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(exportHandler);
intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
// show progress dialog
exportHandler.showProgressDialog(this);
// start service with intent
startService(intent);
}
protected void refreshList() {
mListAdapter.rebuild(true);
mListAdapter.notifyDataSetChanged();
}
protected class KeyListAdapter extends BaseExpandableListAdapter {
private LayoutInflater mInflater;
private Vector<Vector<KeyChild>> mChildren;
private SQLiteDatabase mDatabase;
private Cursor mCursor;
private String mSearchString;
private class KeyChild {
public static final int KEY = 0;
public static final int USER_ID = 1;
public static final int FINGER_PRINT = 2;
public int type;
public String userId;
public long keyId;
public boolean isMasterKey;
public int algorithm;
public int keySize;
public boolean canSign;
public boolean canEncrypt;
public String fingerPrint;
public KeyChild(long keyId, boolean isMasterKey, int algorithm, int keySize,
boolean canSign, boolean canEncrypt) {
this.type = KEY;
this.keyId = keyId;
this.isMasterKey = isMasterKey;
this.algorithm = algorithm;
this.keySize = keySize;
this.canSign = canSign;
this.canEncrypt = canEncrypt;
}
public KeyChild(String userId) {
type = USER_ID;
this.userId = userId;
}
public KeyChild(String fingerPrint, boolean isFingerPrint) {
type = FINGER_PRINT;
this.fingerPrint = fingerPrint;
}
}
public KeyListAdapter(Context context, String searchString) {
mSearchString = searchString;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// mDatabase = PGPMain.getDatabase().db();
// SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
// qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
// + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
// + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
// + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
// + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
// + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK
// + " = '0')");
//
// if (searchString != null && searchString.trim().length() > 0) {
// String[] chunks = searchString.trim().split(" +");
// qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " + UserIds.TABLE_NAME
// + " AS tmp WHERE " + "tmp." + UserIds.KEY_ID + " = " + Keys.TABLE_NAME
// + "." + Keys._ID);
// for (int i = 0; i < chunks.length; ++i) {
// qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE ");
// qb.appendWhereEscapeString("%" + chunks[i] + "%");
// }
// qb.appendWhere(")");
// }
//
// mCursor = qb.query(mDatabase, new String[] { KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0
// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1
// UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2
// }, KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", new String[] { ""
// + (mKeyType == Id.type.public_key ? Id.database.type_public
// : Id.database.type_secret) }, null, null, UserIds.TABLE_NAME + "."
// + UserIds.USER_ID + " ASC");
// content provider way for reference, might have to go back to it sometime:
/*
* Uri contentUri = null; if (mKeyType == Id.type.secret_key) { contentUri =
* Apg.CONTENT_URI_SECRET_KEY_RINGS; } else { contentUri =
* Apg.CONTENT_URI_PUBLIC_KEY_RINGS; } mCursor = getContentResolver().query( contentUri,
* new String[] { DataProvider._ID, // 0 DataProvider.MASTER_KEY_ID, // 1
* DataProvider.USER_ID, // 2 }, null, null, null);
*/
startManagingCursor(mCursor);
rebuild(false);
}
public void cleanup() {
if (mCursor != null) {
stopManagingCursor(mCursor);
mCursor.close();
}
}
public void rebuild(boolean requery) {
if (requery) {
mCursor.requery();
}
mChildren = new Vector<Vector<KeyChild>>();
for (int i = 0; i < mCursor.getCount(); ++i) {
mChildren.add(null);
}
}
protected Vector<KeyChild> getChildrenOfGroup(int groupPosition) {
Vector<KeyChild> children = mChildren.get(groupPosition);
if (children != null) {
return children;
}
mCursor.moveToPosition(groupPosition);
children = new Vector<KeyChild>();
// Cursor c = mDatabase.query(Keys.TABLE_NAME, new String[] { Keys._ID, // 0
// Keys.KEY_ID, // 1
// Keys.IS_MASTER_KEY, // 2
// Keys.ALGORITHM, // 3
// Keys.KEY_SIZE, // 4
// Keys.CAN_SIGN, // 5
// Keys.CAN_ENCRYPT, // 6
// }, Keys.KEY_RING_ID + " = ?", new String[] { mCursor.getString(0) }, null, null,
// Keys.RANK + " ASC");
// int masterKeyId = -1;
// long fingerPrintId = -1;
// for (int i = 0; i < c.getCount(); ++i) {
// c.moveToPosition(i);
// children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4),
// c.getInt(5) == 1, c.getInt(6) == 1));
// if (i == 0) {
// masterKeyId = c.getInt(0);
// fingerPrintId = c.getLong(1);
// }
// }
// c.close();
//
// if (masterKeyId != -1) {
// children.insertElementAt(
// new KeyChild(PGPHelper.getFingerPrint(KeyListActivity.this, fingerPrintId),
// true), 0);
// c = mDatabase.query(UserIds.TABLE_NAME, new String[] { UserIds.USER_ID, // 0
// }, UserIds.KEY_ID + " = ? AND " + UserIds.RANK + " > 0", new String[] { ""
// + masterKeyId }, null, null, UserIds.RANK + " ASC");
//
// for (int i = 0; i < c.getCount(); ++i) {
// c.moveToPosition(i);
// children.add(new KeyChild(c.getString(0)));
// }
// c.close();
// }
mChildren.set(groupPosition, children);
return children;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public int getGroupCount() {
return mCursor.getCount();
}
public Object getChild(int groupPosition, int childPosition) {
return null;
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public int getChildrenCount(int groupPosition) {
return getChildrenOfGroup(groupPosition).size();
}
public Object getGroup(int position) {
return position;
}
public long getGroupId(int position) {
mCursor.moveToPosition(position);
return mCursor.getLong(1); // MASTER_KEY_ID
}
public int getKeyRingId(int position) {
mCursor.moveToPosition(position);
return mCursor.getInt(0); // _ID
}
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
mCursor.moveToPosition(groupPosition);
View view = mInflater.inflate(R.layout.key_list_group_item, null);
view.setBackgroundResource(android.R.drawable.list_selector_background);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText("");
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = mCursor.getString(2); // USER_ID
if (userId != null) {
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]);
}
mainUserId.setText(userId);
}
if (mainUserId.getText().length() == 0) {
mainUserId.setText(R.string.unknownUserId);
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
return view;
}
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
mCursor.moveToPosition(groupPosition);
Vector<KeyChild> children = getChildrenOfGroup(groupPosition);
KeyChild child = children.get(childPosition);
View view = null;
switch (child.type) {
case KeyChild.KEY: {
if (child.isMasterKey) {
view = mInflater.inflate(R.layout.key_list_child_item_master_key, null);
} else {
view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null);
}
TextView keyId = (TextView) view.findViewById(R.id.keyId);
String keyIdStr = PGPHelper.getSmallFingerPrint(child.keyId);
keyId.setText(keyIdStr);
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
String algorithmStr = PGPHelper.getAlgorithmInfo(child.algorithm, child.keySize);
keyDetails.setText("(" + algorithmStr + ")");
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (!child.canEncrypt) {
encryptIcon.setVisibility(View.GONE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (!child.canSign) {
signIcon.setVisibility(View.GONE);
}
break;
}
case KeyChild.USER_ID: {
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(child.userId);
break;
}
case KeyChild.FINGER_PRINT: {
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(getString(R.string.fingerprint) + ":\n"
+ child.fingerPrint.replace(" ", "\n"));
break;
}
}
return view;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) {
try {
String path = data.getData().getPath();
Log.d(Constants.TAG, "path=" + path);
mFileDialog.setFilename(path);
} catch (NullPointerException e) {
Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
}
}
return;
}
default: {
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}

View File

@ -1,19 +1,3 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui; package org.thialfihar.android.apg.ui;
import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPPublicKeyRing;
@ -21,9 +5,10 @@ import org.thialfihar.android.apg.Constants;
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.helper.PGPHelper; import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.provider.ProviderHelper; import org.thialfihar.android.apg.provider.ProviderHelper;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.MenuItem;
@ -35,12 +20,16 @@ import android.view.View;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
public class PublicKeyListActivity extends KeyListActivity { public class KeyListPublicActivity extends KeyListActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.key_list_public_activity);
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);
} }
@Override @Override
@ -116,7 +105,8 @@ public class PublicKeyListActivity extends KeyListActivity {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
final int keyRingId = mListAdapter.getKeyRingId(groupPosition); final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
long keyId = 0; long keyId = 0;
PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, keyRingId); PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this,
keyRingId);
if (keyRing != null) { if (keyRing != null) {
keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID(); keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
} }
@ -149,7 +139,8 @@ public class PublicKeyListActivity extends KeyListActivity {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
final int keyRingId = mListAdapter.getKeyRingId(groupPosition); final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
long keyId = 0; long keyId = 0;
PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, keyRingId); PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this,
keyRingId);
if (keyRing != null) { if (keyRing != null) {
keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID(); keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
} }
@ -181,10 +172,10 @@ public class PublicKeyListActivity extends KeyListActivity {
return; return;
} }
Intent intent = new Intent(this, PublicKeyListActivity.class); Intent intent = new Intent(this, KeyListPublicActivity.class);
intent.setAction(PublicKeyListActivity.ACTION_IMPORT); intent.setAction(KeyListPublicActivity.ACTION_IMPORT);
intent.putExtra(PublicKeyListActivity.EXTRA_TEXT, intent.putExtra(KeyListPublicActivity.EXTRA_TEXT,
data.getStringExtra(KeyListActivity.EXTRA_TEXT)); data.getStringExtra(KeyListActivityOld.EXTRA_TEXT));
handleIntent(intent); handleIntent(intent);
break; break;
} }

View File

@ -0,0 +1,198 @@
///*
// * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package org.thialfihar.android.apg.ui;
//
//import org.spongycastle.openpgp.PGPPublicKeyRing;
//import org.thialfihar.android.apg.Constants;
//import org.thialfihar.android.apg.Id;
//import org.thialfihar.android.apg.R;
//import org.thialfihar.android.apg.helper.PGPHelper;
//import org.thialfihar.android.apg.helper.PGPMain;
//import org.thialfihar.android.apg.provider.ProviderHelper;
//
//import com.actionbarsherlock.view.Menu;
//import com.actionbarsherlock.view.MenuItem;
//
//import android.content.Intent;
//import android.os.Bundle;
//import android.view.ContextMenu;
//import android.view.ContextMenu.ContextMenuInfo;
//import android.view.View;
//import android.widget.ExpandableListView;
//import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
//
//public class KeyListPublicActivityOld extends KeyListActivityOld {
// @Override
// public void onCreate(Bundle savedInstanceState) {
// mExportFilename = Constants.path.APP_DIR + "/pubexport.asc";
// mKeyType = Id.type.public_key;
// super.onCreate(savedInstanceState);
// }
//
// @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// menu.add(1, Id.menu.option.search, 0, R.string.menu_search)
// .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
// menu.add(1, Id.menu.option.scanQRCode, 1, R.string.menu_scanQRCode)
// .setIcon(R.drawable.ic_menu_scan_qrcode)
// .setShowAsAction(
// MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// menu.add(1, Id.menu.option.key_server, 2, R.string.menu_keyServer)
// .setIcon(R.drawable.ic_menu_search_list)
// .setShowAsAction(
// MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// menu.add(0, Id.menu.option.import_keys, 3, R.string.menu_importKeys).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// menu.add(0, Id.menu.option.export_keys, 4, R.string.menu_exportKeys).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
//
// return true;
// }
//
// @Override
// public boolean onOptionsItemSelected(MenuItem item) {
// switch (item.getItemId()) {
// case Id.menu.option.key_server: {
// startActivity(new Intent(this, KeyServerQueryActivity.class));
//
// return true;
// }
// case Id.menu.option.scanQRCode: {
// Intent intent = new Intent(this, ImportFromQRCodeActivity.class);
// intent.setAction(ImportFromQRCodeActivity.IMPORT_FROM_QR_CODE);
// startActivityForResult(intent, Id.request.import_from_qr_code);
//
// return true;
// }
//
// default: {
// return super.onOptionsItemSelected(item);
// }
// }
// }
//
// @Override
// public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
// super.onCreateContextMenu(menu, v, menuInfo);
// ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
// int type = ExpandableListView.getPackedPositionType(info.packedPosition);
//
// if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// // TODO: user id? menu.setHeaderTitle("Key");
// 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.update, 1, R.string.menu_updateKey);
// menu.add(0, Id.menu.exportToServer, 1, R.string.menu_exportKeyToServer);
// menu.add(0, Id.menu.signKey, 1, R.string.menu_signKey);
// }
// }
//
// @Override
// public boolean onContextItemSelected(android.view.MenuItem menuItem) {
// ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
// int type = ExpandableListView.getPackedPositionType(info.packedPosition);
// int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
//
// if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// return super.onContextItemSelected(menuItem);
// }
//
// switch (menuItem.getItemId()) {
// case Id.menu.update: {
// mSelectedItem = groupPosition;
// final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
// long keyId = 0;
// PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, keyRingId);
// if (keyRing != null) {
// keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
// }
// if (keyId == 0) {
// // this shouldn't happen
// return true;
// }
//
// Intent intent = new Intent(this, KeyServerQueryActivity.class);
// intent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID_AND_RETURN);
// intent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, keyId);
// startActivityForResult(intent, Id.request.look_up_key_id);
//
// return true;
// }
//
// case Id.menu.exportToServer: {
// mSelectedItem = groupPosition;
// final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
//
// Intent intent = new Intent(this, KeyServerUploadActivity.class);
// intent.setAction(KeyServerUploadActivity.ACTION_EXPORT_KEY_TO_SERVER);
// intent.putExtra(KeyServerUploadActivity.EXTRA_KEY_ID, keyRingId);
// startActivityForResult(intent, Id.request.export_to_server);
//
// return true;
// }
//
// case Id.menu.signKey: {
// mSelectedItem = groupPosition;
// final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
// long keyId = 0;
// PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, keyRingId);
// if (keyRing != null) {
// keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
// }
//
// if (keyId == 0) {
// // this shouldn't happen
// return true;
// }
//
// Intent intent = new Intent(this, SignKeyActivity.class);
// intent.putExtra(SignKeyActivity.EXTRA_KEY_ID, keyId);
// startActivity(intent);
//
// return true;
// }
//
// default: {
// return super.onContextItemSelected(menuItem);
// }
// }
// }
//
// @Override
// protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// switch (requestCode) {
// case Id.request.look_up_key_id: {
// if (resultCode == RESULT_CANCELED || data == null
// || data.getStringExtra(KeyServerQueryActivity.RESULT_EXTRA_TEXT) == null) {
// return;
// }
//
// Intent intent = new Intent(this, KeyListPublicActivity.class);
// intent.setAction(KeyListPublicActivity.ACTION_IMPORT);
// intent.putExtra(KeyListPublicActivity.EXTRA_TEXT,
// data.getStringExtra(KeyListActivityOld.EXTRA_TEXT));
// handleIntent(intent);
// break;
// }
//
// default: {
// super.onActivityResult(requestCode, resultCode, data);
// break;
// }
// }
// }
//}

View File

@ -0,0 +1,100 @@
package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.R.id;
import org.thialfihar.android.apg.provider.ApgContract.PublicKeyRings;
import org.thialfihar.android.apg.provider.ApgContract.PublicKeys;
import org.thialfihar.android.apg.provider.ApgContract.PublicUserIds;
import org.thialfihar.android.apg.ui.widget.ExpandableListFragment;
import org.thialfihar.android.apg.ui.widget.KeyListAdapter;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.SherlockListFragment;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
public class KeyListPublicFragment extends ExpandableListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
private FragmentActivity mActivity;
private KeyListAdapter mAdapter;
// private long mCurrentRowId;
/**
* Define Adapter and Loader on create of Activity
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mActivity = getActivity();
// register long press context menu
registerForContextMenu(getListView());
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("TODO empty");
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
mAdapter = new KeyListAdapter(mActivity, getLoaderManager(), null, Id.type.public_key);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(-1, null, this);
}
// These are the rows that we will retrieve.
static final String[] PROJECTION = new String[] { PublicKeyRings._ID,
PublicKeyRings.MASTER_KEY_ID, PublicUserIds.USER_ID };
static final String SORT_ORDER = PublicUserIds.USER_ID + " ASC";
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
Uri baseUri = PublicKeyRings.buildPublicKeyRingsUri();
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null, SORT_ORDER);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.setGroupCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.setGroupCursor(null);
}
}

View File

@ -1,32 +1,20 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui; package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.PGPHelper; import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.service.PassphraseCacheService; import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment; import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
import org.thialfihar.android.apg.ui.widget.KeyListAdapter;
import org.thialfihar.android.apg.util.Log; import org.thialfihar.android.apg.util.Log;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.MenuItem;
import com.google.zxing.integration.android.IntentIntegrator;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@ -38,18 +26,18 @@ import android.view.ContextMenu.ContextMenuInfo;
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 com.google.zxing.integration.android.IntentIntegrator; public class KeyListSecretActivity extends KeyListActivity {
public class SecretKeyListActivity extends KeyListActivity implements OnChildClickListener {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.key_list_secret_activity);
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);
mList.setOnChildClickListener(this);
} }
@Override @Override
@ -154,7 +142,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
public void handleMessage(Message message) { public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
String passPhrase = PassphraseCacheService.getCachedPassphrase( String passPhrase = PassphraseCacheService.getCachedPassphrase(
SecretKeyListActivity.this, secretKeyId); KeyListSecretActivity.this, secretKeyId);
PGPMain.setEditPassPhrase(passPhrase); PGPMain.setEditPassPhrase(passPhrase);
editKey(); editKey();
} }
@ -166,7 +154,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
try { try {
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance( PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
SecretKeyListActivity.this, messenger, secretKeyId); KeyListSecretActivity.this, messenger, secretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (PGPMain.ApgGeneralException e) { } catch (PGPMain.ApgGeneralException e) {
@ -195,7 +183,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
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;
} }
@ -207,4 +195,5 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
} }

View File

@ -0,0 +1,210 @@
///*
// * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package org.thialfihar.android.apg.ui;
//
//import org.thialfihar.android.apg.R;
//import org.thialfihar.android.apg.Constants;
//import org.thialfihar.android.apg.Id;
//import org.thialfihar.android.apg.helper.PGPHelper;
//import org.thialfihar.android.apg.helper.PGPMain;
//import org.thialfihar.android.apg.service.PassphraseCacheService;
//import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
//import org.thialfihar.android.apg.util.Log;
//
//import com.actionbarsherlock.view.Menu;
//import com.actionbarsherlock.view.MenuItem;
//
//import android.content.Intent;
//import android.os.Bundle;
//import android.os.Handler;
//import android.os.Message;
//import android.os.Messenger;
//import android.view.ContextMenu;
//import android.view.ContextMenu.ContextMenuInfo;
//import android.view.View;
//import android.widget.ExpandableListView;
//import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
//import android.widget.ExpandableListView.OnChildClickListener;
//
//import com.google.zxing.integration.android.IntentIntegrator;
//
//public class KeyListSecretActivityOld extends KeyListActivityOld implements OnChildClickListener {
//
// @Override
// public void onCreate(Bundle savedInstanceState) {
// mExportFilename = Constants.path.APP_DIR + "/secexport.asc";
// mKeyType = Id.type.secret_key;
// super.onCreate(savedInstanceState);
// mList.setOnChildClickListener(this);
// }
//
// @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// menu.add(3, Id.menu.option.search, 0, R.string.menu_search)
// .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
// menu.add(1, Id.menu.option.create, 1, R.string.menu_createKey).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// menu.add(0, Id.menu.option.import_keys, 2, R.string.menu_importKeys).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// menu.add(0, Id.menu.option.export_keys, 3, R.string.menu_exportKeys).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
//
// return true;
// }
//
// @Override
// public boolean onOptionsItemSelected(MenuItem item) {
// switch (item.getItemId()) {
// case Id.menu.option.create: {
// createKey();
// return true;
// }
//
// default: {
// return super.onOptionsItemSelected(item);
// }
// }
// }
//
// @Override
// public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
// super.onCreateContextMenu(menu, v, menuInfo);
// ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
// int type = ExpandableListView.getPackedPositionType(info.packedPosition);
//
// if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// // TODO: user id? menu.setHeaderTitle("Key");
// 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.delete, 2, R.string.menu_deleteKey);
// menu.add(0, Id.menu.share_qr_code, 2, R.string.menu_share);
// }
// }
//
// @Override
// public boolean onContextItemSelected(android.view.MenuItem menuItem) {
// ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo();
// int type = ExpandableListView.getPackedPositionType(info.packedPosition);
// int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
//
// if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// return super.onContextItemSelected(menuItem);
// }
//
// switch (menuItem.getItemId()) {
// case Id.menu.edit: {
// mSelectedItem = groupPosition;
// checkPassPhraseAndEdit();
// return true;
// }
//
// case Id.menu.share_qr_code: {
// mSelectedItem = groupPosition;
//
// long keyId = ((KeyListAdapter) mList.getExpandableListAdapter())
// .getGroupId(mSelectedItem);
// // String msg = keyId + "," + PGPHelper.getFingerPrint(keyId);
// String msg = PGPHelper.getPubkeyAsArmoredString(this, keyId);
//
// new IntentIntegrator(this).shareText(msg);
// }
//
// default: {
// return super.onContextItemSelected(menuItem);
// }
// }
// }
//
// public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
// int childPosition, long id) {
// mSelectedItem = groupPosition;
// checkPassPhraseAndEdit();
// return true;
// }
//
// public void checkPassPhraseAndEdit() {
// long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
// String passPhrase = PassphraseCacheService.getCachedPassphrase(this, keyId);
// if (passPhrase == null) {
// showPassphraseDialog(keyId);
// } else {
// PGPMain.setEditPassPhrase(passPhrase);
// editKey();
// }
// }
//
// private void showPassphraseDialog(final long secretKeyId) {
// // Message is received after passphrase is cached
// Handler returnHandler = new Handler() {
// @Override
// public void handleMessage(Message message) {
// if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
// String passPhrase = PassphraseCacheService.getCachedPassphrase(
// KeyListSecretActivity.this, secretKeyId);
// PGPMain.setEditPassPhrase(passPhrase);
// editKey();
// }
// }
// };
//
// // Create a new Messenger for the communication back
// Messenger messenger = new Messenger(returnHandler);
//
// try {
// PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
// KeyListSecretActivity.this, messenger, secretKeyId);
//
// passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
// } catch (PGPMain.ApgGeneralException e) {
// Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
// // send message to handler to start encryption directly
// returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
// }
// }
//
// private void createKey() {
// PGPMain.setEditPassPhrase("");
// Intent intent = new Intent(EditKeyActivity.ACTION_CREATE_KEY);
// startActivityForResult(intent, Id.message.create_key);
// }
//
// private void editKey() {
// long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
// Intent intent = new Intent(EditKeyActivity.ACTION_EDIT_KEY);
// intent.putExtra(EditKeyActivity.EXTRA_KEY_ID, keyId);
// startActivityForResult(intent, Id.message.edit_key);
// }
//
// @Override
// protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// switch (requestCode) {
// case Id.message.create_key: // intentionally no break
// case Id.message.edit_key: {
// if (resultCode == RESULT_OK) {
// refreshList();
// }
// break;
// }
//
// default: {
// break;
// }
// }
//
// super.onActivityResult(requestCode, resultCode, data);
// }
//}

View File

@ -0,0 +1,94 @@
package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.provider.ApgContract.SecretKeyRings;
import org.thialfihar.android.apg.provider.ApgContract.SecretUserIds;
import org.thialfihar.android.apg.ui.widget.ExpandableListFragment;
import org.thialfihar.android.apg.ui.widget.KeyListAdapter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
public class KeyListSecretFragment extends ExpandableListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
private FragmentActivity mActivity;
private KeyListAdapter mAdapter;
// private long mCurrentRowId;
/**
* Define Adapter and Loader on create of Activity
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mActivity = getActivity();
// register long press context menu
registerForContextMenu(getListView());
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("TODO empty");
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
mAdapter = new KeyListAdapter(mActivity, getLoaderManager(), null, Id.type.secret_key);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(-1, null, this);
}
// These are the rows that we will retrieve.
static final String[] PROJECTION = new String[] { SecretKeyRings._ID,
SecretKeyRings.MASTER_KEY_ID, SecretUserIds.USER_ID };
static final String SORT_ORDER = SecretUserIds.USER_ID + " ASC";
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
Uri baseUri = SecretKeyRings.buildSecretKeyRingsUri();
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null, SORT_ORDER);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.setGroupCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.setGroupCursor(null);
}
}

View File

@ -83,7 +83,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
case android.R.id.home: case android.R.id.home:
// app icon in Action Bar clicked; go home // app icon in Action Bar clicked; go home
Intent intent = new Intent(this, PublicKeyListActivity.class); Intent intent = new Intent(this, KeyListPublicActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent); startActivity(intent);
return true; return true;
@ -223,9 +223,9 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
} else { } else {
if (mKeyData != null) { if (mKeyData != null) {
Intent intent = new Intent(KeyServerQueryActivity.this, Intent intent = new Intent(KeyServerQueryActivity.this,
PublicKeyListActivity.class); KeyListPublicActivity.class);
intent.setAction(KeyListActivity.ACTION_IMPORT); intent.setAction(KeyListActivityOld.ACTION_IMPORT);
intent.putExtra(KeyListActivity.EXTRA_TEXT, mKeyData); intent.putExtra(KeyListActivityOld.EXTRA_TEXT, mKeyData);
startActivity(intent); startActivity(intent);
} }
} }

View File

@ -60,7 +60,7 @@ public class KeyServerUploadActivity extends SherlockFragmentActivity {
case android.R.id.home: case android.R.id.home:
// app icon in Action Bar clicked; go home // app icon in Action Bar clicked; go home
Intent intent = new Intent(this, PublicKeyListActivity.class); Intent intent = new Intent(this, KeyListPublicActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent); startActivity(intent);
return true; return true;

View File

@ -33,12 +33,12 @@ public class MainActivity extends SherlockActivity {
public void manageKeysOnClick(View view) { public void manageKeysOnClick(View view) {
// used instead of startActivity set actionbar based on callingPackage // used instead of startActivity set actionbar based on callingPackage
startActivityForResult(new Intent(this, PublicKeyListActivity.class), 0); startActivityForResult(new Intent(this, KeyListPublicActivity.class), 0);
} }
public void myKeysOnClick(View view) { public void myKeysOnClick(View view) {
// used instead of startActivity set actionbar based on callingPackage // used instead of startActivity set actionbar based on callingPackage
startActivityForResult(new Intent(this, SecretKeyListActivity.class), 0); startActivityForResult(new Intent(this, KeyListSecretActivity.class), 0);
} }
public void encryptOnClick(View view) { public void encryptOnClick(View view) {

View File

@ -1,198 +1,47 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui; package org.thialfihar.android.apg.ui;
import java.util.Vector;
import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.ui.widget.SelectPublicKeyListAdapter;
import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.MenuItem;
import android.app.SearchManager;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
public class SelectPublicKeyListActivity extends SherlockFragmentActivity { public class SelectPublicKeyListActivity extends SherlockFragmentActivity {
private ActionBar mActionBar;
// Not used in sourcode, but listed in AndroidManifest! // TODO
public static final String ACTION_SELECT_PUBLIC_KEYS = Constants.INTENT_PREFIX
+ "SELECT_PUBLIC_KEYS";
public static final String RESULT_EXTRA_SELECTION = "selection"; public static final String RESULT_EXTRA_SELECTION = "selection";
public static final String RESULT_EXTRA_USER_IDS = "userIds"; public static final String RESULT_EXTRA_USER_IDS = "userIds";
protected ListView mList;
protected SelectPublicKeyListAdapter mListAdapter;
protected View mFilterLayout;
protected Button mClearFilterButton;
protected TextView mFilterInfo;
@Override @Override
public void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final ActionBar actionBar = getSupportActionBar(); mActionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setHomeButtonEnabled(false);
setContentView(R.layout.select_public_key); setContentView(R.layout.select_public_key_activity);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); mActionBar.setDisplayShowTitleEnabled(true);
mActionBar.setDisplayHomeAsUpEnabled(true);
mList = (ListView) findViewById(R.id.list);
// needed in Android 1.5, where the XML attribute gets ignored
mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mFilterLayout = findViewById(R.id.layout_filter);
mFilterInfo = (TextView) mFilterLayout.findViewById(R.id.filterInfo);
mClearFilterButton = (Button) mFilterLayout.findViewById(R.id.btn_clear);
mClearFilterButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
handleIntent(new Intent());
}
});
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
String searchString = null;
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
searchString = intent.getStringExtra(SearchManager.QUERY);
if (searchString != null && searchString.trim().length() == 0) {
searchString = null;
}
}
long selectedKeyIds[] = null;
selectedKeyIds = intent.getLongArrayExtra(RESULT_EXTRA_SELECTION);
if (selectedKeyIds == null) {
Vector<Long> vector = new Vector<Long>();
for (int i = 0; i < mList.getCount(); ++i) {
if (mList.isItemChecked(i)) {
vector.add(mList.getItemIdAtPosition(i));
}
}
selectedKeyIds = new long[vector.size()];
for (int i = 0; i < vector.size(); ++i) {
selectedKeyIds[i] = vector.get(i);
}
}
if (searchString == null) {
mFilterLayout.setVisibility(View.GONE);
} else {
mFilterLayout.setVisibility(View.VISIBLE);
mFilterInfo.setText(getString(R.string.filterInfo, searchString));
}
if (mListAdapter != null) {
mListAdapter.cleanup();
}
mListAdapter = new SelectPublicKeyListAdapter(this, mList, searchString, selectedKeyIds);
mList.setAdapter(mListAdapter);
if (selectedKeyIds != null) {
for (int i = 0; i < mListAdapter.getCount(); ++i) {
long keyId = mListAdapter.getItemId(i);
for (int j = 0; j < selectedKeyIds.length; ++j) {
if (keyId == selectedKeyIds[j]) {
mList.setItemChecked(i, true);
break;
}
}
}
}
}
private void cancelClicked() {
setResult(RESULT_CANCELED, null);
finish();
}
private void okClicked() {
Intent data = new Intent();
Vector<Long> keys = new Vector<Long>();
Vector<String> userIds = new Vector<String>();
for (int i = 0; i < mList.getCount(); ++i) {
if (mList.isItemChecked(i)) {
keys.add(mList.getItemIdAtPosition(i));
userIds.add((String) mList.getItemAtPosition(i));
}
}
long selectedKeyIds[] = new long[keys.size()];
for (int i = 0; i < keys.size(); ++i) {
selectedKeyIds[i] = keys.get(i);
}
String userIdArray[] = new String[0];
data.putExtra(RESULT_EXTRA_SELECTION, selectedKeyIds);
data.putExtra(RESULT_EXTRA_USER_IDS, userIds.toArray(userIdArray));
setResult(RESULT_OK, data);
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.search, 0, R.string.menu_search).setIcon(
android.R.drawable.ic_menu_search);
menu.add(1, Id.menu.option.cancel, 0, R.string.btn_doNotSave).setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(1, Id.menu.option.okay, 1, R.string.btn_okay).setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
} }
/**
* Menu Options
*/
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case android.R.id.home:
case Id.menu.option.okay: // app icon in Action Bar clicked; go home
okClicked(); Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true; return true;
case Id.menu.option.cancel:
cancelClicked();
return true;
default: default:
break; return super.onOptionsItemSelected(item);
} }
return false;
} }
} }

View File

@ -0,0 +1,198 @@
///*
// * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package org.thialfihar.android.apg.ui;
//
//import java.util.Vector;
//
//import org.thialfihar.android.apg.Constants;
//import org.thialfihar.android.apg.R;
//import org.thialfihar.android.apg.Id;
//import org.thialfihar.android.apg.ui.widget.SelectPublicKeyListAdapter;
//
//import com.actionbarsherlock.app.ActionBar;
//import com.actionbarsherlock.app.SherlockFragmentActivity;
//import com.actionbarsherlock.view.Menu;
//import com.actionbarsherlock.view.MenuItem;
//
//import android.app.SearchManager;
//import android.content.Intent;
//import android.os.Bundle;
//import android.view.View;
//import android.view.View.OnClickListener;
//import android.widget.Button;
//import android.widget.ListView;
//import android.widget.TextView;
//
//public class SelectPublicKeyListActivityOld extends SherlockFragmentActivity {
//
// // Not used in sourcode, but listed in AndroidManifest!
// public static final String ACTION_SELECT_PUBLIC_KEYS = Constants.INTENT_PREFIX
// + "SELECT_PUBLIC_KEYS";
//
// public static final String RESULT_EXTRA_SELECTION = "selection";
// public static final String RESULT_EXTRA_USER_IDS = "userIds";
//
// protected ListView mList;
// protected SelectPublicKeyListAdapter mListAdapter;
// protected View mFilterLayout;
// protected Button mClearFilterButton;
// protected TextView mFilterInfo;
//
// @Override
// public void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
//
// final ActionBar actionBar = getSupportActionBar();
// actionBar.setDisplayShowTitleEnabled(true);
// actionBar.setDisplayHomeAsUpEnabled(false);
// actionBar.setHomeButtonEnabled(false);
//
// setContentView(R.layout.select_public_key);
//
// setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
//
// mList = (ListView) findViewById(R.id.list);
// // needed in Android 1.5, where the XML attribute gets ignored
// mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
//
// mFilterLayout = findViewById(R.id.layout_filter);
// mFilterInfo = (TextView) mFilterLayout.findViewById(R.id.filterInfo);
// mClearFilterButton = (Button) mFilterLayout.findViewById(R.id.btn_clear);
//
// mClearFilterButton.setOnClickListener(new OnClickListener() {
// public void onClick(View v) {
// handleIntent(new Intent());
// }
// });
//
// handleIntent(getIntent());
// }
//
// @Override
// protected void onNewIntent(Intent intent) {
// super.onNewIntent(intent);
// handleIntent(intent);
// }
//
// private void handleIntent(Intent intent) {
// String searchString = null;
// if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// searchString = intent.getStringExtra(SearchManager.QUERY);
// if (searchString != null && searchString.trim().length() == 0) {
// searchString = null;
// }
// }
//
// long selectedKeyIds[] = null;
// selectedKeyIds = intent.getLongArrayExtra(RESULT_EXTRA_SELECTION);
//
// if (selectedKeyIds == null) {
// Vector<Long> vector = new Vector<Long>();
// for (int i = 0; i < mList.getCount(); ++i) {
// if (mList.isItemChecked(i)) {
// vector.add(mList.getItemIdAtPosition(i));
// }
// }
// selectedKeyIds = new long[vector.size()];
// for (int i = 0; i < vector.size(); ++i) {
// selectedKeyIds[i] = vector.get(i);
// }
// }
//
// if (searchString == null) {
// mFilterLayout.setVisibility(View.GONE);
// } else {
// mFilterLayout.setVisibility(View.VISIBLE);
// mFilterInfo.setText(getString(R.string.filterInfo, searchString));
// }
//
// if (mListAdapter != null) {
// mListAdapter.cleanup();
// }
//
// mListAdapter = new SelectPublicKeyListAdapter(this, mList, searchString, selectedKeyIds);
// mList.setAdapter(mListAdapter);
//
// if (selectedKeyIds != null) {
// for (int i = 0; i < mListAdapter.getCount(); ++i) {
// long keyId = mListAdapter.getItemId(i);
// for (int j = 0; j < selectedKeyIds.length; ++j) {
// if (keyId == selectedKeyIds[j]) {
// mList.setItemChecked(i, true);
// break;
// }
// }
// }
// }
// }
//
// private void cancelClicked() {
// setResult(RESULT_CANCELED, null);
// finish();
// }
//
// private void okClicked() {
// Intent data = new Intent();
// Vector<Long> keys = new Vector<Long>();
// Vector<String> userIds = new Vector<String>();
// for (int i = 0; i < mList.getCount(); ++i) {
// if (mList.isItemChecked(i)) {
// keys.add(mList.getItemIdAtPosition(i));
// userIds.add((String) mList.getItemAtPosition(i));
// }
// }
// long selectedKeyIds[] = new long[keys.size()];
// for (int i = 0; i < keys.size(); ++i) {
// selectedKeyIds[i] = keys.get(i);
// }
// String userIdArray[] = new String[0];
// data.putExtra(RESULT_EXTRA_SELECTION, selectedKeyIds);
// data.putExtra(RESULT_EXTRA_USER_IDS, userIds.toArray(userIdArray));
// setResult(RESULT_OK, data);
// finish();
// }
//
// @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// menu.add(0, Id.menu.option.search, 0, R.string.menu_search).setIcon(
// android.R.drawable.ic_menu_search);
// menu.add(1, Id.menu.option.cancel, 0, R.string.btn_doNotSave).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// menu.add(1, Id.menu.option.okay, 1, R.string.btn_okay).setShowAsAction(
// MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
// return true;
// }
//
// @Override
// public boolean onOptionsItemSelected(MenuItem item) {
// switch (item.getItemId()) {
//
// case Id.menu.option.okay:
// okClicked();
// return true;
//
// case Id.menu.option.cancel:
// cancelClicked();
// return true;
//
// default:
// break;
//
// }
// return false;
// }
//}

View File

@ -0,0 +1,112 @@
package org.thialfihar.android.apg.ui;
import java.util.Date;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.provider.ApgContract.PublicKeyRings;
import org.thialfihar.android.apg.provider.ApgContract.PublicKeys;
import org.thialfihar.android.apg.provider.ApgContract.PublicUserIds;
import org.thialfihar.android.apg.ui.widget.SelectPublicKeyCursorAdapter;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.app.SherlockListFragment;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.app.LoaderManager;
public class SelectPublicKeyListFragment extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
private SherlockFragmentActivity mActivity;
private SelectPublicKeyCursorAdapter mAdapter;
private long mCurrentRowId;
/**
* Define Adapter and Loader on create of Activity
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mActivity = getSherlockActivity();
// register long press context menu
registerForContextMenu(getListView());
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("TODO empty");
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
mAdapter = new SelectPublicKeyCursorAdapter(mActivity, null);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
static final String SORT_ORDER = PublicUserIds.USER_ID + " ASC";
// static final String SELECTION =
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
Uri baseUri = PublicKeyRings.buildPublicKeyRingsUri();
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
// These are the rows that we will retrieve.
long now = new Date().getTime() / 1000;
String[] projection = new String[] {
PublicKeyRings._ID, // 0
PublicKeyRings.MASTER_KEY_ID, // 1
PublicUserIds.USER_ID, // 2
"(SELECT COUNT(" + PublicKeys._ID + ") WHERE " + PublicKeys.IS_REVOKED
+ " = '0' AND " + PublicKeys.CAN_ENCRYPT + " = '1')", // 3
"(SELECT COUNT(" + PublicKeys._ID + ") WHERE " + PublicKeys.IS_REVOKED
+ " = '0' AND " + PublicKeys.CAN_ENCRYPT + " = '1' AND "
+ PublicKeys.CREATION + " <= '" + now + "' AND " + "(" + PublicKeys.EXPIRY
+ " IS NULL OR " + PublicKeys.EXPIRY + " >= '" + now + "'))", // 4
};
return new CursorLoader(getActivity(), baseUri, projection, null, null, SORT_ORDER);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
}

View File

@ -19,7 +19,7 @@ package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.ui.widget.SelectSecretKeyListAdapter; import org.thialfihar.android.apg.ui.widget.SelectSecretKeyListAdapterOld;
import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
@ -36,7 +36,7 @@ import android.widget.Button;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
public class SelectSecretKeyListActivity extends SherlockFragmentActivity { public class SelectSecretKeyListActivityOld extends SherlockFragmentActivity {
// Not used in sourcode, but listed in AndroidManifest! // Not used in sourcode, but listed in AndroidManifest!
public static final String ACTION_SELECT_SECRET_KEY = Constants.INTENT_PREFIX public static final String ACTION_SELECT_SECRET_KEY = Constants.INTENT_PREFIX
@ -46,7 +46,7 @@ public class SelectSecretKeyListActivity extends SherlockFragmentActivity {
public static final String RESULT_EXTRA_KEY_ID = "keyId"; public static final String RESULT_EXTRA_KEY_ID = "keyId";
protected ListView mList; protected ListView mList;
protected SelectSecretKeyListAdapter mListAdapter; protected SelectSecretKeyListAdapterOld mListAdapter;
protected View mFilterLayout; protected View mFilterLayout;
protected Button mClearFilterButton; protected Button mClearFilterButton;
protected TextView mFilterInfo; protected TextView mFilterInfo;
@ -113,12 +113,12 @@ public class SelectSecretKeyListActivity extends SherlockFragmentActivity {
mFilterInfo.setText(getString(R.string.filterInfo, searchString)); mFilterInfo.setText(getString(R.string.filterInfo, searchString));
} }
if (mListAdapter != null) { // if (mListAdapter != null) {
mListAdapter.cleanup(); // mListAdapter.cleanup();
} // }
//
mListAdapter = new SelectSecretKeyListAdapter(this, mList, searchString); // mListAdapter = new SelectSecretKeyListAdapter(this, mList, searchString);
mList.setAdapter(mListAdapter); // mList.setAdapter(mListAdapter);
} }
@Override @Override

View File

@ -120,7 +120,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
} else { } else {
// kick off the SecretKey selection activity so the user chooses which key to sign with // kick off the SecretKey selection activity so the user chooses which key to sign with
// first // first
Intent intent = new Intent(this, SelectSecretKeyListActivity.class); Intent intent = new Intent(this, SelectSecretKeyListActivityOld.class);
startActivityForResult(intent, Id.request.secret_keys); startActivityForResult(intent, Id.request.secret_keys);
} }
} }

View File

@ -0,0 +1,530 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* @author Khoa Tran
*
* @see android.support.v4.app.ListFragment
* @see android.app.ExpandableListActivity
*
* ExpandableListFragment for Android < 3.0
*
* from
* http://stackoverflow.com/questions/6051050/expandablelistfragment-with-loadermanager-for-
* compatibility-package
*
*/
public class ExpandableListFragment extends Fragment implements OnCreateContextMenuListener,
ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
ExpandableListView.OnGroupExpandListener {
static final int INTERNAL_EMPTY_ID = 0x00ff0001;
static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002;
static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003;
final private Handler mHandler = new Handler();
final private Runnable mRequestFocus = new Runnable() {
public void run() {
mExpandableList.focusableViewAvailable(mExpandableList);
}
};
final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
onListItemClick((ExpandableListView) parent, v, position, id);
}
};
ExpandableListAdapter mAdapter;
ExpandableListView mExpandableList;
boolean mFinishedStart = false;
View mEmptyView;
TextView mStandardEmptyView;
View mProgressContainer;
View mExpandableListContainer;
CharSequence mEmptyText;
boolean mExpandableListShown;
public ExpandableListFragment() {
}
/**
* Provide default implementation to return a simple list view. Subclasses can override to
* replace with their own layout. If doing so, the returned view hierarchy <em>must</em> have a
* ListView whose id is {@link android.R.id#list android.R.id.list} and can optionally have a
* sibling view id {@link android.R.id#empty android.R.id.empty} that is to be shown when the
* list is empty.
*
* <p>
* If you are overriding this method with your own custom content, consider including the
* standard layout {@link android.R.layout#list_content} in your layout file, so that you
* continue to retain all of the standard behavior of ListFragment. In particular, this is
* currently the only way to have the built-in indeterminant progress state be shown.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final Context context = getActivity();
FrameLayout root = new FrameLayout(context);
// ------------------------------------------------------------------
LinearLayout pframe = new LinearLayout(context);
pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID);
pframe.setOrientation(LinearLayout.VERTICAL);
pframe.setVisibility(View.GONE);
pframe.setGravity(Gravity.CENTER);
ProgressBar progress = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge);
pframe.addView(progress, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(pframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
// ------------------------------------------------------------------
FrameLayout lframe = new FrameLayout(context);
lframe.setId(INTERNAL_LIST_CONTAINER_ID);
TextView tv = new TextView(getActivity());
tv.setId(INTERNAL_EMPTY_ID);
tv.setGravity(Gravity.CENTER);
lframe.addView(tv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
ExpandableListView lv = new ExpandableListView(getActivity());
lv.setId(android.R.id.list);
lv.setDrawSelectorOnTop(false);
lframe.addView(lv, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
root.addView(lframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
// ------------------------------------------------------------------
root.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
return root;
}
/**
* Attach to list view once the view hierarchy has been created.
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ensureList();
}
/**
* Detach from list view.
*/
@Override
public void onDestroyView() {
mHandler.removeCallbacks(mRequestFocus);
mExpandableList = null;
mExpandableListShown = false;
mEmptyView = mProgressContainer = mExpandableListContainer = null;
mStandardEmptyView = null;
super.onDestroyView();
}
/**
* This method will be called when an item in the list is selected. Subclasses should override.
* Subclasses can call getListView().getItemAtPosition(position) if they need to access the data
* associated with the selected item.
*
* @param l
* The ListView where the click happened
* @param v
* The view that was clicked within the ListView
* @param position
* The position of the view in the list
* @param id
* The row id of the item that was clicked
*/
public void onListItemClick(ExpandableListView l, View v, int position, long id) {
}
/**
* Provide the cursor for the list view.
*/
public void setListAdapter(ExpandableListAdapter adapter) {
boolean hadAdapter = mAdapter != null;
mAdapter = adapter;
if (mExpandableList != null) {
mExpandableList.setAdapter(adapter);
if (!mExpandableListShown && !hadAdapter) {
// The list was hidden, and previously didn't have an
// adapter. It is now time to show it.
setListShown(true, getView().getWindowToken() != null);
}
}
}
/**
* Set the currently selected list item to the specified position with the adapter's data
*
* @param position
*/
public void setSelection(int position) {
ensureList();
mExpandableList.setSelection(position);
}
/**
* Get the position of the currently selected list item.
*/
public int getSelectedItemPosition() {
ensureList();
return mExpandableList.getSelectedItemPosition();
}
/**
* Get the cursor row ID of the currently selected list item.
*/
public long getSelectedItemId() {
ensureList();
return mExpandableList.getSelectedItemId();
}
/**
* Get the activity's list view widget.
*/
public ExpandableListView getListView() {
ensureList();
return mExpandableList;
}
/**
* The default content for a ListFragment has a TextView that can be shown when the list is
* empty. If you would like to have it shown, call this method to supply the text it should use.
*/
public void setEmptyText(CharSequence text) {
ensureList();
if (mStandardEmptyView == null) {
throw new IllegalStateException("Can't be used with a custom content view");
}
mStandardEmptyView.setText(text);
if (mEmptyText == null) {
mExpandableList.setEmptyView(mStandardEmptyView);
}
mEmptyText = text;
}
/**
* Control whether the list is being displayed. You can make it not displayed if you are waiting
* for the initial data to show in it. During this time an indeterminant progress indicator will
* be shown instead.
*
* <p>
* Applications do not normally need to use this themselves. The default behavior of
* ListFragment is to start with the list not being shown, only showing it once an adapter is
* given with {@link #setListAdapter(ListAdapter)}. If the list at that point had not been
* shown, when it does get shown it will be do without the user ever seeing the hidden state.
*
* @param shown
* If true, the list view is shown; if false, the progress indicator. The initial
* value is true.
*/
public void setListShown(boolean shown) {
setListShown(shown, true);
}
/**
* Like {@link #setListShown(boolean)}, but no animation is used when transitioning from the
* previous state.
*/
public void setListShownNoAnimation(boolean shown) {
setListShown(shown, false);
}
/**
* Control whether the list is being displayed. You can make it not displayed if you are waiting
* for the initial data to show in it. During this time an indeterminant progress indicator will
* be shown instead.
*
* @param shown
* If true, the list view is shown; if false, the progress indicator. The initial
* value is true.
* @param animate
* If true, an animation will be used to transition to the new state.
*/
private void setListShown(boolean shown, boolean animate) {
ensureList();
if (mProgressContainer == null) {
throw new IllegalStateException("Can't be used with a custom content view");
}
if (mExpandableListShown == shown) {
return;
}
mExpandableListShown = shown;
if (shown) {
if (animate) {
mProgressContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(),
android.R.anim.fade_out));
mExpandableListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(),
android.R.anim.fade_in));
} else {
mProgressContainer.clearAnimation();
mExpandableListContainer.clearAnimation();
}
mProgressContainer.setVisibility(View.GONE);
mExpandableListContainer.setVisibility(View.VISIBLE);
} else {
if (animate) {
mProgressContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(),
android.R.anim.fade_in));
mExpandableListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(),
android.R.anim.fade_out));
} else {
mProgressContainer.clearAnimation();
mExpandableListContainer.clearAnimation();
}
mProgressContainer.setVisibility(View.VISIBLE);
mExpandableListContainer.setVisibility(View.GONE);
}
}
/**
* Get the ListAdapter associated with this activity's ListView.
*/
public ExpandableListAdapter getListAdapter() {
return mAdapter;
}
private void ensureList() {
if (mExpandableList != null) {
return;
}
View root = getView();
if (root == null) {
throw new IllegalStateException("Content view not yet created");
}
if (root instanceof ExpandableListView) {
mExpandableList = (ExpandableListView) root;
} else {
mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID);
if (mStandardEmptyView == null) {
mEmptyView = root.findViewById(android.R.id.empty);
} else {
mStandardEmptyView.setVisibility(View.GONE);
}
mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID);
mExpandableListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID);
View rawExpandableListView = root.findViewById(android.R.id.list);
if (!(rawExpandableListView instanceof ExpandableListView)) {
if (rawExpandableListView == null) {
throw new RuntimeException(
"Your content must have a ListView whose id attribute is "
+ "'android.R.id.list'");
}
throw new RuntimeException(
"Content has view with id attribute 'android.R.id.list' "
+ "that is not a ListView class");
}
mExpandableList = (ExpandableListView) rawExpandableListView;
if (mEmptyView != null) {
mExpandableList.setEmptyView(mEmptyView);
} else if (mEmptyText != null) {
mStandardEmptyView.setText(mEmptyText);
mExpandableList.setEmptyView(mStandardEmptyView);
}
}
mExpandableListShown = true;
mExpandableList.setOnItemClickListener(mOnClickListener);
if (mAdapter != null) {
ExpandableListAdapter adapter = mAdapter;
mAdapter = null;
setListAdapter(adapter);
} else {
// We are starting without an adapter, so assume we won't
// have our data right away and start with the progress indicator.
if (mProgressContainer != null) {
setListShown(false, false);
}
}
mHandler.post(mRequestFocus);
}
/**
* Override this to populate the context menu when an item is long pressed. menuInfo will
* contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo} whose
* packedPosition is a packed position that should be used with
* {@link ExpandableListView#getPackedPositionType(long)} and the other similar methods.
* <p>
* {@inheritDoc}
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
}
/**
* Override this for receiving callbacks when a child has been clicked.
* <p>
* {@inheritDoc}
*/
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
return false;
}
/**
* Override this for receiving callbacks when a group has been collapsed.
*/
public void onGroupCollapse(int groupPosition) {
}
/**
* Override this for receiving callbacks when a group has been expanded.
*/
public void onGroupExpand(int groupPosition) {
}
// /**
// * Ensures the expandable list view has been created before Activity restores all
// * of the view states.
// *
// *@see Activity#onRestoreInstanceState(Bundle)
// */
// @Override
// protected void onRestoreInstanceState(Bundle state) {
// ensureList();
// super.onRestoreInstanceState(state);
// }
/**
* Updates the screen state (current list and other views) when the content changes.
*
* @see Activity#onContentChanged()
*/
public void onContentChanged() {
// super.onContentChanged();
View emptyView = getView().findViewById(android.R.id.empty);
mExpandableList = (ExpandableListView) getView().findViewById(android.R.id.list);
if (mExpandableList == null) {
throw new RuntimeException(
"Your content must have a ExpandableListView whose id attribute is "
+ "'android.R.id.list'");
}
if (emptyView != null) {
mExpandableList.setEmptyView(emptyView);
}
mExpandableList.setOnChildClickListener(this);
mExpandableList.setOnGroupExpandListener(this);
mExpandableList.setOnGroupCollapseListener(this);
if (mFinishedStart) {
setListAdapter(mAdapter);
}
mFinishedStart = true;
}
/**
* Get the activity's expandable list view widget. This can be used to get the selection, set
* the selection, and many other useful functions.
*
* @see ExpandableListView
*/
public ExpandableListView getExpandableListView() {
ensureList();
return mExpandableList;
}
/**
* Get the ExpandableListAdapter associated with this activity's ExpandableListView.
*/
public ExpandableListAdapter getExpandableListAdapter() {
return mAdapter;
}
/**
* Gets the ID of the currently selected group or child.
*
* @return The ID of the currently selected group or child.
*/
public long getSelectedId() {
return mExpandableList.getSelectedId();
}
/**
* Gets the position (in packed position representation) of the currently selected group or
* child. Use {@link ExpandableListView#getPackedPositionType},
* {@link ExpandableListView#getPackedPositionGroup}, and
* {@link ExpandableListView#getPackedPositionChild} to unpack the returned packed position.
*
* @return A packed position representation containing the currently selected group or child's
* position and type.
*/
public long getSelectedPosition() {
return mExpandableList.getSelectedPosition();
}
/**
* Sets the selection to the specified child. If the child is in a collapsed group, the group
* will only be expanded and child subsequently selected if shouldExpandGroup is set to true,
* otherwise the method will return false.
*
* @param groupPosition
* The position of the group that contains the child.
* @param childPosition
* The position of the child within the group.
* @param shouldExpandGroup
* Whether the child's group should be expanded if it is collapsed.
* @return Whether the selection was successfully set on the child.
*/
public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
return mExpandableList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
}
/**
* Sets the selection to the specified group.
*
* @param groupPosition
* The position of the group that should be selected.
*/
public void setSelectedGroup(int groupPosition) {
mExpandableList.setSelectedGroup(groupPosition);
}
}

View File

@ -0,0 +1,235 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.OtherHelper;
import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.provider.ApgContract.PublicKeys;
import org.thialfihar.android.apg.provider.ApgContract.PublicUserIds;
import org.thialfihar.android.apg.provider.ApgContract.SecretKeys;
import org.thialfihar.android.apg.provider.ApgContract.SecretUserIds;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleCursorTreeAdapter;
import android.widget.TextView;
public class KeyListAdapter extends SimpleCursorTreeAdapter implements
LoaderManager.LoaderCallbacks<Cursor> {
private Context mContext;
private LoaderManager mManager;
private LayoutInflater mInflater;
// Id.type.public_key / Id.type.secret_key
protected int mKeyType;
public KeyListAdapter(Context context, LoaderManager manager, Cursor groupCursor, int keyType) {
super(context, groupCursor, -1, null, null, -1, null, null);
mContext = context;
mManager = manager;
mInflater = LayoutInflater.from(context);
mKeyType = keyType;
}
/**
* Inflate new view for group items
*/
@Override
public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
return mInflater.inflate(R.layout.key_list_group_item, null);
}
/**
* Binds TextViews from view to results from database group cursor.
*/
@Override
protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) {
int userIdIndex;
if (mKeyType == Id.type.public_key) {
userIdIndex = cursor.getColumnIndex(PublicUserIds.USER_ID);
} else {
userIdIndex = cursor.getColumnIndex(SecretUserIds.USER_ID);
}
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = cursor.getString(userIdIndex);
if (userId != null) {
String[] userIdSplit = OtherHelper.splitUserId(userId);
if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]);
}
mainUserId.setText(userIdSplit[0]);
}
if (mainUserId.getText().length() == 0) {
mainUserId.setText(R.string.unknownUserId);
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
}
/**
* Inflate new view for child items
*/
@Override
public View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup parent) {
return mInflater.inflate(R.layout.key_list_child_item_master_key, null);
}
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
int keyIdIndex;
if (mKeyType == Id.type.public_key) {
keyIdIndex = cursor.getColumnIndex(PublicKeys.KEY_ID);
} else {
keyIdIndex = cursor.getColumnIndex(SecretKeys.KEY_ID);
}
TextView keyId = (TextView) view.findViewById(R.id.keyId);
String keyIdStr = PGPHelper.getSmallFingerPrint(cursor.getLong(keyIdIndex));
keyId.setText(keyIdStr);
}
/**
* Given the group, we return a cursor for all the children within that group
*/
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
final long idGroup = groupCursor.getLong(groupCursor.getColumnIndex(BaseColumns._ID));
Bundle bundle = new Bundle();
bundle.putLong("idGroup", idGroup);
int groupPos = groupCursor.getPosition();
if (mManager.getLoader(groupPos) != null && !mManager.getLoader(groupPos).isReset()) {
mManager.restartLoader(groupPos, bundle, this);
} else {
mManager.initLoader(groupPos, bundle, this);
}
return null;
// OLD CODE:
// Vector<KeyChild> children = mChildren.get(groupPosition);
// if (children != null) {
// return children;
// }
// mCursor.moveToPosition(groupPosition);
// children = new Vector<KeyChild>();
// Cursor c = mDatabase.query(Keys.TABLE_NAME, new String[] { Keys._ID, // 0
// Keys.KEY_ID, // 1
// Keys.IS_MASTER_KEY, // 2
// Keys.ALGORITHM, // 3
// Keys.KEY_SIZE, // 4
// Keys.CAN_SIGN, // 5
// Keys.CAN_ENCRYPT, // 6
// }, Keys.KEY_RING_ID + " = ?", new String[] { mCursor.getString(0) }, null, null,
// Keys.RANK + " ASC");
// int masterKeyId = -1;
// long fingerPrintId = -1;
// for (int i = 0; i < c.getCount(); ++i) {
// c.moveToPosition(i);
// children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4),
// c.getInt(5) == 1, c.getInt(6) == 1));
// if (i == 0) {
// masterKeyId = c.getInt(0);
// fingerPrintId = c.getLong(1);
// }
// }
// c.close();
//
// if (masterKeyId != -1) {
// children.insertElementAt(
// new KeyChild(PGPHelper.getFingerPrint(KeyListActivity.this, fingerPrintId),
// true), 0);
// c = mDatabase.query(UserIds.TABLE_NAME, new String[] { UserIds.USER_ID, // 0
// }, UserIds.KEY_ID + " = ? AND " + UserIds.RANK + " > 0", new String[] { ""
// + masterKeyId }, null, null, UserIds.RANK + " ASC");
//
// for (int i = 0; i < c.getCount(); ++i) {
// c.moveToPosition(i);
// children.add(new KeyChild(c.getString(0)));
// }
// c.close();
// }
// mChildren.set(groupPosition, children);
// return children;
}
@Override
public Loader<Cursor> onCreateLoader(int groupPos, Bundle bundle) {
long idGroup = bundle.getLong("idGroup");
Uri uri = null;
String[] projection = null;
String orderBy = null;
if (mKeyType == Id.type.public_key) {
projection = new String[] { PublicKeys._ID, // 0
PublicKeys.KEY_ID, // 1
PublicKeys.IS_MASTER_KEY, // 2
PublicKeys.ALGORITHM, // 3
PublicKeys.KEY_SIZE, // 4
PublicKeys.CAN_SIGN, // 5
PublicKeys.CAN_ENCRYPT, // 6
};
orderBy = PublicKeys.RANK + " ASC";
uri = PublicKeys.buildPublicKeysUri(String.valueOf(idGroup));
} else {
projection = new String[] { SecretKeys._ID, // 0
SecretKeys.KEY_ID, // 1
SecretKeys.IS_MASTER_KEY, // 2
SecretKeys.ALGORITHM, // 3
SecretKeys.KEY_SIZE, // 4
SecretKeys.CAN_SIGN, // 5
SecretKeys.CAN_ENCRYPT, // 6
};
orderBy = SecretKeys.RANK + " ASC";
uri = SecretKeys.buildSecretKeysUri(String.valueOf(idGroup));
}
return new CursorLoader(mContext, uri, projection, null, null, orderBy);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
setChildrenCursor(loader.getId(), cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.OtherHelper;
import org.thialfihar.android.apg.helper.PGPHelper;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
public class SelectPublicKeyCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
// private int mActivityIndex;
// private int mTimeIndex;
// private int mActionIndex;
// private int mAmountIndex;
public SelectPublicKeyCursorAdapter(Context context, Cursor c) {
super(context, c);
//
// mActivityIndex = c.getColumnIndex(Notes.ACTIVITY);
// mTimeIndex = c.getColumnIndex(Notes.TIME);
// mActionIndex = c.getColumnIndex(Notes.ACTION);
// mAmountIndex = c.getColumnIndex(Notes.AMOUNT);
mInflater = LayoutInflater.from(context);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// TextView activity = (TextView) view.findViewById(android.R.id.text1);
// TextView time = (TextView) view.findViewById(android.R.id.text2);
// TextView actionAndAmount = (TextView) view.findViewById(R.id.text3);
//
// activity.setText(cursor.getString(mActivityIndex));
//
// long lTime = cursor.getLong(mTimeIndex);
// Calendar cal = Calendar.getInstance();
// cal.setTimeInMillis(lTime);
// time.setText(cal.get(Calendar.HOUR_OF_DAY) + : + String.format(%02d,
// cal.get(Calendar.MINUTE)));
//
// String amount = cursor.getString(mAmountIndex);
// if ( amount.length() > 0){
// actionAndAmount.setText(cursor.getString(mActionIndex) + ( + amount + ));
// } else {
// actionAndAmount.setText(cursor.getString(mActionIndex));
// }
// boolean enabled = isEnabled(position);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(R.string.noKey);
TextView status = (TextView) view.findViewById(R.id.status);
status.setText(R.string.unknownStatus);
String userId = cursor.getString(2); // USER_ID
if (userId != null) {
String[] userIdSplit = OtherHelper.splitUserId(userId);
if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]);
}
mainUserId.setText(userIdSplit[0]);
}
long masterKeyId = cursor.getLong(1); // MASTER_KEY_ID
keyId.setText(PGPHelper.getSmallFingerPrint(masterKeyId));
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
// if (enabled) {
// status.setText(R.string.canEncrypt);
// } else {
if (cursor.getInt(3) > 0) {
// has some CAN_ENCRYPT keys, but col(4) = 0, so must be revoked or expired
status.setText(R.string.expired);
} else {
status.setText(R.string.noKey);
}
// }
status.setText(status.getText() + " ");
CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
// if (!enabled) {
// mParent.setItemChecked(position, false);
// }
// selected.setChecked(mParent.isItemChecked(position));
// view.setEnabled(enabled);
// mainUserId.setEnabled(enabled);
// mainUserIdRest.setEnabled(enabled);
// keyId.setEnabled(enabled);
// selected.setEnabled(enabled);
// status.setEnabled(enabled);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.select_public_key, null);
}
}

View File

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

View File

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

View File

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

View File

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