fix qr code scanning, implement basic scanning of fingerprint only

This commit is contained in:
Dominik Schürmann 2014-01-19 00:45:53 +01:00
parent 1bac2849b8
commit 88aa439ea7
4 changed files with 177 additions and 97 deletions

View File

@ -320,6 +320,7 @@
<string name="import_qr_code_start_with_one">Please start with QR Code with ID 1</string> <string name="import_qr_code_start_with_one">Please start with QR Code with ID 1</string>
<string name="import_qr_code_wrong">QR Code malformed! Please try again!</string> <string name="import_qr_code_wrong">QR Code malformed! Please try again!</string>
<string name="import_qr_code_finished">QR Code scanning finished!</string> <string name="import_qr_code_finished">QR Code scanning finished!</string>
<string name="import_qr_code_too_short_fingerprint">Fingerprint contained in this QR Code is too short (&lt; 16 characters)</string>
<string name="import_qr_scan_button">Scan QR Code with \'Barcode Scanner\'</string> <string name="import_qr_scan_button">Scan QR Code with \'Barcode Scanner\'</string>
<string name="import_nfc_text">To receive keys via NFC, the device needs to be unlocked.</string> <string name="import_nfc_text">To receive keys via NFC, the device needs to be unlocked.</string>
<string name="import_nfc_help_button">Help</string> <string name="import_nfc_help_button">Help</string>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -18,9 +18,11 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import android.content.Intent; import android.content.Intent;
@ -35,7 +37,6 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.beardedhen.androidbootstrap.BootstrapButton; import com.beardedhen.androidbootstrap.BootstrapButton;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult; import com.google.zxing.integration.android.IntentResult;
public class ImportKeysQrCodeFragment extends Fragment { public class ImportKeysQrCodeFragment extends Fragment {
@ -75,7 +76,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// scan using xzing's Barcode Scanner // 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 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode & 0xFFFF) { switch (requestCode & 0xFFFF) {
case IntentIntegrator.REQUEST_CODE: { case IntentIntegratorSupportV4.REQUEST_CODE: {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, IntentResult scanResult = IntentIntegratorSupportV4.parseActivityResult(requestCode,
data); resultCode, data);
if (scanResult != null && scanResult.getFormatName() != null) { 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(","); String[] parts = scanResult.getContents().split(",");
if (parts.length == 3) {
if (parts.length != 3) { importParts(parts);
Toast.makeText(getActivity(), R.string.import_qr_code_wrong, Toast.LENGTH_LONG)
.show();
return; return;
} }
int counter = Integer.valueOf(parts[0]); // fail...
int size = Integer.valueOf(parts[1]); Toast.makeText(getActivity(), R.string.import_qr_code_wrong, Toast.LENGTH_LONG)
String content = parts[2]; .show();
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<Integer> missing = new ArrayList<Integer>();
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);
}
} }
break; break;
@ -176,4 +127,83 @@ public class ImportKeysQrCodeFragment extends Fragment {
break; 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<Integer> missing = new ArrayList<Integer>();
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);
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* 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");
@ -66,23 +66,19 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
+ "LOOK_UP_KEY_ID_AND_RETURN"; + "LOOK_UP_KEY_ID_AND_RETURN";
public static final String EXTRA_KEY_ID = "key_id"; public static final String EXTRA_KEY_ID = "key_id";
public static final String EXTRA_FINGERPRINT = "fingerprint";
public static final String RESULT_EXTRA_TEXT = "text"; public static final String RESULT_EXTRA_TEXT = "text";
private ListView mList; private ListView mList;
private EditText mQuery; private EditText mQuery;
private Button mSearch; private Button mSearch;
private Spinner mKeyServer;
private KeyInfoListAdapter mAdapter; private KeyInfoListAdapter mAdapter;
private Spinner mKeyServer;
private int mQueryType; private int mQueryType;
private String mQueryString; private String mQueryString;
private long mQueryId; private long mQueryId;
private volatile List<KeyInfo> mSearchResult; private volatile List<KeyInfo> mSearchResult;
@ -93,15 +89,15 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
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, KeyListPublicActivity.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;
default: default:
break; break;
} }
return false; return false;
@ -113,13 +109,13 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
setContentView(R.layout.key_server_query); setContentView(R.layout.key_server_query);
mQuery = (EditText)findViewById(R.id.query); mQuery = (EditText) findViewById(R.id.query);
mSearch = (Button)findViewById(R.id.btn_search); mSearch = (Button) findViewById(R.id.btn_search);
mList = (ListView)findViewById(R.id.list); mList = (ListView) findViewById(R.id.list);
mAdapter = new KeyInfoListAdapter(this); mAdapter = new KeyInfoListAdapter(this);
mList.setAdapter(mAdapter); mList.setAdapter(mAdapter);
mKeyServer = (Spinner)findViewById(R.id.sign_key_keyserver); mKeyServer = (Spinner) findViewById(R.id.sign_key_keyserver);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, Preferences.getPreferences(this) android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
.getKeyServers()); .getKeyServers());
@ -168,6 +164,12 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
mQuery.setText(query); mQuery.setText(query);
search(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 // fill values for this action
Bundle data = new Bundle(); Bundle data = new Bundle();
String server = (String)mKeyServer.getSelectedItem(); String server = (String) mKeyServer.getSelectedItem();
data.putString(KeychainIntentService.QUERY_KEY_SERVER, server); data.putString(KeychainIntentService.QUERY_KEY_SERVER, server);
data.putInt(KeychainIntentService.QUERY_KEY_TYPE, mQueryType); data.putInt(KeychainIntentService.QUERY_KEY_TYPE, mQueryType);
@ -286,7 +288,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
public KeyInfoListAdapter(Activity activity) { public KeyInfoListAdapter(Activity activity) {
mActivity = activity; mActivity = activity;
mInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mKeys = new ArrayList<KeyInfo>(); mKeys = new ArrayList<KeyInfo>();
} }
@ -321,15 +323,15 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
View view = mInflater.inflate(R.layout.key_server_query_result_item, null); 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); 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(""); mainUserIdRest.setText("");
TextView keyId = (TextView)view.findViewById(R.id.keyId); TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(R.string.no_key); keyId.setText(R.string.no_key);
TextView algorithm = (TextView)view.findViewById(R.id.algorithm); TextView algorithm = (TextView) view.findViewById(R.id.algorithm);
algorithm.setText(""); algorithm.setText("");
TextView status = (TextView)view.findViewById(R.id.status); TextView status = (TextView) view.findViewById(R.id.status);
status.setText(""); status.setText("");
String userId = keyInfo.userIds.get(0); String userId = keyInfo.userIds.get(0);
@ -356,7 +358,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
status.setVisibility(View.GONE); 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) { if (keyInfo.userIds.size() == 1) {
ll.setVisibility(View.GONE); ll.setVisibility(View.GONE);
} else { } else {
@ -373,7 +375,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark); sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark);
ll.addView(sep); ll.addView(sep);
} }
TextView uidView = (TextView)mInflater.inflate( TextView uidView = (TextView) mInflater.inflate(
R.layout.key_server_query_result_user_id, null); R.layout.key_server_query_result_user_id, null);
uidView.setText(uid); uidView.setText(uid);
ll.addView(uidView); ll.addView(uidView);

View File

@ -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);
}
}