1    /*
2     *  ====================================================================
3     *  The Apache Software License, Version 1.1
4     *
5     *  Copyright (c) 2000 The Apache Software Foundation.  All rights
6     *  reserved.
7     *
8     *  Redistribution and use in source and binary forms, with or without
9     *  modification, are permitted provided that the following conditions
10    *  are met:
11    *
12    *  1. Redistributions of source code must retain the above copyright
13    *  notice, this list of conditions and the following disclaimer.
14    *
15    *  2. Redistributions in binary form must reproduce the above copyright
16    *  notice, this list of conditions and the following disclaimer in
17    *  the documentation and/or other materials provided with the
18    *  distribution.
19    *
20    *  3. The end-user documentation included with the redistribution,
21    *  if any, must include the following acknowledgment:
22    *  "This product includes software developed by the
23    *  Apache Software Foundation (http://www.apache.org/)."
24    *  Alternately, this acknowledgment may appear in the software itself,
25    *  if and wherever such third-party acknowledgments normally appear.
26    *
27    *  4. The names "Apache" and "Apache Software Foundation" must
28    *  not be used to endorse or promote products derived from this
29    *  software without prior written permission. For written
30    *  permission, please contact apache@apache.org.
31    *
32    *  5. Products derived from this software may not be called "Apache",
33    *  nor may "Apache" appear in their name, without prior written
34    *  permission of the Apache Software Foundation.
35    *
36    *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    *  SUCH DAMAGE.
48    *  ====================================================================
49    *
50    *  This software consists of voluntary contributions made by many
51    *  individuals on behalf of the Apache Software Foundation.  For more
52    *  information on the Apache Software Foundation, please see
53    *  <http://www.apache.org/>.
54    *
55    *  Portions of this software are based upon public domain software
56    *  originally written at the National Center for Supercomputing Applications,
57    *  University of Illinois, Urbana-Champaign.
58    *
59    *  Portions of this software are based upon public domain software
60    *  originally written at the National Center for Supercomputing Applications,
61    *  University of Illinois, Urbana-Champaign.
62    */
63   package org.apache.poi.hpsf;
64   
65   import java.util.*;
66   import org.apache.poi.util.LittleEndian;
67   
68   /**
69    * <p>Reader for specific data types.</p>
70    *
71    * @author Rainer Klute (klute@rainer-klute.de)
72    * @see Property
73    * @see Variant
74    * @version $Id: TypeReader.java,v 1.2 2003/02/05 19:33:27 klute Exp $
75    * @since 2002-12-09
76    */
77   public class TypeReader
78   {
79   
80       /**
81        * <p>Reads a variant data type from a byte array.</p>
82        *
83        * @param src The byte array
84        * @param offset The offset in the byte array where the variant
85        * starts
86        * @param length The length of the variant including the variant
87        * type field
88        * @return A Java object that corresponds best to the variant
89        * field. For example, a VT_I4 is returned as a {@link Long}, a
90        * VT_LPSTR as a {@link String}.
91        *
92        * @see Variant
93        */
94       public static Object read(final byte[] src, int offset, int length,
95   			      final int type)
96       {
97   	/*
98   	 * FIXME: Support reading more types and clean up this code!
99   	 */
100  	Object value;
101  	length = length - LittleEndian.INT_SIZE;
102          switch (type)
103  	{
104              case Variant.VT_I2:
105              {
106                  /*
107                   * Read a short. In Java it is represented as an
108                   * Integer object.
109                   */
110                  value = new Integer(LittleEndian.getUShort(src, offset));
111                  break;
112              }
113              case Variant.VT_I4:
114              {
115                  /*
116                   * Read a word. In Java it is represented as a
117                   * Long object.
118                   */
119                  value = new Long(LittleEndian.getUInt(src, offset));
120                  break;
121              }
122              case Variant.VT_FILETIME:
123              {
124                  /*
125                   * Read a FILETIME object. In Java it is represented
126                   * as a Date object.
127                   */
128                  final long low = LittleEndian.getUInt(src, offset);
129                  offset += LittleEndian.INT_SIZE;
130                  final long high = LittleEndian.getUInt(src, offset);
131                  value = Util.filetimeToDate((int) high, (int) low);
132                  break;
133              }
134              case Variant.VT_LPSTR:
135              {
136                  /*
137                   * Read a byte string. In Java it is represented as a
138                   * String object. The 0x00 bytes at the end must be
139                   * stripped.
140  		 *
141  		 * FIXME: Reading an 8-bit string should pay attention
142  		 * to the codepage. Currently the byte making out the
143  		 * property's value are interpreted according to the
144  		 * platform's default character set.
145                   */
146                  final int first = offset + LittleEndian.INT_SIZE;
147                  long last = first + LittleEndian.getUInt(src, offset) - 1;
148                  offset += LittleEndian.INT_SIZE;
149                  while (src[(int) last] == 0 && first <= last)
150                      last--;
151                  value = new String(src, (int) first, (int) (last - first + 1));
152  		break;
153              }
154              case Variant.VT_LPWSTR:
155              {
156                  /*
157                   * Read a Unicode string. In Java it is represented as
158                   * a String object. The 0x00 bytes at the end must be
159                   * stripped.
160                   */
161                  final int first = offset + LittleEndian.INT_SIZE;
162                  long last = first + LittleEndian.getUInt(src, offset) - 1;
163  		long l = last - first;
164                  offset += LittleEndian.INT_SIZE;
165  		StringBuffer b = new StringBuffer((int) (last - first));
166  		for (int i = 0; i <= l; i++)
167  		{
168  		    final int i1 = offset + (i * 2);
169  		    final int i2 = i1 + 1;
170  		    b.append((char) ((src[i2] << 8) + src[i1]));
171  		}
172  		/* Strip 0x00 characters from the end of the string: */
173  		while (b.charAt(b.length() - 1) == 0x00)
174  		    b.setLength(b.length() - 1);
175  		value = b.toString();
176  		break;
177              }
178              case Variant.VT_CF:
179              {
180                  final byte[] v = new byte[length];
181                  for (int i = 0; i < length; i++)
182                      v[i] = src[(int) (offset + i)];
183  		value = v;
184                  break;
185              }
186              case Variant.VT_BOOL:
187              {
188                  /*
189                   * The first four bytes in src, from src[offset] to
190                   * src[offset + 3] contain the DWord for VT_BOOL, so
191                   * skip it, we don't need it.
192                   */
193                  final int first = offset + LittleEndian.INT_SIZE;
194                  long bool = LittleEndian.getUInt(src, offset);
195                  if (bool != 0)
196                      value = new Boolean(true);
197                  else
198                      value = new Boolean(false);
199  		break;
200              }
201              default:
202              {
203                  final byte[] v = new byte[length];
204                  for (int i = 0; i < length; i++)
205                      v[i] = src[(int) (offset + i)];
206  		value = v;
207                  break;
208              }
209          }
210  	return value;
211      }
212  
213  }
214