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