DerInputBuffer.java revision 51b1b6997fd3f980076b8081f7f1165ccc2a4008
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.util; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ByteArrayInputStream; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.math.BigInteger; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.util.calendar.CalendarDate; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.util.calendar.CalendarSystem; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DER input buffer ... this is the main abstraction in the DER library 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which actively works with the "untyped byte stream" abstraction. It 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * does so with impunity, since it's not intended to be exposed to 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * anyone who could violate the "typed value stream" DER model and hence 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * corrupt the input stream of DER values. 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author David Brownell 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass DerInputBuffer extends ByteArrayInputStream implements Cloneable { 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer(byte[] buf) { super(buf); } 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer(byte[] buf, int offset, int len) { 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski super(buf, offset, len); 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer dup() { 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer retval = (DerInputBuffer)clone(); 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval.mark(Integer.MAX_VALUE); 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (CloneNotSupportedException e) { 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(e.toString()); 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] toByteArray() { 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = available(); 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len <= 0) 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[len]; 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos, retval, 0, len); 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int peek() throws IOException { 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= count) 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("out of data"); 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buf[pos]; 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Compares this DerInputBuffer for equality with the specified 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object. 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean equals(Object other) { 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (other instanceof DerInputBuffer) 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return equals((DerInputBuffer)other); 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean equals(DerInputBuffer other) { 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (this == other) 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int max = this.available(); 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (other.available() != max) 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < max; i++) { 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (this.buf[this.pos + i] != other.buf[other.pos + i]) { 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a hashcode for this DerInputBuffer. 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a hashcode for this DerInputBuffer. 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode() { 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int retval = 0; 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = available(); 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int p = pos; 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < len; i++) 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval += buf[p + i] * i; 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void truncate(int len) throws IOException { 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("insufficient data"); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = pos + len; 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the integer which takes up the specified number 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of bytes in this buffer as a BigInteger. 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use. 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param makePositive whether to always return a positive value, 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * irrespective of actual encoding 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer as a BigInteger. 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BigInteger getBigInteger(int len, boolean makePositive) throws IOException { 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of integer"); 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) { 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid encoding: zero length Int value"); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] bytes = new byte[len]; 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos, bytes, 0, len); 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski skip(len); 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (makePositive) { 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new BigInteger(1, bytes); 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new BigInteger(bytes); 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the integer which takes up the specified number 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of bytes in this buffer. 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the result is not within the valid 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range for integer, i.e. between Integer.MIN_VALUE and 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Integer.MAX_VALUE. 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use. 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer. 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getInteger(int len) throws IOException { 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BigInteger result = getBigInteger(len, false); 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (result.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0) { 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Integer below minimum valid value"); 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (result.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Integer exceeds maximum valid value"); 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return result.intValue(); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the bit string which takes up the specified 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * number of bytes in this buffer. 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getBitString(int len) throws IOException { 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of bit string"); 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid encoding: zero length bit string"); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numOfPadBits = buf[pos]; 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((numOfPadBits < 0) || (numOfPadBits > 7)) { 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid number of padding bits"); 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // minus the first byte which indicates the number of padding bits 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[len - 1]; 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos + 1, retval, 0, len - 1); 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numOfPadBits != 0) { 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // get rid of the padding bits 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval[len - 2] &= (0xff << numOfPadBits); 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski skip(len); 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the bit string which takes up the rest of this buffer. 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] getBitString() throws IOException { 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getBitString(available()); 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the bit string which takes up the rest of this buffer. 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The bit string need not be byte-aligned. 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BitArray getUnalignedBitString() throws IOException { 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= count) 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Just copy the data into an aligned, padded octet buffer, 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and consume the rest of the buffer. 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = available(); 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int unusedBits = buf[pos] & 0xff; 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (unusedBits > 7 ) { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid value for unused bits: " + unusedBits); 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] bits = new byte[len - 1]; 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // number of valid bits 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = (bits.length == 0) ? 0 : bits.length * 8 - unusedBits; 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos + 1, bits, 0, len - 1); 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BitArray bitArray = new BitArray(length, bits); 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = count; 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bitArray; 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the UTC Time value that takes up the specified number 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of bytes in this buffer. 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getUTCTime(int len) throws IOException { 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER UTC Time"); 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len < 11 || len > 17) 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER UTC Time length error"); 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getTime(len, false); 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the Generalized Time value that takes up the specified 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * number of bytes in this buffer. 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getGeneralizedTime(int len) throws IOException { 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER Generalized Time"); 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len < 13 || len > 23) 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER Generalized Time length error"); 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getTime(len, true); 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine to extract time from the der value. 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param generalized true if Generalized Time is to be read, false 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if UTC Time is to be read. 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Date getTime(int len, boolean generalized) throws IOException { 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTC time encoded as ASCII chars: 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmZ 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmssZ 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmm+hhmm 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmm-hhmm 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmss+hhmm 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmss-hhmm 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTC Time is broken in storing only two digits of year. 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If YY < 50, we assume 20YY; 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if YY >= 50, we assume 19YY, as per RFC 3280. 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Generalized time has a four-digit year and allows any 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * precision specified in ISO 8601. However, for our purposes, 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * we will only allow the same format as UTC time, except that 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fractional seconds (millisecond precision) are supported. 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int year, month, day, hour, minute, second, millis; 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String type = null; 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (generalized) { 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski type = "Generalized"; 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year = 1000 * Character.digit((char)buf[pos++], 10); 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 100 * Character.digit((char)buf[pos++], 10); 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 10 * Character.digit((char)buf[pos++], 10); 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += Character.digit((char)buf[pos++], 10); 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= 2; // For the two extra YY 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski type = "UTC"; 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year = 10 * Character.digit((char)buf[pos++], 10); 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += Character.digit((char)buf[pos++], 10); 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (year < 50) // origin 2000 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 2000; 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 1900; // origin 1900 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski month = 10 * Character.digit((char)buf[pos++], 10); 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski month += Character.digit((char)buf[pos++], 10); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski day = 10 * Character.digit((char)buf[pos++], 10); 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski day += Character.digit((char)buf[pos++], 10); 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hour = 10 * Character.digit((char)buf[pos++], 10); 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hour += Character.digit((char)buf[pos++], 10); 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minute = 10 * Character.digit((char)buf[pos++], 10); 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minute += Character.digit((char)buf[pos++], 10); 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= 10; // YYMMDDhhmm 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * We allow for non-encoded seconds, even though the 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IETF-PKIX specification says that the seconds should 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * always be encoded even if it is zero. 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis = 0; 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > 2 && len < 12) { 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski second = 10 * Character.digit((char)buf[pos++], 10); 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski second += Character.digit((char)buf[pos++], 10); 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= 2; 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // handle fractional seconds (if present) 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buf[pos] == '.' || buf[pos] == ',') { 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len --; 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos++; 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // handle upto milisecond precision only 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int precision = 0; 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int peek = pos; 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (buf[peek] != 'Z' && 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[peek] != '+' && 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[peek] != '-') { 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski peek++; 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski precision++; 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (precision) { 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 3: 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 100 * Character.digit((char)buf[pos++], 10); 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 10 * Character.digit((char)buf[pos++], 10); 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += Character.digit((char)buf[pos++], 10); 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 2: 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 100 * Character.digit((char)buf[pos++], 10); 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 10 * Character.digit((char)buf[pos++], 10); 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 1: 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 100 * Character.digit((char)buf[pos++], 10); 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " time, unsupported precision for seconds value"); 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= precision; 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski second = 0; 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (month == 0 || day == 0 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || month > 12 || day > 31 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || hour >= 24 || minute >= 60 || second >= 60) 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, invalid format"); 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Generalized time can theoretically allow any precision, 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * but we're not supporting that. 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarSystem gcal = CalendarSystem.getGregorianCalendar(); 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarDate date = gcal.newCalendarDate(null); // no time zone 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski date.setDate(year, month, day); 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski date.setTimeOfDay(hour, minute, second, millis); 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long time = gcal.getTime(date); 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (! (len == 1 || len == 5)) 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, invalid offset"); 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int hr, min; 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (buf[pos++]) { 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case '+': 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr = 10 * Character.digit((char)buf[pos++], 10); 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr += Character.digit((char)buf[pos++], 10); 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min = 10 * Character.digit((char)buf[pos++], 10); 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min += Character.digit((char)buf[pos++], 10); 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hr >= 24 || min >= 60) 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, +hhmm"); 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski time -= ((hr * 60) + min) * 60 * 1000; 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case '-': 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr = 10 * Character.digit((char)buf[pos++], 10); 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr += Character.digit((char)buf[pos++], 10); 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min = 10 * Character.digit((char)buf[pos++], 10); 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min += Character.digit((char)buf[pos++], 10); 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hr >= 24 || min >= 60) 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, -hhmm"); 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski time += ((hr * 60) + min) * 60 * 1000; 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 'Z': 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, garbage offset"); 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new Date(time); 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 434