mirror of
https://github.com/zxing/zxing.git
synced 2025-02-02 05:41:08 -08:00
- Prevented secure URIs from being added to History or copied to the clipboard.
- Made the History display parsed entries instead of raw contents. - Some minor cleanup and comments. git-svn-id: https://zxing.googlecode.com/svn/trunk@1813 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
886e3a3e02
commit
e04e3ef2c1
|
@ -20,8 +20,8 @@ version to be published. The next versionCode will be 7, regardless of whether t
|
||||||
versionName is 2.31, 2.4, or 3.0. -->
|
versionName is 2.31, 2.4, or 3.0. -->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.google.zxing.client.android"
|
package="com.google.zxing.client.android"
|
||||||
android:versionName="3.6"
|
android:versionName="3.61 beta 1"
|
||||||
android:versionCode="70"
|
android:versionCode="71"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<!-- We require Cupcake (Android 1.5) or later, but are really targeting Donut. -->
|
<!-- We require Cupcake (Android 1.5) or later, but are really targeting Donut. -->
|
||||||
<uses-sdk android:minSdkVersion="3"
|
<uses-sdk android:minSdkVersion="3"
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
<link rel="stylesheet" href="style.css" type="text/css"/>
|
<link rel="stylesheet" href="style.css" type="text/css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<p><b>New in version 3.61:</b></p>
|
||||||
|
<ul>
|
||||||
|
<li>Fixed a couple of crashes.</li>
|
||||||
|
<li>Made items in the History easier to read.</li>
|
||||||
|
</ul>
|
||||||
<p><b>New in version 3.6:</b></p>
|
<p><b>New in version 3.6:</b></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Added support for the Motorola Xoom and other tablets.</li>
|
<li>Added support for the Motorola Xoom and other tablets.</li>
|
||||||
|
|
|
@ -364,23 +364,25 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
||||||
public void handleDecode(Result rawResult, Bitmap barcode) {
|
public void handleDecode(Result rawResult, Bitmap barcode) {
|
||||||
inactivityTimer.onActivity();
|
inactivityTimer.onActivity();
|
||||||
lastResult = rawResult;
|
lastResult = rawResult;
|
||||||
historyManager.addHistoryItem(rawResult);
|
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
|
||||||
|
historyManager.addHistoryItem(rawResult, resultHandler);
|
||||||
|
|
||||||
if (barcode == null) {
|
if (barcode == null) {
|
||||||
// This is from history -- no saved barcode
|
// This is from history -- no saved barcode
|
||||||
handleDecodeInternally(rawResult, null);
|
handleDecodeInternally(rawResult, resultHandler, null);
|
||||||
} else {
|
} else {
|
||||||
beepManager.playBeepSoundAndVibrate();
|
beepManager.playBeepSoundAndVibrate();
|
||||||
drawResultPoints(barcode, rawResult);
|
drawResultPoints(barcode, rawResult);
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case NATIVE_APP_INTENT:
|
case NATIVE_APP_INTENT:
|
||||||
case PRODUCT_SEARCH_LINK:
|
case PRODUCT_SEARCH_LINK:
|
||||||
handleDecodeExternally(rawResult, barcode);
|
handleDecodeExternally(rawResult, resultHandler, barcode);
|
||||||
break;
|
break;
|
||||||
case ZXING_LINK:
|
case ZXING_LINK:
|
||||||
if (returnUrlTemplate == null){
|
if (returnUrlTemplate == null){
|
||||||
handleDecodeInternally(rawResult, barcode);
|
handleDecodeInternally(rawResult, resultHandler, barcode);
|
||||||
} else {
|
} else {
|
||||||
handleDecodeExternally(rawResult, barcode);
|
handleDecodeExternally(rawResult, resultHandler, barcode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NONE:
|
case NONE:
|
||||||
|
@ -393,7 +395,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
||||||
}
|
}
|
||||||
resetStatusView();
|
resetStatusView();
|
||||||
} else {
|
} else {
|
||||||
handleDecodeInternally(rawResult, barcode);
|
handleDecodeInternally(rawResult, resultHandler, barcode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -441,7 +443,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put up our own UI for how to handle the decoded contents.
|
// Put up our own UI for how to handle the decoded contents.
|
||||||
private void handleDecodeInternally(Result rawResult, Bitmap barcode) {
|
private void handleDecodeInternally(Result rawResult, ResultHandler resultHandler, Bitmap barcode) {
|
||||||
statusView.setVisibility(View.GONE);
|
statusView.setVisibility(View.GONE);
|
||||||
viewfinderView.setVisibility(View.GONE);
|
viewfinderView.setVisibility(View.GONE);
|
||||||
resultView.setVisibility(View.VISIBLE);
|
resultView.setVisibility(View.VISIBLE);
|
||||||
|
@ -457,7 +459,6 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
||||||
TextView formatTextView = (TextView) findViewById(R.id.format_text_view);
|
TextView formatTextView = (TextView) findViewById(R.id.format_text_view);
|
||||||
formatTextView.setText(rawResult.getBarcodeFormat().toString());
|
formatTextView.setText(rawResult.getBarcodeFormat().toString());
|
||||||
|
|
||||||
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
|
|
||||||
TextView typeTextView = (TextView) findViewById(R.id.type_text_view);
|
TextView typeTextView = (TextView) findViewById(R.id.type_text_view);
|
||||||
typeTextView.setText(resultHandler.getType().toString());
|
typeTextView.setText(resultHandler.getType().toString());
|
||||||
|
|
||||||
|
@ -518,23 +519,22 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copyToClipboard) {
|
if (copyToClipboard && !resultHandler.areContentsSecure()) {
|
||||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||||
clipboard.setText(displayContents);
|
clipboard.setText(displayContents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Briefly show the contents of the barcode, then handle the result outside Barcode Scanner.
|
// Briefly show the contents of the barcode, then handle the result outside Barcode Scanner.
|
||||||
private void handleDecodeExternally(Result rawResult, Bitmap barcode) {
|
private void handleDecodeExternally(Result rawResult, ResultHandler resultHandler, Bitmap barcode) {
|
||||||
viewfinderView.drawResultBitmap(barcode);
|
viewfinderView.drawResultBitmap(barcode);
|
||||||
|
|
||||||
// Since this message will only be shown for a second, just tell the user what kind of
|
// Since this message will only be shown for a second, just tell the user what kind of
|
||||||
// barcode was found (e.g. contact info) rather than the full contents, which they won't
|
// barcode was found (e.g. contact info) rather than the full contents, which they won't
|
||||||
// have time to read.
|
// have time to read.
|
||||||
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
|
|
||||||
statusView.setText(getString(resultHandler.getDisplayTitle()));
|
statusView.setText(getString(resultHandler.getDisplayTitle()));
|
||||||
|
|
||||||
if (copyToClipboard) {
|
if (copyToClipboard && !resultHandler.areContentsSecure()) {
|
||||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||||
clipboard.setText(resultHandler.getDisplayContents());
|
clipboard.setText(resultHandler.getDisplayContents());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,38 +16,39 @@
|
||||||
|
|
||||||
package com.google.zxing.client.android.history;
|
package com.google.zxing.client.android.history;
|
||||||
|
|
||||||
import java.util.List;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.client.android.CaptureActivity;
|
||||||
|
import com.google.zxing.client.android.R;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import com.google.zxing.Result;
|
|
||||||
import com.google.zxing.client.android.CaptureActivity;
|
import java.util.List;
|
||||||
import com.google.zxing.client.android.R;
|
|
||||||
|
|
||||||
final class HistoryClickListener implements DialogInterface.OnClickListener {
|
final class HistoryClickListener implements DialogInterface.OnClickListener {
|
||||||
|
|
||||||
private final HistoryManager historyManager;
|
private final HistoryManager historyManager;
|
||||||
private final CaptureActivity activity;
|
private final CaptureActivity activity;
|
||||||
private final String[] dialogItems;
|
|
||||||
private final List<Result> items;
|
private final List<Result> items;
|
||||||
|
|
||||||
HistoryClickListener(HistoryManager historyManager,
|
/**
|
||||||
CaptureActivity activity,
|
* Handles clicks in the History dialog.
|
||||||
String[] dialogItems,
|
*
|
||||||
List<Result> items) {
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
|
* @author Sean Owen
|
||||||
|
*/
|
||||||
|
HistoryClickListener(HistoryManager historyManager, CaptureActivity activity, List<Result> items) {
|
||||||
this.historyManager = historyManager;
|
this.historyManager = historyManager;
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.dialogItems = dialogItems;
|
|
||||||
this.items = items;
|
this.items = items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
if (i == dialogItems.length - 1) {
|
if (i == items.size()) {
|
||||||
historyManager.clearHistory();
|
// Share history.
|
||||||
} else if (i == dialogItems.length - 2) {
|
|
||||||
CharSequence history = historyManager.buildHistory();
|
CharSequence history = historyManager.buildHistory();
|
||||||
Uri historyFile = HistoryManager.saveHistory(history.toString());
|
Uri historyFile = HistoryManager.saveHistory(history.toString());
|
||||||
if (historyFile == null) {
|
if (historyFile == null) {
|
||||||
|
@ -65,7 +66,11 @@ final class HistoryClickListener implements DialogInterface.OnClickListener {
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, historyFile);
|
intent.putExtra(Intent.EXTRA_STREAM, historyFile);
|
||||||
intent.setType("text/csv");
|
intent.setType("text/csv");
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
|
} else if (i == items.size() + 1) {
|
||||||
|
// Clear history.
|
||||||
|
historyManager.clearHistory();
|
||||||
} else {
|
} else {
|
||||||
|
// Display a single history entry.
|
||||||
Result result = items.get(i);
|
Result result = items.get(i);
|
||||||
Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, result);
|
Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, result);
|
||||||
message.sendToTarget();
|
message.sendToTarget();
|
||||||
|
|
|
@ -16,17 +16,27 @@
|
||||||
|
|
||||||
package com.google.zxing.client.android.history;
|
package com.google.zxing.client.android.history;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.client.android.CaptureActivity;
|
||||||
|
import com.google.zxing.client.android.Intents;
|
||||||
|
import com.google.zxing.client.android.PreferencesActivity;
|
||||||
|
import com.google.zxing.client.android.R;
|
||||||
|
import com.google.zxing.client.android.result.ResultHandler;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteException;
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
@ -34,19 +44,9 @@ import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Collections;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
|
||||||
import com.google.zxing.client.android.Intents;
|
|
||||||
import com.google.zxing.client.android.PreferencesActivity;
|
|
||||||
import com.google.zxing.client.android.R;
|
|
||||||
import com.google.zxing.client.android.CaptureActivity;
|
|
||||||
import com.google.zxing.Result;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Manages functionality related to scan history.</p>
|
* <p>Manages functionality related to scan history.</p>
|
||||||
|
@ -54,13 +54,13 @@ import com.google.zxing.Result;
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
public final class HistoryManager {
|
public final class HistoryManager {
|
||||||
|
|
||||||
private static final String TAG = HistoryManager.class.getSimpleName();
|
private static final String TAG = HistoryManager.class.getSimpleName();
|
||||||
|
|
||||||
private static final int MAX_ITEMS = 500;
|
private static final int MAX_ITEMS = 500;
|
||||||
//private static final String[] TEXT_COL_PROJECTION = { DBHelper.TEXT_COL };
|
|
||||||
private static final String[] GET_ITEM_COL_PROJECTION = {
|
private static final String[] GET_ITEM_COL_PROJECTION = {
|
||||||
DBHelper.TEXT_COL,
|
DBHelper.TEXT_COL,
|
||||||
|
DBHelper.DISPLAY_COL,
|
||||||
DBHelper.FORMAT_COL,
|
DBHelper.FORMAT_COL,
|
||||||
DBHelper.TIMESTAMP_COL,
|
DBHelper.TIMESTAMP_COL,
|
||||||
};
|
};
|
||||||
|
@ -79,60 +79,53 @@ public final class HistoryManager {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Result> getHistoryItems() {
|
public AlertDialog buildAlert() {
|
||||||
SQLiteOpenHelper helper = new DBHelper(activity);
|
SQLiteOpenHelper helper = new DBHelper(activity);
|
||||||
List<Result> items = new ArrayList<Result>();
|
List<Result> items = new ArrayList<Result>();
|
||||||
SQLiteDatabase db;
|
List<String> dialogItems = new ArrayList<String>();
|
||||||
try {
|
SQLiteDatabase db = null;
|
||||||
db = helper.getWritableDatabase();
|
|
||||||
} catch (SQLiteException sqle) {
|
|
||||||
Log.w(TAG, "Error while opening database", sqle);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = db.query(DBHelper.TABLE_NAME,
|
db = helper.getWritableDatabase();
|
||||||
GET_ITEM_COL_PROJECTION,
|
cursor = db.query(DBHelper.TABLE_NAME, GET_ITEM_COL_PROJECTION, null, null, null, null,
|
||||||
null, null, null, null,
|
|
||||||
DBHelper.TIMESTAMP_COL + " DESC");
|
DBHelper.TIMESTAMP_COL + " DESC");
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
Result result = new Result(cursor.getString(0),
|
Result result = new Result(cursor.getString(0), null, null,
|
||||||
null,
|
BarcodeFormat.valueOf(cursor.getString(2)), cursor.getLong(3));
|
||||||
null,
|
|
||||||
BarcodeFormat.valueOf(cursor.getString(1)),
|
|
||||||
cursor.getLong(2));
|
|
||||||
items.add(result);
|
items.add(result);
|
||||||
|
String display = cursor.getString(1);
|
||||||
|
if (display == null || display.length() == 0) {
|
||||||
|
display = result.getText();
|
||||||
}
|
}
|
||||||
|
dialogItems.add(display);
|
||||||
|
}
|
||||||
|
} catch (SQLiteException sqle) {
|
||||||
|
Log.w(TAG, "Error while opening database", sqle);
|
||||||
} finally {
|
} finally {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
if (db != null) {
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AlertDialog buildAlert() {
|
|
||||||
List<Result> items = getHistoryItems();
|
|
||||||
int size = items.size();
|
|
||||||
String[] dialogItems = new String[size + 2];
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
dialogItems[i] = items.get(i).getText();
|
|
||||||
}
|
|
||||||
Resources res = activity.getResources();
|
Resources res = activity.getResources();
|
||||||
dialogItems[dialogItems.length - 2] = res.getString(R.string.history_send);
|
dialogItems.add(res.getString(R.string.history_send));
|
||||||
dialogItems[dialogItems.length - 1] = res.getString(R.string.history_clear_text);
|
dialogItems.add(res.getString(R.string.history_clear_text));
|
||||||
DialogInterface.OnClickListener clickListener = new HistoryClickListener(this, activity,
|
DialogInterface.OnClickListener clickListener = new HistoryClickListener(this, activity, items);
|
||||||
dialogItems, items);
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setTitle(R.string.history_title);
|
builder.setTitle(R.string.history_title);
|
||||||
builder.setItems(dialogItems, clickListener);
|
builder.setItems(dialogItems.toArray(new String[dialogItems.size()]), clickListener);
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addHistoryItem(Result result) {
|
public void addHistoryItem(Result result, ResultHandler handler) {
|
||||||
if (!activity.getIntent().getBooleanExtra(Intents.Scan.SAVE_HISTORY, true)) {
|
// Do not save this item to the history if the preference is turned off, or the contents are
|
||||||
return; // Do not save this item to the history.
|
// considered secure.
|
||||||
|
if (!activity.getIntent().getBooleanExtra(Intents.Scan.SAVE_HISTORY, true) ||
|
||||||
|
handler.areContentsSecure()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
|
@ -149,13 +142,11 @@ public final class HistoryManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Insert
|
// Insert the new entry into the DB.
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(DBHelper.TEXT_COL, result.getText());
|
values.put(DBHelper.TEXT_COL, result.getText());
|
||||||
values.put(DBHelper.FORMAT_COL, result.getBarcodeFormat().toString());
|
values.put(DBHelper.FORMAT_COL, result.getBarcodeFormat().toString());
|
||||||
// It would be nice to use ParsedResult.getDisplayResult() instead, but we don't want to
|
values.put(DBHelper.DISPLAY_COL, handler.getDisplayContents().toString());
|
||||||
// parse it twice, and it can be multiline which won't fit in the current UI.
|
|
||||||
values.put(DBHelper.DISPLAY_COL, result.getText());
|
|
||||||
values.put(DBHelper.TIMESTAMP_COL, System.currentTimeMillis());
|
values.put(DBHelper.TIMESTAMP_COL, System.currentTimeMillis());
|
||||||
db.insert(DBHelper.TABLE_NAME, DBHelper.TIMESTAMP_COL, values);
|
db.insert(DBHelper.TABLE_NAME, DBHelper.TIMESTAMP_COL, values);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -143,6 +143,16 @@ public abstract class ResultHandler {
|
||||||
*/
|
*/
|
||||||
public abstract void handleButtonPress(int index);
|
public abstract void handleButtonPress(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some barcode contents are considered secure, and should not be saved to history, copied to
|
||||||
|
* the clipboard, or otherwise persisted.
|
||||||
|
*
|
||||||
|
* @return If true, do not create any permanent record of these contents.
|
||||||
|
*/
|
||||||
|
public boolean areContentsSecure() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Google Shopper button is special and is not handled by the abstract button methods above.
|
* The Google Shopper button is special and is not handled by the abstract button methods above.
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,6 +28,11 @@ import android.app.Activity;
|
||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
*/
|
*/
|
||||||
public final class URIResultHandler extends ResultHandler {
|
public final class URIResultHandler extends ResultHandler {
|
||||||
|
// URIs beginning with entries in this array will not be saved to history or copied to the
|
||||||
|
// clipboard for security.
|
||||||
|
private static final String[] SECURE_PROTOCOLS = new String[] {
|
||||||
|
"otpauth:"
|
||||||
|
};
|
||||||
|
|
||||||
private static final int[] buttons = {
|
private static final int[] buttons = {
|
||||||
R.string.button_open_browser,
|
R.string.button_open_browser,
|
||||||
|
@ -75,9 +80,20 @@ public final class URIResultHandler extends ResultHandler {
|
||||||
return R.string.result_uri;
|
return R.string.result_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsSecure() {
|
||||||
|
URIParsedResult uriResult = (URIParsedResult) getResult();
|
||||||
|
String uri = uriResult.getURI().toLowerCase();
|
||||||
|
for (String secure : SECURE_PROTOCOLS) {
|
||||||
|
if (uri.startsWith(secure)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isGoogleBooksURI() {
|
private boolean isGoogleBooksURI() {
|
||||||
// FIXME(dswitkin): Should not hardcode Books URL. Also does not handle books.google.ca etc.
|
// FIXME(dswitkin): Should not hardcode Books URL. Also does not handle books.google.ca etc.
|
||||||
return ((URIParsedResult) getResult()).getURI().startsWith("http://google.com/books?id=");
|
return ((URIParsedResult) getResult()).getURI().startsWith("http://google.com/books?id=");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ public abstract class ResultParser {
|
||||||
} else if ((result = URLTOResultParser.parse(theResult)) != null) {
|
} else if ((result = URLTOResultParser.parse(theResult)) != null) {
|
||||||
return result;
|
return result;
|
||||||
} else if ((result = URIResultParser.parse(theResult)) != null) {
|
} else if ((result = URIResultParser.parse(theResult)) != null) {
|
||||||
|
// URI is a catch-all for protocol: contents that we don't handle explicitly above.
|
||||||
return result;
|
return result;
|
||||||
} else if ((result = ISBNResultParser.parse(theResult)) != null) {
|
} else if ((result = ISBNResultParser.parse(theResult)) != null) {
|
||||||
// We depend on ISBN parsing coming before UPC, as it is a subset.
|
// We depend on ISBN parsing coming before UPC, as it is a subset.
|
||||||
|
@ -126,7 +127,6 @@ public abstract class ResultParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String urlDecode(String escaped) {
|
private static String urlDecode(String escaped) {
|
||||||
|
|
||||||
// No we can't use java.net.URLDecoder here. JavaME doesn't have it.
|
// No we can't use java.net.URLDecoder here. JavaME doesn't have it.
|
||||||
if (escaped == null) {
|
if (escaped == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -139,7 +139,7 @@ public abstract class ResultParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
int max = escapedArray.length;
|
int max = escapedArray.length;
|
||||||
// final length is at most 2 less than original due to at least 1 unescaping
|
// Final length is at most 2 less than original due to at least 1 unescaping.
|
||||||
StringBuffer unescaped = new StringBuffer(max - 2);
|
StringBuffer unescaped = new StringBuffer(max - 2);
|
||||||
// Can append everything up to first escape character
|
// Can append everything up to first escape character
|
||||||
unescaped.append(escapedArray, 0, first);
|
unescaped.append(escapedArray, 0, first);
|
||||||
|
@ -152,14 +152,14 @@ public abstract class ResultParser {
|
||||||
unescaped.append(' ');
|
unescaped.append(' ');
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
// Are there even two more chars? if not we will just copy the escaped sequence and be done
|
// Are there even two more chars? If not we'll just copy the escaped sequence and be done.
|
||||||
if (i >= max - 2) {
|
if (i >= max - 2) {
|
||||||
unescaped.append('%'); // append that % and move on
|
unescaped.append('%'); // append that % and move on
|
||||||
} else {
|
} else {
|
||||||
int firstDigitValue = parseHexDigit(escapedArray[++i]);
|
int firstDigitValue = parseHexDigit(escapedArray[++i]);
|
||||||
int secondDigitValue = parseHexDigit(escapedArray[++i]);
|
int secondDigitValue = parseHexDigit(escapedArray[++i]);
|
||||||
if (firstDigitValue < 0 || secondDigitValue < 0) {
|
if (firstDigitValue < 0 || secondDigitValue < 0) {
|
||||||
// bad digit, just move on
|
// Bad digit, just move on.
|
||||||
unescaped.append('%');
|
unescaped.append('%');
|
||||||
unescaped.append(escapedArray[i - 1]);
|
unescaped.append(escapedArray[i - 1]);
|
||||||
unescaped.append(escapedArray[i]);
|
unescaped.append(escapedArray[i]);
|
||||||
|
|
Loading…
Reference in a new issue