001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: //-----------------------------------------------------------------------------
028: // PACKAGE DEFINITION
029: //-----------------------------------------------------------------------------
030: package sim.toolkit;
031:
032: //import sat.AccessBuffer;
033:
034: //-----------------------------------------------------------------------------
035: // IMPORTS
036: //-----------------------------------------------------------------------------
037: import javacard.framework.Util;
038: import javacard.framework.ISO7816;
039:
040: /**
041: *
042: * The ViewHandler class offers basic services and contains basic
043: * methods to handle
044: * a Simple TLV List, such as in a <b>Terminal Response</b> data field
045: * or in a BER-TLV
046: * element (<b>Envelope</b> data field or <b>Proactive</b> command).
047: * The byte at offset 0 of a handler is the tag of the first Simple TLV.
048: *
049: * @version 8.3.0
050: *
051: * @see ToolkitException
052: */
053: public abstract class ViewHandler {
054: /** Offset of BER_TLV_TAG. */
055: protected static final byte BER_TLV_TAG_OFFSET = (byte) 5;
056: /** Offset of Lc in the APDU buffer. */
057: protected static final byte OFFSET_LC = (byte) 4;
058: /** Offset of TPDUD. */
059: protected static final byte TPUD_OFFSET = (byte) 12;
060: /** Tag of DEVICE_ID field. */
061: private static final byte DEVICE_ID_TAG = (byte) 0x82;
062: /** Length of DEVICE_ID field. */
063: private static final byte DEVICE_ID_LENGTH = (byte) 0x02;
064: /** Tag of ADDRESS field. */
065: private static final byte ADDRESS_TAG = (byte) 0x06;
066: /** Tag of SMS_TPDU. */
067: private static final byte SMS_TPDU_TAG = (byte) 0x8B;
068:
069: /** Offset of first occurrence of TLV. */
070: short currentTLVOffset;
071: /** Offset of first occurrence of TLV. */
072: short firstTLVOffset;
073:
074: /** Reference to SAT Accessor. */
075: public static AccessSAT SATAccessor;
076:
077: /** Reference to TI which is now serviced. */
078: public static ToolkitInterface currentTI;
079:
080: /**
081: * Constructor.
082: */
083: ViewHandler() {
084: }
085:
086: // ------------------------------- Constructor ---------------------------
087: /**
088: * Builds a new ViewHandler object.
089: *
090: * @param buffer a reference to the TLV buffer
091: * @param offset the position in the TLV buffer
092: * @param length the length of the TLV buffer
093: *
094: * @exception NullPointerException if <code>buffer</code>
095: * is <code>null</code>
096: * @exception ArrayIndexOutOfBoundsException if <code>offset</code>
097: * or <code>length</code> or both would cause access outside array bounds
098: */
099: ViewHandler(byte[] buffer, short offset, short length)
100: throws NullPointerException, ArrayIndexOutOfBoundsException {
101: }
102:
103: // ------------------------------- Public methods -------------------------
104: /**
105: * Returns the length of the TLV list.
106: *
107: * @return length in bytes
108: *
109: * @exception ToolkitException with the following reason codes: <ul>
110: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is
111: * busy</ul>
112: */
113: public short getLength() throws ToolkitException {
114: byte[] buffer = getAPDUBuffer();
115: short length = (short) (buffer[(short) (currentTLVOffset + 1)] & 0xFF);
116: return length;
117: }
118:
119: /**
120: * Copies the simple TLV list contained in the handler to the
121: * destination byte array.
122: *
123: * <p>
124: * Notes:<ul>
125: * <li><em>If </em><code>dstOffset</code><em> or
126: * </em><code>dstLength</code><em> parameter is negative
127: * an </em><code>ArrayIndexOutOfBoundsException</code>
128: * <em> exception is thrown and no copy is performed.</em>
129: * <li><em>If </em><code>dstOffset+dstLength</code><em> is greater
130: * than </em><code>dstBuffer.length</code><em>, the length
131: * of the </em><code>dstBuffer</code><em> array an
132: * </em><code>ArrayIndexOutOfBoundsException</code><em>
133: * exception is thrown and no copy is performed.</em>
134: * </ul>
135: *
136: * @param dstBuffer a reference to the destination buffer
137: * @param dstOffset the position in the destination buffer
138: * @param dstLength the data length to be copied
139: *
140: * @return <code>dstOffset+dstLength</code>
141: *
142: * @exception NullPointerException if <code>dstBuffer</code>
143: * is <code>null</code>
144: * @exception ArrayIndexOutOfBoundsException if copy would
145: * cause access of data outside array bounds.
146: * @exception ToolkitException with the following reason codes: <ul>
147: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
148: * <li><code>OUT_OF_TLV_BOUNDARIES</code> if <code>dstLength</code>
149: * is grater than the length of the simple TLV List.</ul>
150: */
151: public short copy(byte[] dstBuffer, short dstOffset, short dstLength)
152: throws NullPointerException,
153: ArrayIndexOutOfBoundsException, ToolkitException {
154: byte[] buffer = getAPDUBuffer();
155: short TLVLength = (short) (buffer[(short) (currentTLVOffset + 1)] & 0xFF);
156: if (TLVLength < dstLength) {
157: // if length is greater than the TLV length itself, then
158: // throw exception
159: ToolkitException
160: .throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES);
161: }
162: // copy the current TLV list
163: Util.arrayCopy(buffer, (short) (currentTLVOffset + 2),
164: dstBuffer, dstOffset, dstLength);
165: return (short) (dstOffset + dstLength);
166: }
167:
168: /**
169: * Looks for the indicated occurrence of a TLV element from the beginning of
170: * the TLV list (handler buffer). If the method is successful then the
171: * corresponding TLV becomes current, else no TLV is selected.
172: * This search method is Comprehension Required flag independent.
173: *
174: * @param tag the tag of the TLV element to search
175: * @param occurrence the occurrence number of the TLV element (1 for the
176: * first, 2 for the second...)
177: *
178: * @return result of the method: <ul>
179: * <li><code>TLV_NOT_FOUND</code> if the required occurrence of the
180: * TLV element does not exist
181: * <li><code>TLV_FOUND_CR_SET</code> if the required occurrence exists
182: * and Comprehension Required flag is set
183: * <li><code>TLV_FOUND_CR_NOT_SET</code> if the required occurrence
184: * exists and Comprehension Required flag is not set</ul>
185: *
186: * @exception ToolkitException with the following reason codes: <ul>
187: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
188: * <li><code>BAD_INPUT_PARAMETER</code> if an input parameter is not
189: * valid (e.g. occurrence = 0)</ul>
190: */
191: public byte findTLV(byte tag, byte occurrence)
192: throws ToolkitException {
193: byte count = 0; // count of occurances
194: byte[] buffer = getAPDUBuffer();
195: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
196: short TLVOffset = getTLVOffset(buffer, tag, Lc, occurrence);
197: if (TLVOffset >= Lc)
198: return ToolkitConstants.TLV_NOT_FOUND; // not found
199:
200: currentTLVOffset = TLVOffset;
201: if ((byte) (buffer[TLVOffset] & ToolkitConstants.TAG_SET_CR) == ToolkitConstants.TAG_SET_CR)
202: return ToolkitConstants.TLV_FOUND_CR_SET;
203:
204: return ToolkitConstants.TLV_FOUND_CR_NOT_SET;
205: }
206:
207: /**
208: * Gets the binary length of the value field for the last TLV element
209: * which has been found in the handler.
210: *
211: * @return length of the value field
212: *
213: * @exception ToolkitException with the following reason codes: <ul>
214: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
215: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
216: * TLV element</ul>
217: */
218: public short getValueLength() throws ToolkitException {
219: byte[] buffer = getAPDUBuffer();
220: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
221: short TLVOffset = getLastTLVOffset(buffer, Lc);
222: if (TLVOffset >= Lc) {
223: ToolkitException
224: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
225: }
226: return (short) (buffer[(short) (TLVOffset + 1)] & 0xFF); // return the length
227: }
228:
229: /**
230: * Gets a byte from the last TLV element which has been found in the
231: * handler.
232: *
233: * @param valueOffset the offset of the byte to return in the TLV element
234: *
235: * @return element value (1 byte)
236: *
237: * @exception ToolkitException with the following reason codes: <ul>
238: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
239: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable TLV
240: * element
241: * <li><code>OUT_OF_TLV_BOUNDARIES</code> if
242: * <code>valueOffset</code> is out of the current TLV </ul>
243: */
244: public byte getValueByte(short valueOffset) throws ToolkitException {
245: byte[] buffer = getAPDUBuffer();
246: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
247: short TLVOffset = getLastTLVOffset(buffer, Lc);
248: if (TLVOffset >= Lc) {
249: ToolkitException
250: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
251: }
252: short TLVLength = (short) (buffer[(short) (TLVOffset + 1)] & 0xFF);
253: if (valueOffset > TLVLength) {
254: ToolkitException
255: .throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES);
256: }
257: // return the byte at offset
258: return buffer[(short) (TLVOffset + 2 + valueOffset)];
259: }
260:
261: /**
262: * Copies a part of the last TLV element which has been found, into a
263: * destination buffer.
264: *
265: * <p>
266: * Notes:<ul>
267: * <li><em>If </em><code>dstOffset</code><em> or
268: * </em><code>dstLength</code><em> parameter is negative an
269: * </em><code>ArrayIndexOutOfBoundsException</code>
270: * <em> exception is thrown and no copy is performed.</em>
271: * <li><em>If </em><code>dstOffset+dstLength</code><em> is
272: * greater than </em><code>dstBuffer.length</code><em>, the length
273: * of the </em><code>dstBuffer</code><em> array an
274: * </em><code>ArrayIndexOutOfBoundsException</code><em> exception
275: * is thrown and no copy is performed.</em>
276: * </ul>
277: *
278: * @param valueOffset the offset of the first byte in the source
279: * TLV element
280: * @param dstBuffer a reference to the destination buffer
281: * @param dstOffset the position in the destination buffer
282: * @param dstLength the data length to be copied
283: *
284: * @return <code>dstOffset+dstLength</code>
285: *
286: * @exception NullPointerException if <code>dstBuffer</code> is
287: * <code>null</code>
288: * @exception ArrayIndexOutOfBoundsException if copyValue would
289: * cause access of data outside array bounds.
290: * @exception ToolkitException with the following reason codes: <ul>
291: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
292: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
293: * TLV element
294: * <li><code>OUT_OF_TLV_BOUNDARIES</code> if:
295: * <ul>
296: * <li><code>valueOffset</code> parameter is negative or
297: * <li><code>valueOffset + dstLength</code> is greater than
298: * the length of the current TLV
299: * </ul>
300: * </ul>
301: */
302: public short copyValue(short valueOffset, byte[] dstBuffer,
303: short dstOffset, short dstLength)
304: throws NullPointerException,
305: ArrayIndexOutOfBoundsException, ToolkitException {
306: byte[] buffer = getAPDUBuffer();
307: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
308: short TLVOffset = getLastTLVOffset(buffer, Lc);
309: if (TLVOffset >= Lc) {
310: ToolkitException
311: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
312: }
313: short TLVLength = (short) (buffer[(short) (TLVOffset + 1)] & 0xFF);
314: if (valueOffset > TLVLength || valueOffset < 0) {
315: ToolkitException
316: .throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES);
317: }
318: Util.arrayCopy(buffer,
319: (short) (currentTLVOffset + 2 + valueOffset),
320: dstBuffer, dstOffset, dstLength);
321: return buffer[(short) (TLVOffset + 2 + valueOffset)];
322: }
323:
324: /**
325: * Compares the last found TLV element with a buffer.
326: *
327: * <p>
328: * Notes:<ul>
329: * <li><em>If </em><code>compareOffset</code><em> or
330: * </em><code>compareLength</code><em> parameter is negative
331: * an </em><code>ArrayIndexOutOfBoundsException</code>
332: * <em> exception is thrown and no compare is performed.</em>
333: * <li><em>If </em><code>compareOffset+compareLength</code><em>is
334: * greater than </em><code>compareBuffer.length</code><em>, the length
335: * of the </em><code>compareBuffer</code><em> array an
336: * </em><code>ArrayIndexOutOfBoundsException</code><em> exception
337: * is thrown and no compare is performed.</em>
338: * </ul>
339: *
340: * @param valueOffset the offset of the first byte to compare in
341: * the TLV element
342: * @param compareBuffer a reference to the comparison buffer
343: * @param compareOffset the position in the comparison buffer
344: * @param compareLength the length to be compared
345: *
346: * @return the result of the comparison as follows: <ul>
347: * <li><code>0</code> if identical
348: * <li><code>-1</code> if the first miscomparing byte in simple
349: * TLV List is less than that in <code>compareBuffer</code>,
350: * <li><code>1</code> if the first miscomparing byte in simple
351: * TLV List is greater than that in <code>compareBuffer</code>.</ul>
352: *
353: * @exception NullPointerException if <code>compareBuffer</code> is
354: * <code>null</code>
355: * @exception ArrayIndexOutOfBoundsException if compareValue would
356: * cause access of data outside array bounds.
357: * @exception ToolkitException with the following reason codes: <ul>
358: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
359: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
360: * TLV element
361: * <li><code>OUT_OF_TLV_BOUNDARIES</code> if:
362: * <ul>
363: * <li><code>valueOffset</code> parameter is negative or
364: * <li><code>valueOffset + compareLength</code> is greater
365: * than the length of the current TLV
366: * </ul>
367: * </ul>
368: */
369: public byte compareValue(short valueOffset, byte[] compareBuffer,
370: short compareOffset, short compareLength)
371: throws NullPointerException,
372: ArrayIndexOutOfBoundsException, ToolkitException {
373: byte[] buffer = getAPDUBuffer();
374: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
375: short TLVOffset = getLastTLVOffset(buffer, Lc);
376: if (TLVOffset >= Lc) {
377: ToolkitException
378: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
379: }
380: short TLVLength = (short) (buffer[(short) (TLVOffset + 1)] & 0xFF);
381: if (valueOffset > TLVLength || valueOffset < 0) {
382: ToolkitException
383: .throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES);
384: }
385: return Util.arrayCompare(buffer,
386: (short) (currentTLVOffset + 2 + valueOffset),
387: compareBuffer, compareOffset, compareLength);
388: }
389:
390: /**
391: * Looks for the first occurrence of a TLV element from the beginning
392: * of a TLV
393: * list and copy its value into a destination buffer.
394: * If no TLV element is found, the <code>UNAVAILABLE_ELEMENT</code>
395: * exception is thrown.
396: * If the method is successful then the corresponding TLV becomes current,
397: * else no TLV is selected.
398: * This search method is Comprehension Required flag independent.
399: *
400: * <p>
401: * Notes:<ul>
402: * <li><em>If </em><code>dstOffset</code><em> parameter is negative or
403: * </em><code>dstOffset</code>
404: * <em> is greater than </em><code>dstBuffer.length</code><em>, the
405: * length of the </em><code>dstBuffer</code>
406: * <em> array an </em><code>ArrayIndexOutOfBoundsException</code><em>
407: * exception is thrown and no find is performed.</em>
408: * </ul>
409: *
410: * @param tag the tag of the TLV element to search
411: * @param dstBuffer a reference to the destination buffer
412: * @param dstOffset the position in the destination buffer
413: *
414: * @return <code>dstOffset</code> + length of the copied value
415: *
416: * @exception NullPointerException if <code>dstBuffer</code>
417: * is <code>null</code>
418: * @exception ArrayIndexOutOfBoundsException if findAndCopyValue
419: * would cause access of data outside array bounds.
420: * @exception ToolkitException with the following reason codes: <ul>
421: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
422: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
423: * TLV element</ul>
424: */
425: public short findAndCopyValue(byte tag, byte[] dstBuffer,
426: short dstOffset) throws NullPointerException,
427: ArrayIndexOutOfBoundsException, ToolkitException {
428: // this method could potentialy use the other
429: // findAndCopyValue() method. The only problem is the length
430: // parameter required by that method
431:
432: byte[] buffer = getAPDUBuffer();
433: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
434: short TLVOffset = getTLVOffset(buffer, tag, Lc, (short) 1);
435:
436: if (TLVOffset >= Lc) {
437: // TLV not found
438: ToolkitException
439: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
440: }
441: currentTLVOffset = TLVOffset;
442: short length = buffer[(short) (TLVOffset + 1)];
443: Util.arrayCopy(buffer, (short) (TLVOffset + 2), dstBuffer,
444: dstOffset, length);
445: return (short) (dstOffset + length);
446: }
447:
448: /**
449: * Looks for the indicated occurrence of a TLV element from the
450: * beginning of a TLV
451: * list and copy its value into a destination buffer.
452: * If no TLV element is found, the <code>UNAVAILABLE_ELEMENT</code>
453: * exception is thrown.
454: * If the method is successful then the corresponding TLV becomes current,
455: * else no TLV is selected.
456: * This search method is Comprehension Required flag independent.
457: *
458: * <p>
459: * Notes:<ul>
460: * <li><em>If </em><code>dstOffset</code><em> or
461: * </em><code>dstLength</code><em> parameter is negative
462: * an </em><code>ArrayIndexOutOfBoundsException</code>
463: * <em> exception is thrown and no copy is performed.</em>
464: * <li><em>If </em><code>dstOffset+dstLength</code><em>is greater
465: * than </em><code>dstBuffer.length</code><em>, the length
466: * of the </em><code>dstBuffer</code><em> array an
467: * </em><code>ArrayIndexOutOfBoundsException</code><em> exception
468: * is thrown and no copy is performed.</em>
469: * </ul>
470: *
471: * @param tag the tag of the TLV element to search
472: * @param occurrence the occurrence number of the TLV element
473: * (1 for the first, 2 for the second...)
474: * @param valueOffset the offset of the first byte in the source
475: * TLV element
476: * @param dstBuffer a reference to the destination buffer
477: * @param dstOffset the position in the destination buffer
478: * @param dstLength the data length to be copied
479: *
480: * @return <code>dstOffset + dstLength</code>
481: *
482: * @exception NullPointerException if <code>dstBuffer</code> is
483: * <code>null</code>
484: * @exception ArrayIndexOutOfBoundsException if findAndCopyValue
485: * would cause access of data outside array bounds.
486: * @exception ToolkitException with the following reason codes: <ul>
487: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
488: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
489: * TLV element
490: * <li><code>OUT_OF_TLV_BOUNDARIES</code> if:
491: * <ul>
492: * <li><code>valueOffset</code> parameter is negative or
493: * <li><code>valueOffset + dstLength</code> is greater
494: * than the length of the current TLV
495: * </ul>
496: * <li><code>BAD_INPUT_PARAMETER</code> if an input parameter
497: * is not valid (e.g. occurrence = 0)</ul>
498: */
499: public short findAndCopyValue(byte tag, byte occurrence,
500: short valueOffset, byte[] dstBuffer, short dstOffset,
501: short dstLength) throws NullPointerException,
502: ArrayIndexOutOfBoundsException, ToolkitException {
503:
504: byte[] buffer = getAPDUBuffer();
505: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
506: short TLVOffset = getTLVOffset(buffer, tag, Lc, occurrence);
507:
508: if (TLVOffset >= Lc) {
509: // TLV not found
510: ToolkitException
511: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
512: }
513: // this is the current TLV
514: currentTLVOffset = TLVOffset;
515: short length = buffer[(short) (TLVOffset + 1)];
516: if ((valueOffset < 0)
517: || (short) (valueOffset + dstLength) > length) {
518: ToolkitException
519: .throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES);
520: }
521: Util.arrayCopy(buffer, (short) (TLVOffset + 2 + valueOffset),
522: dstBuffer, dstOffset, dstLength);
523: return (short) (dstOffset + length);
524:
525: }
526:
527: /**
528: * Looks for the first occurrence of a TLV element
529: * from beginning of a TLV
530: * list and compare its value with a buffer.
531: * If no TLV element is found, the
532: * <code>UNAVAILABLE_ELEMENT</code> exception is thrown.
533: * If the method is successful then the corresponding TLV
534: * becomes current, else no TLV is selected.
535: * This search method is Comprehension Required flag independent.
536: *
537: * <p>
538: * Notes:<ul>
539: * <li><em>If </em><code>compareOffset</code><em> parameter is
540: * negative or </em><code>compareOffset</code>
541: * <em> is greater than </em><code>compareBuffer.length</code><em>,
542: * the length of the </em><code>compareBuffer</code>
543: * <em> array an </em><code>ArrayIndexOutOfBoundsException</code><em>
544: * exception is thrown and no find is performed.</em>
545: * </ul>
546: *
547: * @param tag the tag of the TLV element to search
548: * @param compareBuffer a reference to the comparison buffer
549: * @param compareOffset the position in the comparison buffer
550: *
551: * @return the result of the comparison as follows: <ul>
552: * <li><code>0</code> if identical
553: * <li><code>-1</code> if the first miscomparing byte in simple
554: * TLV is less than that in <code>compareBuffer</code>,
555: * <li><code>1</code> if the first miscomparing byte in simple
556: * TLV is greater than that in <code>compareBuffer</code>.</ul>
557: *
558: * @exception NullPointerException if <code>compareBuffer</code> is
559: * <code>null</code>
560: * @exception ArrayIndexOutOfBoundsException if findAndCompareValue
561: * would cause access of data outside array bounds.
562: * @exception ToolkitException with the following reason codes: <ul>
563: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
564: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
565: * TLV element</ul>
566: */
567: public byte findAndCompareValue(byte tag, byte[] compareBuffer,
568: short compareOffset) throws NullPointerException,
569: ArrayIndexOutOfBoundsException, ToolkitException {
570: byte[] buffer = getAPDUBuffer();
571: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
572: short TLVOffset = getTLVOffset(buffer, tag, Lc, (byte) 1);
573:
574: if (TLVOffset >= Lc) {
575: // TLV not found
576: ToolkitException
577: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
578: }
579: // this is the current TLV
580: currentTLVOffset = TLVOffset;
581: short length = buffer[(short) (TLVOffset + 1)];
582: return Util.arrayCompare(buffer, (short) (TLVOffset + 2),
583: compareBuffer, compareOffset, length);
584: }
585:
586: /**
587: * Looks for the indicated occurrence of a TLV element from the
588: * beginning of a TLV list and compare its value with a buffer.
589: * If no TLV element is found, the <code>UNAVAILABLE_ELEMENT</code>
590: * exception is thrown.
591: * If the method is successful then the corresponding TLV becomes
592: * current, else no TLV is selected.
593: * This search method is Comprehension Required flag independent.
594: *
595: * <p>
596: * Notes:<ul>
597: * <li><em>If </em><code>compareOffset</code><em> or
598: * </em><code>compareLength</code><em> parameter is
599: * negative an </em><code>ArrayIndexOutOfBoundsException</code>
600: * <em> exception is thrown and no find and compare is performed.</em>
601: * <li><em>If </em><code>compareOffset+compareLength</code><em> is
602: * greater than </em><code>compareBuffer.length</code><em>, the length
603: * of the </em><code>compareBuffer</code><em> array an
604: * </em><code>ArrayIndexOutOfBoundsException</code><em> exception
605: * is thrown and no find and compare is performed.</em>
606: * </ul>
607: *
608: * @param tag the tag of the TLV element to search
609: * @param occurrence the occurrence number of the TLV element
610: * (1 for the first, 2 for the second...)
611: * @param valueOffset the offset of the first byte in the source
612: * TLV element
613: * @param compareBuffer a reference to the comparison buffer
614: * @param compareOffset the position in the comparison buffer
615: * @param compareLength the length to be compared
616: *
617: * @return the result of the comparison as follows: <ul>
618: * <li><code>0</code> if identical
619: * <li><code>-1</code> if the first miscomparing byte in
620: * simple TLV is less than that in <code>compareBuffer</code>,
621: * <li><code>1</code> if the first miscomparing byte in simple
622: * TLV is greater than that in <code>compareBuffer</code>.</ul>
623: *
624: * @exception NullPointerException if <code>compareBuffer</code>
625: * is <code>null</code>
626: * @exception ArrayIndexOutOfBoundsException if findAndCompareValue
627: * would cause access of data outside array bounds.
628: * @exception ToolkitException with the following reason codes: <ul>
629: * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy
630: * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable
631: * TLV element
632: * <li><code>OUT_OF_TLV_BOUNDARIES</code> if:
633: * <ul>
634: * <li><code>valueOffset</code> parameter is negative or
635: * <li><code>valueOffset + compareLength</code> is greater
636: * than the length of the current TLV
637: * </ul>
638: * <li><code>BAD_INPUT_PARAMETER</code> if an input parameter is
639: * not valid (e.g. occurrence = 0)</ul>
640: */
641: public byte findAndCompareValue(byte tag, byte occurrence,
642: short valueOffset, byte[] compareBuffer,
643: short compareOffset, short compareLength)
644: throws NullPointerException,
645: ArrayIndexOutOfBoundsException, ToolkitException {
646: byte[] buffer = getAPDUBuffer();
647: short Lc = (short) (buffer[OFFSET_LC] & 0xFF);
648: short TLVOffset = getTLVOffset(buffer, tag, Lc, occurrence);
649:
650: if (TLVOffset >= Lc) {
651: // TLV not found
652: ToolkitException
653: .throwIt(ToolkitException.UNAVAILABLE_ELEMENT);
654: }
655: // this is the current TLV
656: currentTLVOffset = TLVOffset;
657: short length = buffer[(short) (TLVOffset + 1)];
658: if ((valueOffset < 0)
659: || (short) (valueOffset + compareLength) > length) {
660: ToolkitException
661: .throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES);
662: }
663: return Util.arrayCompare(buffer,
664: (short) (TLVOffset + 2 + valueOffset), compareBuffer,
665: compareOffset, compareLength);
666: }
667:
668: /**
669: * Helper method for <code>findAndCompareValue</code>.
670: * @param buffer APDU buffer
671: * @param tag What tag we are finding
672: * @param Lc Length of command data
673: * @param occurrence The occurrence number of the TLV element
674: * @return Offset of the tag
675: */
676: protected short getTLVOffset(byte[] buffer, byte tag, short Lc,
677: short occurrence) {
678: byte count = 0; // count of occurances
679: short offset = firstTLVOffset;
680: tag = (byte) (tag & 0x7F);
681: while (offset < Lc) {
682: if ((byte) (buffer[offset] & 0x7F) == tag) {
683: count++;
684: if (count != occurrence) {
685: continue;
686: }
687: return offset;
688: } else {
689: // advance to next TLV
690: offset++;
691: short length = buffer[offset];
692: offset = (short) (offset + length + 1);
693: }
694: }
695: return offset; // not found
696: }
697:
698: /**
699: * Helper method for <code>getValue...</code> and
700: * <code>copyValue...</code>.
701: * @param buffer APDU buffer
702: * @param Lc Length of command data
703: * @return Offset of the tag
704: */
705: protected short getLastTLVOffset(byte[] buffer, short Lc) {
706: short offset = firstTLVOffset;
707: short lastTLVOffset;
708: do {
709: lastTLVOffset = offset;
710: // advance to next TLV
711: offset++;
712: short length = buffer[offset];
713: offset = (short) (offset + length + 1);
714: } while (offset < Lc);
715: return lastTLVOffset;
716: }
717:
718: /**
719: * Copies the APDUBuffer content into provided buffer.
720: * @param buffer The buffer
721: * @return Provided buffer filled with APDUBuffer content
722: */
723: public static byte[] getAPDUBuffer(byte[] buffer) {
724: short len = SATAccessor.getAPDUBufferLength();
725:
726: for (short i = 0; i < len; i++) {
727: buffer[i] = SATAccessor.getAPDUBufferByte(i);
728: }
729: return buffer;
730: }
731:
732: /**
733: * Copies the APDUBuffer content into current buffer.
734: * @return apdu buffer
735: */
736: public static byte[] getAPDUBuffer() {
737: return getAPDUBuffer(currentTI.getAPDUBuffer());
738: }
739:
740: /**
741: * Copies content of provided buffer into the APDUBuffer.
742: * @param buffer The buffer
743: * @param length Length of the buffer
744: */
745: public static void setAPDUBuffer(byte[] buffer, short length) {
746:
747: for (short i = 0; i < length; i++) {
748: SATAccessor.setAPDUBufferByte(i, buffer[i]);
749: }
750: }
751:
752: /**
753: * Copies content of current buffer into the APDUBuffer.
754: * @param length Length of the current buffer
755: */
756: public static void setAPDUBuffer(short length) {
757: setAPDUBuffer(currentTI.getAPDUBuffer(), length);
758: }
759:
760: /**
761: * Sets the data in the out buffer.
762: * @param length Length of data
763: */
764: public static void setOutBufferData(short length) {
765: setAPDUBuffer(length);
766: SATAccessor.setOutBufferData(length);
767: }
768: }
|