generate aztec code

This commit is contained in:
Harald Hoyer 2014-07-31 10:57:16 +02:00
parent 4fd4949813
commit 1bb906f660
7 changed files with 259 additions and 71 deletions

View file

@ -61,7 +61,10 @@
</content>
<orderEntry type="jdk" jdkName="Android API 20 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-20.0.0" level="project" />
<orderEntry type="library" exported="" name="core-3.1.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-20.0.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-20.0.0" level="project" />
<orderEntry type="library" exported="" name="miglayout-3.7.4" level="project" />
<orderEntry type="library" exported="" name="secretshare-1.4.1" level="project" />
</component>

View file

@ -5,6 +5,7 @@ apply plugin: 'maven'
dependencies {
compile 'com.tiemens:secretshare:1.4.1'
compile 'com.google.zxing:core:3.1.0'
compile 'com.android.support:appcompat-v7:20.+'
}
buildscript {

View file

@ -1,31 +1,27 @@
package org.surfsite.android.secretshare;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.print.PrintHelper;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.tiemens.secretshare.engine.SecretShare;
import com.tiemens.secretshare.engine.SecretShare.ShareInfo;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Hashtable;
import java.util.List;
@ -41,7 +37,6 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
private static final String ARG_N = "n";
private static final String ARG_K = "k";
private static final String ARG_CLEARTEXT = "cleartext";
private final static QRCodeWriter sQRCodeWriter = new QRCodeWriter();
private int n;
private int k;
private String cleartext;
@ -128,12 +123,11 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
super.onStart();
if (generateSharesTask != null)
generateSharesTask.cancel(true);
TextView tv = (TextView) getActivity().findViewById(R.id.generate_status);
generateSharesTask = new GenerateSharesTask(tv, n, k, cleartext);
else {
generateSharesTask = new GenerateSharesTask(n, k, cleartext);
generateSharesTask.execute();
}
}
@Override
public void onStop() {
@ -168,6 +162,7 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
}
private class GenerateSharesTask extends AsyncTask<Void, Void, Void> {
private final Activity activity;
private TextView tv;
private List<SecretShare.ShareInfo> pieces;
private int n;
@ -175,9 +170,12 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
private String cleartext;
private SecretShare.PublicInfo publicInfo;
private boolean finished = false;
private Bitmap qrCodeBitmap;
private ImageView qrCodeView;
public GenerateSharesTask(TextView tv, int n, int k, String cleartext) {
this.tv = tv;
public GenerateSharesTask(int n, int k, String cleartext) {
activity = getActivity();
this.tv = (TextView) activity.findViewById(R.id.generate_status);
this.n = n;
this.k = k;
this.cleartext = cleartext;
@ -185,50 +183,6 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
+ " chars. Please Wait. This can take a long time.");
}
private Bitmap createBitmap(byte[] content, final int size) {
final Hashtable<EncodeHintType, Object> hints =
new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
BitMatrix result;
String data;
try {
data = new String(content, "ISO-8859-1");
} catch (Exception ex) {
ex.printStackTrace();
data = new String(content);
}
try {
result = sQRCodeWriter.encode(data,
BarcodeFormat.QR_CODE,
size,
size,
hints);
} catch (WriterException ex) {
return null;
}
final int width = result.getWidth();
final int height = result.getHeight();
final int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
final int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] =
result.get(x, y) ? Color.BLACK : Color.TRANSPARENT;
}
}
final Bitmap bitmap =
Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
public boolean isFinished() {
return finished;
}
@ -260,7 +214,7 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
byte[] bmodulus = publicInfo.getPrimeModulus().toByteArray();
byte[] bshare = piece.getShare().toByteArray();
int blen = 4 + 4 + 4 + 4 + 4 + bmodulus.length + bshare.length;
ByteBuffer bencoded = ByteBuffer.allocate(blen);
final ByteBuffer bencoded = ByteBuffer.allocate(blen);
bencoded.putInt(n).putInt(k).putInt(piece.getX());
bencoded.putInt(bmodulus.length).put(bmodulus);
bencoded.putInt(bshare.length).put(bshare);
@ -281,7 +235,32 @@ public class GenerateFragment extends Fragment implements FragmentSupport {
tv.append("B64Len: " + bencoded64.length() + "\n");
tv.append(bencoded64 + "\n");
tv.append(bencoded + "\n\n");
final String data = "ssss-android:" + bencoded64;
if (i == 0) {
View view = activity.getLayoutInflater().inflate(R.layout.address_qr, null);
final TextView tv = (TextView) view.findViewById(R.id.secret_text);
tv.setText(out[i]);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("ssss-1");
builder.setView(view);
if (PrintHelper.systemSupportsPrint()) {
builder.setPositiveButton(R.string.print, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Renderer.printCode(activity, "sss-1", data);
}
});
builder.setNegativeButton(android.R.string.cancel, null);
} else {
builder.setPositiveButton(android.R.string.ok, null);
}
builder.show();
}
}
this.finished = true;
}
}

View file

