1 /* 2 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 ******************************************************************************* 28 * (C) Copyright IBM Corp. 1996-2005 - All Rights Reserved * 29 * * 30 * The original version of this source code and documentation is copyrighted * 31 * and owned by IBM, These materials are provided under terms of a License * 32 * Agreement between IBM and Sun. This technology is protected by multiple * 33 * US and International patents. This notice and attribution to IBM may not * 34 * to removed. * 35 ******************************************************************************* 36 */ 37 38 package sun.text.normalizer; 39 40 import java.io.InputStream; 41 import java.io.DataInputStream; 42 import java.io.IOException; 43 import java.util.Arrays; 44 45 public final class ICUBinary 46 { 47 // public inner interface ------------------------------------------------ 48 49 /** 50 * Special interface for data authentication 51 */ 52 public static interface Authenticate 53 { 54 /** 55 * Method used in ICUBinary.readHeader() to provide data format 56 * authentication. 57 * @param version version of the current data 58 * @return true if dataformat is an acceptable version, false otherwise 59 */ 60 public boolean isDataVersionAcceptable(byte version[]); 61 } 62 63 // public methods -------------------------------------------------------- 64 65 /** 66 * <p>ICU data header reader method. 67 * Takes a ICU generated big-endian input stream, parse the ICU standard 68 * file header and authenticates them. 69 * <p>Header format: 70 * <ul> 71 * <li> Header size (char) 72 * <li> Magic number 1 (byte) 73 * <li> Magic number 2 (byte) 74 * <li> Rest of the header size (char) 75 * <li> Reserved word (char) 76 * <li> Big endian indicator (byte) 77 * <li> Character set family indicator (byte) 78 * <li> Size of a char (byte) for c++ and c use 79 * <li> Reserved byte (byte) 80 * <li> Data format identifier (4 bytes), each ICU data has its own 81 * identifier to distinguish them. [0] major [1] minor 82 * [2] milli [3] micro 83 * <li> Data version (4 bytes), the change version of the ICU data 84 * [0] major [1] minor [2] milli [3] micro 85 * <li> Unicode version (4 bytes) this ICU is based on. 86 * </ul> 87 * 88 * <p> 89 * Example of use:<br> 90 * <pre> 91 * try { 92 * FileInputStream input = new FileInputStream(filename); 93 * If (Utility.readICUDataHeader(input, dataformat, dataversion, 94 * unicode) { 95 * System.out.println("Verified file header, this is a ICU data file"); 96 * } 97 * } catch (IOException e) { 98 * System.out.println("This is not a ICU data file"); 99 * } 100 * </pre> 101 * 102 * @param inputStream input stream that contains the ICU data header 103 * @param dataFormatIDExpected Data format expected. An array of 4 bytes 104 * information about the data format. 105 * E.g. data format ID 1.2.3.4. will became an array of 106 * {1, 2, 3, 4} 107 * @param authenticate user defined extra data authentication. This value 108 * can be null, if no extra authentication is needed. 109 * @exception IOException thrown if there is a read error or 110 * when header authentication fails. 111 * @draft 2.1 112 */ 113 public static final byte[] readHeader(InputStream inputStream, 114 byte dataFormatIDExpected[], 115 Authenticate authenticate) 116 throws IOException 117 { 118 DataInputStream input = new DataInputStream(inputStream); 119 char headersize = input.readChar(); 120 int readcount = 2; 121 //reading the header format 122 byte magic1 = input.readByte(); 123 readcount ++; 124 byte magic2 = input.readByte(); 125 readcount ++; 126 if (magic1 != MAGIC1 || magic2 != MAGIC2) { 127 throw new IOException(MAGIC_NUMBER_AUTHENTICATION_FAILED_); 128 } 129 130 input.readChar(); // reading size 131 readcount += 2; 132 input.readChar(); // reading reserved word 133 readcount += 2; 134 byte bigendian = input.readByte(); 135 readcount ++; 136 byte charset = input.readByte(); 137 readcount ++; 138 byte charsize = input.readByte(); 139 readcount ++; 140 input.readByte(); // reading reserved byte 141 readcount ++; 142 143 byte dataFormatID[] = new byte[4]; 144 input.readFully(dataFormatID); 145 readcount += 4; 146 byte dataVersion[] = new byte[4]; 147 input.readFully(dataVersion); 148 readcount += 4; 149 byte unicodeVersion[] = new byte[4]; 150 input.readFully(unicodeVersion); 151 readcount += 4; 152 if (headersize < readcount) { 153 throw new IOException("Internal Error: Header size error"); 154 } 155 input.skipBytes(headersize - readcount); 156 157 if (bigendian != BIG_ENDIAN_ || charset != CHAR_SET_ 158 || charsize != CHAR_SIZE_ 159 || !Arrays.equals(dataFormatIDExpected, dataFormatID) 160 || (authenticate != null 161 && !authenticate.isDataVersionAcceptable(dataVersion))) { 162 throw new IOException(HEADER_AUTHENTICATION_FAILED_); 163 } 164 return unicodeVersion; 165 } 166 167 // private variables ------------------------------------------------- 168 169 /** 170 * Magic numbers to authenticate the data file 171 */ 172 private static final byte MAGIC1 = (byte)0xda; 173 private static final byte MAGIC2 = (byte)0x27; 174 175 /** 176 * File format authentication values 177 */ 178 private static final byte BIG_ENDIAN_ = 1; 179 private static final byte CHAR_SET_ = 0; 180 private static final byte CHAR_SIZE_ = 2; 181 182 /** 183 * Error messages 184 */ 185 private static final String MAGIC_NUMBER_AUTHENTICATION_FAILED_ = 186 "ICU data file error: Not an ICU data file"; 187 private static final String HEADER_AUTHENTICATION_FAILED_ = 188 "ICU data file error: Header authentication failed, please check if you have a valid ICU data file"; 189 }