From 88aa439ea71d49462616e20aa4042052d0290647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 19 Jan 2014 00:45:53 +0100 Subject: [PATCH] fix qr code scanning, implement basic scanning of fingerprint only --- OpenPGP-Keychain/res/values/strings.xml | 1 + .../keychain/ui/ImportKeysQrCodeFragment.java | 168 +++++++++++------- .../keychain/ui/KeyServerQueryActivity.java | 58 +++--- .../util/IntentIntegratorSupportV4.java | 47 +++++ 4 files changed, 177 insertions(+), 97 deletions(-) create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/IntentIntegratorSupportV4.java diff --git a/OpenPGP-Keychain/res/values/strings.xml b/OpenPGP-Keychain/res/values/strings.xml index 28741d90a..d5eff50a9 100644 --- a/OpenPGP-Keychain/res/values/strings.xml +++ b/OpenPGP-Keychain/res/values/strings.xml @@ -320,6 +320,7 @@ Please start with QR Code with ID 1 QR Code malformed! Please try again! QR Code scanning finished! + Fingerprint contained in this QR Code is too short (< 16 characters) Scan QR Code with \'Barcode Scanner\' To receive keys via NFC, the device needs to be unlocked. Help diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java index 58a1400b0..3ede641d3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2013-2014 Dominik Schürmann * * 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 @@ -18,9 +18,11 @@ package org.sufficientlysecure.keychain.ui; import java.util.ArrayList; +import java.util.Locale; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4; import org.sufficientlysecure.keychain.util.Log; import android.content.Intent; @@ -35,7 +37,6 @@ import android.widget.TextView; import android.widget.Toast; import com.beardedhen.androidbootstrap.BootstrapButton; -import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; public class ImportKeysQrCodeFragment extends Fragment { @@ -75,7 +76,7 @@ public class ImportKeysQrCodeFragment extends Fragment { @Override public void onClick(View v) { // scan using xzing's Barcode Scanner - new IntentIntegrator(getActivity()).initiateScan(); + new IntentIntegratorSupportV4(ImportKeysQrCodeFragment.this).initiateScan(); } }); @@ -92,79 +93,29 @@ public class ImportKeysQrCodeFragment extends Fragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode & 0xFFFF) { - case IntentIntegrator.REQUEST_CODE: { - IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, - data); + case IntentIntegratorSupportV4.REQUEST_CODE: { + IntentResult scanResult = IntentIntegratorSupportV4.parseActivityResult(requestCode, + resultCode, data); if (scanResult != null && scanResult.getFormatName() != null) { - Log.d(Constants.TAG, scanResult.getContents()); + Log.d(Constants.TAG, "scanResult content: " + scanResult.getContents()); + // look if it's fingerprint only + if (scanResult.getContents().toLowerCase(Locale.ENGLISH).startsWith("openpgp4fpr")) { + importFingerprint(scanResult.getContents().toLowerCase(Locale.ENGLISH)); + return; + } + + // look if it is the whole key String[] parts = scanResult.getContents().split(","); - - if (parts.length != 3) { - Toast.makeText(getActivity(), R.string.import_qr_code_wrong, Toast.LENGTH_LONG) - .show(); + if (parts.length == 3) { + importParts(parts); return; } - int counter = Integer.valueOf(parts[0]); - int size = Integer.valueOf(parts[1]); - String content = parts[2]; - - Log.d(Constants.TAG, "" + counter); - Log.d(Constants.TAG, "" + size); - Log.d(Constants.TAG, "" + content); - - // first qr code -> setup - if (counter == 0) { - mScannedContent = new String[size]; - mProgress.setMax(size); - mProgress.setVisibility(View.VISIBLE); - mText.setVisibility(View.VISIBLE); - } - - if (mScannedContent == null || counter > mScannedContent.length) { - Toast.makeText(getActivity(), R.string.import_qr_code_start_with_one, - Toast.LENGTH_LONG).show(); - return; - } - - // save scanned content - mScannedContent[counter] = content; - - // get missing numbers - ArrayList missing = new ArrayList(); - for (int i = 0; i < mScannedContent.length; i++) { - if (mScannedContent[i] == null) { - missing.add(i); - } - } - - // update progress and text - int alreadyScanned = mScannedContent.length - missing.size(); - mProgress.setProgress(alreadyScanned); - - String missingString = ""; - for (int m : missing) { - if (!missingString.equals("")) { - missingString += ", "; - } - missingString += String.valueOf(m + 1); - } - - String missingText = getResources().getQuantityString( - R.plurals.import_qr_code_missing, missing.size(), missingString); - mText.setText(missingText); - - // finished! - if (missing.size() == 0) { - mText.setText(R.string.import_qr_code_finished); - String result = ""; - for (String in : mScannedContent) { - result += in; - } - mImportActivity.loadCallback(result.getBytes(), null); - } + // fail... + Toast.makeText(getActivity(), R.string.import_qr_code_wrong, Toast.LENGTH_LONG) + .show(); } break; @@ -176,4 +127,83 @@ public class ImportKeysQrCodeFragment extends Fragment { break; } } + + private void importFingerprint(String uri) { + String fingerprint = uri.split(":")[1]; + + Log.d(Constants.TAG, "fingerprint: " + fingerprint); + + if (fingerprint.length() < 16) { + Toast.makeText(getActivity(), R.string.import_qr_code_too_short_fingerprint, + Toast.LENGTH_LONG).show(); + return; + } + + Intent queryIntent = new Intent(getActivity(), KeyServerQueryActivity.class); + queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); + queryIntent.putExtra(KeyServerQueryActivity.EXTRA_FINGERPRINT, fingerprint); + startActivity(queryIntent); + } + + private void importParts(String[] parts) { + int counter = Integer.valueOf(parts[0]); + int size = Integer.valueOf(parts[1]); + String content = parts[2]; + + Log.d(Constants.TAG, "" + counter); + Log.d(Constants.TAG, "" + size); + Log.d(Constants.TAG, "" + content); + + // first qr code -> setup + if (counter == 0) { + mScannedContent = new String[size]; + mProgress.setMax(size); + mProgress.setVisibility(View.VISIBLE); + mText.setVisibility(View.VISIBLE); + } + + if (mScannedContent == null || counter > mScannedContent.length) { + Toast.makeText(getActivity(), R.string.import_qr_code_start_with_one, Toast.LENGTH_LONG) + .show(); + return; + } + + // save scanned content + mScannedContent[counter] = content; + + // get missing numbers + ArrayList missing = new ArrayList(); + for (int i = 0; i < mScannedContent.length; i++) { + if (mScannedContent[i] == null) { + missing.add(i); + } + } + + // update progress and text + int alreadyScanned = mScannedContent.length - missing.size(); + mProgress.setProgress(alreadyScanned); + + String missingString = ""; + for (int m : missing) { + if (!missingString.equals("")) { + missingString += ", "; + } + missingString += String.valueOf(m + 1); + } + + String missingText = getResources().getQuantityString(R.plurals.import_qr_code_missing, + missing.size(), missingString); + mText.setText(missingText); + + // finished! + if (missing.size() == 0) { + mText.setText(R.string.import_qr_code_finished); + String result = ""; + for (String in : mScannedContent) { + result += in; + } + mImportActivity.loadCallback(result.getBytes(), null); + } + } + } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java index c3ec7b9c3..5e3b3d052 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2012-2014 Dominik Schürmann * Copyright (C) 2010 Thialfihar * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,23 +66,19 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { + "LOOK_UP_KEY_ID_AND_RETURN"; public static final String EXTRA_KEY_ID = "key_id"; + public static final String EXTRA_FINGERPRINT = "fingerprint"; public static final String RESULT_EXTRA_TEXT = "text"; private ListView mList; - private EditText mQuery; - private Button mSearch; + private Spinner mKeyServer; private KeyInfoListAdapter mAdapter; - private Spinner mKeyServer; - private int mQueryType; - private String mQueryString; - private long mQueryId; private volatile List mSearchResult; @@ -93,15 +89,15 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { 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, KeyListPublicActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; + case android.R.id.home: + // app icon in Action Bar clicked; go home + Intent intent = new Intent(this, KeyListPublicActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; - default: - break; + default: + break; } return false; @@ -113,13 +109,13 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { setContentView(R.layout.key_server_query); - mQuery = (EditText)findViewById(R.id.query); - mSearch = (Button)findViewById(R.id.btn_search); - mList = (ListView)findViewById(R.id.list); + mQuery = (EditText) findViewById(R.id.query); + mSearch = (Button) findViewById(R.id.btn_search); + mList = (ListView) findViewById(R.id.list); mAdapter = new KeyInfoListAdapter(this); mList.setAdapter(mAdapter); - mKeyServer = (Spinner)findViewById(R.id.sign_key_keyserver); + mKeyServer = (Spinner) findViewById(R.id.sign_key_keyserver); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, Preferences.getPreferences(this) .getKeyServers()); @@ -168,6 +164,12 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { mQuery.setText(query); search(query); } + String fingerprint = intent.getStringExtra(EXTRA_FINGERPRINT); + if (fingerprint != null) { + fingerprint = "0x" + fingerprint; + mQuery.setText(fingerprint); + search(fingerprint); + } } } @@ -197,7 +199,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { // fill values for this action Bundle data = new Bundle(); - String server = (String)mKeyServer.getSelectedItem(); + String server = (String) mKeyServer.getSelectedItem(); data.putString(KeychainIntentService.QUERY_KEY_SERVER, server); data.putInt(KeychainIntentService.QUERY_KEY_TYPE, mQueryType); @@ -286,7 +288,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { public KeyInfoListAdapter(Activity activity) { mActivity = activity; - mInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mKeys = new ArrayList(); } @@ -321,15 +323,15 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { View view = mInflater.inflate(R.layout.key_server_query_result_item, null); - TextView mainUserId = (TextView)view.findViewById(R.id.mainUserId); + TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); mainUserId.setText(R.string.unknown_user_id); - TextView mainUserIdRest = (TextView)view.findViewById(R.id.mainUserIdRest); + TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); mainUserIdRest.setText(""); - TextView keyId = (TextView)view.findViewById(R.id.keyId); + TextView keyId = (TextView) view.findViewById(R.id.keyId); keyId.setText(R.string.no_key); - TextView algorithm = (TextView)view.findViewById(R.id.algorithm); + TextView algorithm = (TextView) view.findViewById(R.id.algorithm); algorithm.setText(""); - TextView status = (TextView)view.findViewById(R.id.status); + TextView status = (TextView) view.findViewById(R.id.status); status.setText(""); String userId = keyInfo.userIds.get(0); @@ -356,7 +358,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { status.setVisibility(View.GONE); } - LinearLayout ll = (LinearLayout)view.findViewById(R.id.list); + LinearLayout ll = (LinearLayout) view.findViewById(R.id.list); if (keyInfo.userIds.size() == 1) { ll.setVisibility(View.GONE); } else { @@ -373,7 +375,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity { sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark); ll.addView(sep); } - TextView uidView = (TextView)mInflater.inflate( + TextView uidView = (TextView) mInflater.inflate( R.layout.key_server_query_result_user_id, null); uidView.setText(uid); ll.addView(uidView); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/IntentIntegratorSupportV4.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/IntentIntegratorSupportV4.java new file mode 100644 index 000000000..a43c03e3e --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/IntentIntegratorSupportV4.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012 ZXing authors + * + * 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.sufficientlysecure.keychain.util; + +import android.content.Intent; +import android.support.v4.app.Fragment; + +import com.google.zxing.integration.android.IntentIntegrator; + +/** + * IntentIntegrator for the V4 Android compatibility package. + * + * @author Lachezar Dobrev + */ +public final class IntentIntegratorSupportV4 extends IntentIntegrator { + + private final Fragment fragment; + + /** + * @param fragment + * Fragment to handle activity response. + */ + public IntentIntegratorSupportV4(Fragment fragment) { + super(fragment.getActivity()); + this.fragment = fragment; + } + + @Override + protected void startActivityForResult(Intent intent, int code) { + fragment.startActivityForResult(intent, code); + } + +}