search works

This commit is contained in:
Dominik Schürmann 2014-02-01 19:49:44 +01:00
parent 7e634a9930
commit 0e53d901e6
12 changed files with 206 additions and 96 deletions

View File

@ -28,12 +28,9 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@ -48,10 +45,8 @@ import org.sufficientlysecure.keychain.pgp.PgpOperation;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.HkpKeyServer;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.KeyServer.KeyInfo;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
@ -144,8 +139,6 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public static final String DELETE_FILE = "deleteFile";
// import key
public static final String IMPORT_INPUT_STREAM = "import_input_stream";
public static final String IMPORT_FILENAME = "import_filename";
public static final String IMPORT_BYTES = "import_bytes";
public static final String IMPORT_KEY_LIST = "import_key_list";
@ -161,8 +154,6 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// query key
public static final String QUERY_KEY_SERVER = "query_key_server";
public static final String QUERY_KEY_TYPE = "query_key_type";
public static final String QUERY_KEY_STRING = "query_key_string";
public static final String QUERY_KEY_ID = "query_key_id";
// sign key
@ -762,25 +753,25 @@ public class KeychainIntentService extends IntentService implements ProgressDial
try {
/* Input */
int queryType = data.getInt(QUERY_KEY_TYPE);
// int queryType = data.getInt(QUERY_KEY_TYPE);
String keyServer = data.getString(QUERY_KEY_SERVER);
String queryString = data.getString(QUERY_KEY_STRING);
// String queryString = data.getString(QUERY_KEY_STRING);
long keyId = data.getLong(QUERY_KEY_ID);
/* Operation */
Bundle resultData = new Bundle();
HkpKeyServer server = new HkpKeyServer(keyServer);
if (queryType == Id.keyserver.search) {
ArrayList<KeyInfo> searchResult = server.search(queryString);
resultData.putParcelableArrayList(RESULT_QUERY_KEY_SEARCH_RESULT, searchResult);
} else if (queryType == Id.keyserver.get) {
// if (queryType == Id.keyserver.search) {
// ArrayList<KeyInfo> searchResult = server.search(queryString);
//
// resultData.putParcelableArrayList(RESULT_QUERY_KEY_SEARCH_RESULT, searchResult);
// } else if (queryType == Id.keyserver.get) {
String keyData = server.get(keyId);
resultData.putString(RESULT_QUERY_KEY_DATA, keyData);
}
// }
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {

View File

@ -179,9 +179,6 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
loadFragment(ImportKeysServerFragment.class, args, mNavigationStrings[0]);
// TODO: implement KEYSERVER!
} else {
// Other actions
startListFragment(savedInstanceState, null, null);
@ -279,8 +276,8 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi
startActivity(queryIntent);
}
public void loadCallback(byte[] importData, Uri dataUri, String serverQuery) {
mListFragment.loadNew(importData, dataUri, serverQuery);
public void loadCallback(byte[] importData, Uri dataUri, String serverQuery, String keyserver) {
mListFragment.loadNew(importData, dataUri, serverQuery, keyserver);
}
// private void importAndSignOld(final long keyId, final String expectedFingerprint) {
@ -444,6 +441,8 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi
// start service with intent
startService(intent);
} else if (mListFragment.getServerQuery() != null) {
// TODO!
} else {
Toast.makeText(this, R.string.error_nothing_import, Toast.LENGTH_LONG).show();
}

View File

@ -62,7 +62,7 @@ public class ImportKeysClipboardFragment extends Fragment {
String sendText = "";
if (clipboardText != null)
sendText = clipboardText.toString();
mImportActivity.loadCallback(sendText.getBytes(), null, null);
mImportActivity.loadCallback(sendText.getBytes(), null, null, null);
}
});

View File

