4 * Copyright (C) 2011 Eric Butler
7 * Eric Butler <eric@codebutler.com>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 package com.codebutler.farebot;
25 import android.app.Activity;
26 import android.app.AlertDialog;
27 import android.content.DialogInterface;
28 import android.util.Log;
29 import android.view.WindowManager;
31 import com.codebutler.farebot.card.desfire.DesfireException;
32 import com.codebutler.farebot.card.desfire.DesfireFileSettings;
33 import com.codebutler.farebot.card.desfire.DesfireProtocol;
35 import org.w3c.dom.Node;
37 import java.io.StringWriter;
38 import java.util.List;
40 import javax.xml.transform.OutputKeys;
41 import javax.xml.transform.Result;
42 import javax.xml.transform.Source;
43 import javax.xml.transform.Transformer;
44 import javax.xml.transform.TransformerFactory;
45 import javax.xml.transform.dom.DOMSource;
46 import javax.xml.transform.stream.StreamResult;
50 private static final String TAG = Utils.class.getName();
52 public static void showError (final Activity activity, Exception ex) {
53 Log.e(activity.getClass().getName(), ex.getMessage(), ex);
54 new AlertDialog.Builder(activity)
55 .setMessage(Utils.getErrorMessage(ex))
59 public static void showErrorAndFinish (final Activity activity, Exception ex) {
61 Log.e(activity.getClass().getName(), Utils.getErrorMessage(ex));
64 new AlertDialog.Builder(activity)
65 .setMessage(Utils.getErrorMessage(ex))
67 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
68 public void onClick(DialogInterface arg0, int arg1) {
73 } catch (WindowManager.BadTokenException unused) {
74 /* Ignore... happens if the activity was destroyed */
78 public static String getHexString (byte[] b) throws Exception {
80 for (int i=0; i < b.length; i++) {
81 result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
86 public static String getHexString (byte[] b, String defaultResult) {
88 return getHexString(b);
89 } catch (Exception ex) {
94 public static byte[] hexStringToByteArray (String s) {
95 if ((s.length() % 2) != 0) {
96 throw new IllegalArgumentException("Bad input string: " + s);
100 byte[] data = new byte[len / 2];
101 for (int i = 0; i < len; i += 2) {
102 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
103 + Character.digit(s.charAt(i+1), 16));
109 public static byte[] intToByteArray(int value) {
111 (byte)(value >>> 24),
112 (byte)(value >>> 16),
118 public static int byteArrayToInt(byte[] b) {
119 return byteArrayToInt(b, 0);
122 public static int byteArrayToInt(byte[] b, int offset) {
123 return byteArrayToInt(b, offset, b.length);
126 public static int byteArrayToInt(byte[] b, int offset, int length) {
127 return (int) byteArrayToLong(b, offset, length);
130 public static long byteArrayToLong(byte[] b, int offset, int length) {
131 if (b.length < length)
132 throw new IllegalArgumentException("length must be less than or equal to b.length");
135 for (int i = 0; i < length; i++) {
136 int shift = (length - 1 - i) * 8;
137 value += (b[i + offset] & 0x000000FF) << shift;
142 public static byte[] byteArraySlice(byte[] b, int offset, int length) {
143 byte[] ret = new byte[length];
144 for (int i = 0; i < length; i++)
145 ret[i] = b[offset+i];
149 public static String xmlNodeToString (Node node) throws Exception {
150 // The amount of code required to do simple things in Java is incredible.
151 Source source = new DOMSource(node);
152 StringWriter stringWriter = new StringWriter();
153 Result result = new StreamResult(stringWriter);
154 TransformerFactory factory = TransformerFactory.newInstance();
155 Transformer transformer = factory.newTransformer();
156 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
157 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
158 transformer.setURIResolver(null);
159 transformer.transform(source, result);
160 return stringWriter.getBuffer().toString();
163 public static String getErrorMessage (Throwable ex) {
164 String errorMessage = ex.getLocalizedMessage();
165 if (errorMessage == null)
166 errorMessage = ex.getMessage();
167 if (errorMessage == null)
168 errorMessage = ex.toString();
170 if (ex.getCause() != null) {
171 String causeMessage = ex.getCause().getLocalizedMessage();
172 if (causeMessage == null)
173 causeMessage = ex.getCause().getMessage();
174 if (causeMessage == null)
175 causeMessage = ex.getCause().toString();
177 if (causeMessage != null)
178 errorMessage += ": " + causeMessage;
185 public static <T> T findInList(List<T> list, Matcher<T> matcher) {
186 for (T item : list) {
187 if (matcher.matches(item)) {
194 public static interface Matcher<T> {
195 public boolean matches(T t);
198 public static int convertBCDtoInteger(byte data) {
199 return (((data & (char)0xF0) >> 4) * 10) + ((data & (char)0x0F));
202 public static int getBitsFromInteger(int buffer, int iStartBit, int iLength) {
203 return (buffer >> (iStartBit)) & ((char)0xFF >> (8 - iLength));
206 /* Based on function from mfocGUI by 'Huuf' (http://www.huuf.info/OV/) */
207 public static int getBitsFromBuffer(byte[] buffer, int iStartBit, int iLength) {
208 int iEndBit = iStartBit + iLength - 1;
209 int iSByte = iStartBit / 8;
210 int iSBit = iStartBit % 8;
211 int iEByte = iEndBit / 8;
212 int iEBit = iEndBit % 8;
214 if (iSByte == iEByte) {
215 return (int)(((char)buffer[iEByte] >> (7 - iEBit)) & ((char)0xFF >> (8 - iLength)));
217 int uRet = (((char)buffer[iSByte] & (char)((char)0xFF >> iSBit)) << (((iEByte - iSByte - 1) * 8) + (iEBit + 1)));
219 for (int i = iSByte + 1; i < iEByte; i++) {
220 uRet |= (((char)buffer[i] & (char)0xFF) << (((iEByte - i - 1) * 8) + (iEBit + 1)));
223 uRet |= (((char)buffer[iEByte] & (char)0xFF)) >> (7 - iEBit);
230 public static DesfireFileSettings selectAppFile(DesfireProtocol tag, int appID, int fileID) {
232 tag.selectApp(appID);
233 } catch (DesfireException e) {
234 Log.w(TAG,"App not found");
238 return tag.getFileSettings(fileID);
239 } catch (DesfireException e) {
240 Log.w(TAG,"File not found");
245 public static boolean arrayContains(int[] arr, int item) {
252 public static boolean containsAppFile(DesfireProtocol tag, int appID, int fileID) {
254 tag.selectApp(appID);
255 } catch (DesfireException e) {
256 Log.w(TAG,"App not found");
261 return arrayContains(tag.getFileList(),fileID);
262 } catch (DesfireException e) {
263 Log.w(TAG,"File not found");