DerInputBuffer.java revision ddde3e18b22acdaecb883794f5c8e21f0b87bf2f
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 74ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin int getPos() { 75ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return pos; 76ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin } 77ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin 78ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin byte[] getSlice(int startPos, int size) { 79ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin byte[] result = new byte[size]; 80ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin System.arraycopy(buf, startPos, result, 0, size); 81ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return result; 82ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin } 83ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int peek() throws IOException { 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= count) 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("out of data"); 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buf[pos]; 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Compares this DerInputBuffer for equality with the specified 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object. 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean equals(Object other) { 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (other instanceof DerInputBuffer) 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return equals((DerInputBuffer)other); 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean equals(DerInputBuffer other) { 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (this == other) 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int max = this.available(); 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (other.available() != max) 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < max; i++) { 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (this.buf[this.pos + i] != other.buf[other.pos + i]) { 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a hashcode for this DerInputBuffer. 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a hashcode for this DerInputBuffer. 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode() { 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int retval = 0; 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = available(); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int p = pos; 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < len; i++) 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval += buf[p + i] * i; 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski void truncate(int len) throws IOException { 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("insufficient data"); 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = pos + len; 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the integer which takes up the specified number 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of bytes in this buffer as a BigInteger. 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use. 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param makePositive whether to always return a positive value, 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * irrespective of actual encoding 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer as a BigInteger. 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BigInteger getBigInteger(int len, boolean makePositive) throws IOException { 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of integer"); 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid encoding: zero length Int value"); 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] bytes = new byte[len]; 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos, bytes, 0, len); 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski skip(len); 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (makePositive) { 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new BigInteger(1, bytes); 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new BigInteger(bytes); 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the integer which takes up the specified number 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of bytes in this buffer. 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the result is not within the valid 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * range for integer, i.e. between Integer.MIN_VALUE and 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Integer.MAX_VALUE. 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use. 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer. 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getInteger(int len) throws IOException { 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BigInteger result = getBigInteger(len, false); 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (result.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0) { 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Integer below minimum valid value"); 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (result.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Integer exceeds maximum valid value"); 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return result.intValue(); 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the bit string which takes up the specified 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * number of bytes in this buffer. 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getBitString(int len) throws IOException { 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of bit string"); 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) { 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid encoding: zero length bit string"); 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int numOfPadBits = buf[pos]; 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((numOfPadBits < 0) || (numOfPadBits > 7)) { 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid number of padding bits"); 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // minus the first byte which indicates the number of padding bits 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[len - 1]; 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos + 1, retval, 0, len - 1); 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numOfPadBits != 0) { 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // get rid of the padding bits 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval[len - 2] &= (0xff << numOfPadBits); 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski skip(len); 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the bit string which takes up the rest of this buffer. 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] getBitString() throws IOException { 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getBitString(available()); 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the bit string which takes up the rest of this buffer. 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The bit string need not be byte-aligned. 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BitArray getUnalignedBitString() throws IOException { 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos >= count) 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Just copy the data into an aligned, padded octet buffer, 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and consume the rest of the buffer. 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = available(); 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int unusedBits = buf[pos] & 0xff; 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (unusedBits > 7 ) { 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid value for unused bits: " + unusedBits); 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] bits = new byte[len - 1]; 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // number of valid bits 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = (bits.length == 0) ? 0 : bits.length * 8 - unusedBits; 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(buf, pos + 1, bits, 0, len - 1); 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BitArray bitArray = new BitArray(length, bits); 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos = count; 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return bitArray; 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the UTC Time value that takes up the specified number 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of bytes in this buffer. 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getUTCTime(int len) throws IOException { 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER UTC Time"); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len < 11 || len > 17) 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER UTC Time length error"); 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getTime(len, false); 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the Generalized Time value that takes up the specified 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * number of bytes in this buffer. 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getGeneralizedTime(int len) throws IOException { 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > available()) 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER Generalized Time"); 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len < 13 || len > 23) 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER Generalized Time length error"); 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getTime(len, true); 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine to extract time from the der value. 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len the number of bytes to use 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param generalized true if Generalized Time is to be read, false 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if UTC Time is to be read. 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Date getTime(int len, boolean generalized) throws IOException { 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTC time encoded as ASCII chars: 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmZ 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmssZ 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmm+hhmm 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmm-hhmm 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmss+hhmm 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * YYMMDDhhmmss-hhmm 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTC Time is broken in storing only two digits of year. 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If YY < 50, we assume 20YY; 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if YY >= 50, we assume 19YY, as per RFC 3280. 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Generalized time has a four-digit year and allows any 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * precision specified in ISO 8601. However, for our purposes, 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * we will only allow the same format as UTC time, except that 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fractional seconds (millisecond precision) are supported. 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int year, month, day, hour, minute, second, millis; 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String type = null; 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (generalized) { 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski type = "Generalized"; 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year = 1000 * Character.digit((char)buf[pos++], 10); 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 100 * Character.digit((char)buf[pos++], 10); 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 10 * Character.digit((char)buf[pos++], 10); 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += Character.digit((char)buf[pos++], 10); 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= 2; // For the two extra YY 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski type = "UTC"; 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year = 10 * Character.digit((char)buf[pos++], 10); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += Character.digit((char)buf[pos++], 10); 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (year < 50) // origin 2000 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 2000; 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski year += 1900; // origin 1900 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski month = 10 * Character.digit((char)buf[pos++], 10); 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski month += Character.digit((char)buf[pos++], 10); 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski day = 10 * Character.digit((char)buf[pos++], 10); 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski day += Character.digit((char)buf[pos++], 10); 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hour = 10 * Character.digit((char)buf[pos++], 10); 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hour += Character.digit((char)buf[pos++], 10); 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minute = 10 * Character.digit((char)buf[pos++], 10); 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minute += Character.digit((char)buf[pos++], 10); 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= 10; // YYMMDDhhmm 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * We allow for non-encoded seconds, even though the 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IETF-PKIX specification says that the seconds should 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * always be encoded even if it is zero. 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis = 0; 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len > 2 && len < 12) { 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski second = 10 * Character.digit((char)buf[pos++], 10); 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski second += Character.digit((char)buf[pos++], 10); 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= 2; 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // handle fractional seconds (if present) 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buf[pos] == '.' || buf[pos] == ',') { 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len --; 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos++; 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // handle upto milisecond precision only 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int precision = 0; 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int peek = pos; 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (buf[peek] != 'Z' && 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[peek] != '+' && 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buf[peek] != '-') { 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski peek++; 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski precision++; 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (precision) { 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 3: 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 100 * Character.digit((char)buf[pos++], 10); 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 10 * Character.digit((char)buf[pos++], 10); 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += Character.digit((char)buf[pos++], 10); 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 2: 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 100 * Character.digit((char)buf[pos++], 10); 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 10 * Character.digit((char)buf[pos++], 10); 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 1: 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski millis += 100 * Character.digit((char)buf[pos++], 10); 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " time, unsupported precision for seconds value"); 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len -= precision; 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski second = 0; 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (month == 0 || day == 0 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || month > 12 || day > 31 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || hour >= 24 || minute >= 60 || second >= 60) 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, invalid format"); 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Generalized time can theoretically allow any precision, 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * but we're not supporting that. 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarSystem gcal = CalendarSystem.getGregorianCalendar(); 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarDate date = gcal.newCalendarDate(null); // no time zone 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski date.setDate(year, month, day); 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski date.setTimeOfDay(hour, minute, second, millis); 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long time = gcal.getTime(date); 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (! (len == 1 || len == 5)) 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, invalid offset"); 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int hr, min; 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (buf[pos++]) { 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case '+': 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr = 10 * Character.digit((char)buf[pos++], 10); 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr += Character.digit((char)buf[pos++], 10); 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min = 10 * Character.digit((char)buf[pos++], 10); 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min += Character.digit((char)buf[pos++], 10); 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hr >= 24 || min >= 60) 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, +hhmm"); 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski time -= ((hr * 60) + min) * 60 * 1000; 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case '-': 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr = 10 * Character.digit((char)buf[pos++], 10); 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hr += Character.digit((char)buf[pos++], 10); 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min = 10 * Character.digit((char)buf[pos++], 10); 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski min += Character.digit((char)buf[pos++], 10); 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hr >= 24 || min >= 60) 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, -hhmm"); 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski time += ((hr * 60) + min) * 60 * 1000; 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case 'Z': 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Parse " + type + " time, garbage offset"); 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new Date(time); 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 444