@ -84,7 +84,7 @@ public class ImportKeysFileFragment extends Fragment {
if (resultCode == Activity.RESULT_OK && data != null) {
// load data
mImportActivity.loadCallback(null, data.getData(), null);
mImportActivity.loadCallback(null, data.getData(), null, null);
}
break;

View File

@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@ -29,6 +28,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@ -54,6 +54,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements
private byte[] mKeyBytes;
private Uri mDataUri;
private String mServerQuery;
private String mKeyServer;
private static final int LOADER_ID_BYTES = 0;
private static final int LOADER_ID_SERVER_QUERY = 1;
@ -66,6 +67,10 @@ public class ImportKeysListFragment extends SherlockListFragment implements
return mDataUri;
}
public String getServerQuery() {
return mServerQuery;
}
public List<ImportKeysListEntry> getData() {
return mAdapter.getData();
}
@ -131,15 +136,16 @@ public class ImportKeysListFragment extends SherlockListFragment implements
mAdapter.notifyDataSetChanged();
}
public void loadNew(byte[] importData, Uri dataUri, String serverQuery) {
public void loadNew(byte[] importData, Uri dataUri, String serverQuery, String keyServer) {
mKeyBytes = importData;
mDataUri = dataUri;
mServerQuery = serverQuery;
mKeyServer = keyServer;
if (mKeyBytes != null || mDataUri != null)
getLoaderManager().restartLoader(LOADER_ID_BYTES, null, this);
if (mServerQuery != null)
if (mServerQuery != null && mKeyServer != null)
getLoaderManager().restartLoader(LOADER_ID_SERVER_QUERY, null, this);
}
@ -152,7 +158,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements
return new ImportKeysListLoader(mActivity, inputData);
}
case LOADER_ID_SERVER_QUERY: {
return new ImportKeysListServerLoader(getActivity(), mServerQuery, mKeyServer);
}
default:
@ -165,31 +171,32 @@ public class ImportKeysListFragment extends SherlockListFragment implements
List<ImportKeysListEntry> data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
case LOADER_ID_BYTES:
Log.d(Constants.TAG, "data: " + data);
// swap in the real data!
mAdapter.setData(data);
mAdapter.notifyDataSetChanged();
Log.d(Constants.TAG, "data: " + data);
setListAdapter(mAdapter);
// swap in the real data!
mAdapter.setData(data);
mAdapter.notifyDataSetChanged();
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
setListAdapter(mAdapter);
break;
case LOADER_ID_SERVER_QUERY:
break;
default:
break;
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
// switch (loader.getId()) {
// case LOADER_ID_BYTES:
//
// break;
//
// case LOADER_ID_SERVER_QUERY:
// break;
//
// default:
// break;
// }
}
@Override

View File

@ -190,7 +190,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
for (String in : mScannedContent) {
result += in;
}
mImportActivity.loadCallback(result.getBytes(), null, null);
mImportActivity.loadCallback(result.getBytes(), null, null, null);
}
}

View File