@ -0,0 +1,183 @@
package org.surfsite.android.secretshare;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.support.v4.print.PrintHelper;
import android.text.TextPaint;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.aztec.AztecWriter;
import com.google.zxing.common.BitMatrix;
import java.util.ArrayList;
import java.util.Hashtable;
public class Renderer {
private final static AztecWriter sCodeWriter = new AztecWriter();
public static Bitmap createBitmap(String data) {
final Hashtable<EncodeHintType, Object> hints =
new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
BitMatrix result;
final int size = (int) Math.sqrt(data.length() * 8) * 10;
result = sCodeWriter.encode(data,
BarcodeFormat.AZTEC,
size,
size,
hints);
final int width = result.getWidth();
final int height = result.getHeight();
final int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
final int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] =
result.get(x, y) ? Color.BLACK : Color.TRANSPARENT;
}
}
final Bitmap bitmap =
Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
public static void printCode(final Activity context, final String label, final String contents) {
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
TextPaint textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setColor(0xFF000000);
final int bitmapMargin = 100;//big margin is to prevent possible clipping
final int textHeight = 28;
textPaint.setTextSize(textHeight);
textPaint.setTextAlign(Paint.Align.CENTER);
final int codePadding = (int) (textPaint.descent() * 2);
int textWidth = getTextWidth(label, textPaint);
Bitmap codeBitmap = createBitmap(contents);
final int width = Math.max(textWidth, codeBitmap.getWidth());
Bitmap bmp = Bitmap.createBitmap(width + bitmapMargin * 2,
textHeight + codeBitmap.getHeight() + codePadding * 2 + bitmapMargin * 2,
Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setARGB(0xFF, 0xFF, 0xFF, 0xFF);
paint.setAntiAlias(false);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
int centerXForAddress = bitmapMargin + width / 2;
int y = bitmapMargin + codePadding;
Paint codePaint = new Paint();
codePaint.setAntiAlias(false);
codePaint.setDither(false);
canvas.drawBitmap(codeBitmap, centerXForAddress - codeBitmap.getWidth() / 2, y, codePaint);
y += codePadding - textPaint.ascent();
canvas.drawText(label, centerXForAddress, y + codeBitmap.getHeight(), textPaint);
return bmp;
}
@Override
protected void onPostExecute(final Bitmap bitmap) {
if (bitmap != null) {
//DEBUG
// android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(context);
// android.widget.ImageView view = new android.widget.ImageView(context);
// view.setImageBitmap(bitmap);
// builder.setView(view);
// builder.setPositiveButton(android.R.string.ok, null);
// builder.show();
PrintHelper printHelper = new PrintHelper(context);
printHelper.setScaleMode(PrintHelper.SCALE_MODE_FIT);
printHelper.printBitmap(label, bitmap);
}
}
}.execute();
}
private static int getTextWidth(String s, Paint paint) {
Rect bounds = new Rect();
paint.getTextBounds(s, 0, s.length(), bounds);
return bounds.right - bounds.left;
}
public static ArrayList<String> wrap(String txt, int maxWidth, boolean mustFit, Paint paint) {
int pos = 0;
int start = pos;
ArrayList<String> lines = new ArrayList<String>();
while (true) {
int i = pos;
if (txt == null) txt = "";
int len = txt.length();
if (pos >= len) {
break;
}
int startForLineBreak = pos;
while (true) {
while (i < len && txt.charAt(i) != ' ' && txt.charAt(i) != '\n') {
i++;
}
int w = getTextWidth(txt.substring(startForLineBreak, i), paint);
if (pos == startForLineBreak) {
if (w > maxWidth) {
if (mustFit) {
do {
i--;
}
while (getTextWidth(txt.substring(startForLineBreak, i), paint) > maxWidth);
}
pos = i;
break;
}
}
if (w <= maxWidth) {
pos = i;
if (pos >= len)
break;
}
if (w > maxWidth || i >= len || txt.charAt(i) == '\n') {
break;
}
i++;
}
int nextBreak = pos >= len ? len : ++pos;
if (nextBreak >= txt.length()) {
lines.add(txt.substring(start, txt.length()));
} else {
char c = txt.charAt(nextBreak - 1);
if ((c == ' ') || (c == '\n')) {
if (nextBreak - 2 < start) {
lines.add("");
} else {
lines.add(txt.substring(start, nextBreak - 1));
}
} else {
lines.add(txt.substring(start, nextBreak));
}
}
start = pos;
}
return lines;
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/secret_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:gravity="center_horizontal"
android:textSize="16sp"/>
</ScrollView>

View file

@ -6,6 +6,13 @@
android:layout_height="fill_parent"
tools:context="org.surfsite.android.secretshare.GenerateFragment">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="8dp">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@ -19,5 +26,5 @@
android:text="@string/hello_blank_fragment"
/>
</ScrollView>
</LinearLayout>
</FrameLayout>

View file

@ -8,5 +8,6 @@
<string name="string_generate_secrets">Generate Secrets</string>
<string name="string_encrypted_secrets">Encrypted secrets</string>
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="print">Print</string>
</resources>