@ -17,11 +17,10 @@
package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
import android.content.Intent;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.KeyEvent;
@ -30,6 +29,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
@ -39,23 +39,24 @@ import com.beardedhen.androidbootstrap.BootstrapButton;
public class ImportKeysServerFragment extends Fragment {
public static final String ARG_QUERY = "query";
public static final String ARG_KEY_SERVER = "key_server";
private ImportKeysActivity mImportActivity;
private BootstrapButton mOldButton;
private BootstrapButton mSearchButton;
private EditText mQueryEditText;
private Spinner mServerSpinner;
private ArrayAdapter<String> mServerAdapter;
/**
* Creates new instance of this fragment
*/
public static ImportKeysServerFragment newInstance(String query) {
public static ImportKeysServerFragment newInstance(String query, String keyServer) {
ImportKeysServerFragment frag = new ImportKeysServerFragment();
Bundle args = new Bundle();
args.putString(ARG_QUERY, query);
args.putString(ARG_KEY_SERVER, keyServer);
frag.setArguments(args);
@ -69,17 +70,17 @@ public class ImportKeysServerFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_server_fragment, container, false);
mSearchButton = (BootstrapButton) view.findViewById(R.id.import_server_button);
mSearchButton = (BootstrapButton) view.findViewById(R.id.import_server_search);
mQueryEditText = (EditText) view.findViewById(R.id.import_server_query);
mServerSpinner = (Spinner) view.findViewById(R.id.import_server_spinner);
// add keyservers to spinner
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
mServerAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item, Preferences.getPreferences(getActivity())
.getKeyServers());
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mServerSpinner.setAdapter(adapter);
if (adapter.getCount() > 0) {
mServerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mServerSpinner.setAdapter(mServerAdapter);
if (mServerAdapter.getCount() > 0) {
mServerSpinner.setSelection(0);
} else {
mSearchButton.setEnabled(false);
@ -89,31 +90,28 @@ public class ImportKeysServerFragment extends Fragment {
@Override
public void onClick(View v) {
String query = mQueryEditText.getText().toString();
String keyServer = (String) mServerSpinner.getSelectedItem();
search(query, keyServer);
// close keyboard after pressing search
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mQueryEditText.getWindowToken(), 0);
}
});
// TODO: not supported by BootstrapButton
// mSearchButton.setOnEditorActionListener(new TextView.OnEditorActionListener() {
// @Override
// public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// String query = mQueryEditText.getText().toString();
// search(query);
// // FIXME This is a hack to hide a keyboard after search
// // http://tinyurl.com/pwdc3q9
// return false;
// }
// return false;
// }
// });
// TODO: remove:
mOldButton = (BootstrapButton) view.findViewById(R.id.import_server_button);
mOldButton.setOnClickListener(new OnClickListener() {
mQueryEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public void onClick(View v) {
startActivityForResult(new Intent(getActivity(), KeyServerQueryActivity.class), 0);
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
String query = mQueryEditText.getText().toString();
String keyServer = (String) mServerSpinner.getSelectedItem();
search(query, keyServer);
// Don't return true to let the keyboard close itself after pressing search
// http://stackoverflow.com/questions/2342620/how-to-hide-keyboard-after-typing-in-edittext-in-android
return false;
}
return false;
}
});
@ -130,12 +128,22 @@ public class ImportKeysServerFragment extends Fragment {
if (getArguments() != null && getArguments().containsKey(ARG_QUERY)) {
String query = getArguments().getString(ARG_QUERY);
mQueryEditText.setText(query);
search(query);
String keyServer = null;
if (getArguments().containsKey(ARG_KEY_SERVER)) {
keyServer = getArguments().getString(ARG_KEY_SERVER);
int keyServerPos = mServerAdapter.getPosition(keyServer);
mServerSpinner.setSelection(keyServerPos);
} else {
keyServer = (String) mServerSpinner.getSelectedItem();
}
search(query, keyServer);
}
}
private void search(String query) {
private void search(String query, String keyServer) {
mImportActivity.loadCallback(null, null, query, keyServer);
}
}

View File

@ -202,13 +202,13 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
String server = (String) mKeyServer.getSelectedItem();
data.putString(KeychainIntentService.QUERY_KEY_SERVER, server);
data.putInt(KeychainIntentService.QUERY_KEY_TYPE, mQueryType);
// data.putInt(KeychainIntentService.QUERY_KEY_TYPE, mQueryType);
if (mQueryType == Id.keyserver.search) {
data.putString(KeychainIntentService.QUERY_KEY_STRING, mQueryString);
} else if (mQueryType == Id.keyserver.get) {
data.putLong(KeychainIntentService.QUERY_KEY_ID, mQueryId);
}
// if (mQueryType == Id.keyserver.search) {
// data.putString(KeychainIntentService.QUERY_KEY_STRING, mQueryString);
// } else if (mQueryType == Id.keyserver.get) {
// data.putLong(KeychainIntentService.QUERY_KEY_ID, mQueryId);
// }
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);

View File

@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui.adapter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
@ -33,7 +34,7 @@ public class ImportKeysListEntry implements Serializable {
public long keyId;
public boolean revoked;
// public Date date;
public Date date; // TODO: not displayed
public String fingerPrint;
public String hexKeyId;
public int bitStrength;

View File

@ -0,0 +1,100 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.adapter;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.HkpKeyServer;
import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
import java.util.List;
public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
Context mContext;
String mServerQuery;
String mKeyServer;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) {
super(context);
mContext = context;
mServerQuery = serverQuery;
mKeyServer = keyServer;
}
@Override
public List<ImportKeysListEntry> loadInBackground() {
if (mServerQuery == null) {
Log.e(Constants.TAG, "mServerQuery is null!");
return data;
}
queryServer(mServerQuery, mKeyServer);
return data;
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
}
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
public void deliverResult(List<ImportKeysListEntry> data) {
super.deliverResult(data);
}
/**
* Query key server
*/
private void queryServer(String query, String keyServer) {
HkpKeyServer server = new HkpKeyServer(keyServer);
try {
ArrayList<ImportKeysListEntry> searchResult = server.search(query);
// add result to data
data.addAll(searchResult);
} catch (KeyServer.InsufficientQuery e) {
Log.e(Constants.TAG, "InsufficientQuery", e);
} catch (KeyServer.QueryException e) {
Log.e(Constants.TAG, "QueryException", e);
} catch (KeyServer.TooManyResponses e) {
Log.e(Constants.TAG, "TooManyResponses", e);
}
}
}

View File

@ -46,6 +46,7 @@ import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import android.text.Html;
@ -141,9 +142,9 @@ public class HkpKeyServer extends KeyServer {
}
@Override
public ArrayList<KeyInfo> search(String query) throws QueryException, TooManyResponses,
public ArrayList<ImportKeysListEntry> search(String query) throws QueryException, TooManyResponses,
InsufficientQuery {
ArrayList<KeyInfo> results = new ArrayList<KeyInfo>();
ArrayList<ImportKeysListEntry> results = new ArrayList<ImportKeysListEntry>();
if (query.length() < 3) {
throw new InsufficientQuery();
@ -177,8 +178,9 @@ public class HkpKeyServer extends KeyServer {
Matcher matcher = PUB_KEY_LINE.matcher(data);
while (matcher.find()) {
KeyInfo info = new KeyInfo();
info.size = Integer.parseInt(matcher.group(1));
// KeyInfo info = new KeyInfo();
ImportKeysListEntry info = new ImportKeysListEntry();
info.bitStrength = Integer.parseInt(matcher.group(1));
info.algorithm = matcher.group(2);
info.keyId = PgpKeyHelper.convertHexToKeyId(matcher.group(3));
info.fingerPrint = PgpKeyHelper.convertKeyIdToHex(info.keyId);
@ -186,11 +188,11 @@ public class HkpKeyServer extends KeyServer {
GregorianCalendar tmpGreg = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
tmpGreg.set(Integer.parseInt(chunks[0]), Integer.parseInt(chunks[1]),
Integer.parseInt(chunks[2]));
Integer.parseInt(chunks[2]));
info.date = tmpGreg.getTime();
info.userIds = new ArrayList<String>();
if (matcher.group(5).startsWith("*** KEY")) {
info.revoked = matcher.group(5);
info.revoked = true;
} else {
String tmp = matcher.group(5).replaceAll("<.*?>", "");
tmp = Html.fromHtml(tmp).toString();

View File

@ -24,6 +24,8 @@ import java.util.List;
import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
public abstract class KeyServer {
static public class QueryException extends Exception {
private static final long serialVersionUID = 2703768928624654512L;
@ -88,7 +90,7 @@ public abstract class KeyServer {
}
}
abstract List<KeyInfo> search(String query) throws QueryException, TooManyResponses,
abstract List<ImportKeysListEntry> search(String query) throws QueryException, TooManyResponses,
InsufficientQuery;
abstract String get(long keyId) throws QueryException;