001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hdf.extractor;
019:
020: import java.io.*;
021: import java.util.*;
022:
023: /**
024: * Comment me
025: *
026: * @author Ryan Ackley
027: */
028:
029: public class NewOleFile extends RandomAccessFile {
030: private byte[] LAOLA_ID_ARRAY = new byte[] { (byte) 0xd0,
031: (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1,
032: (byte) 0xb1, (byte) 0x1a, (byte) 0xe1 };
033: private int _num_bbd_blocks;
034: private int _root_startblock;
035: private int _sbd_startblock;
036: private long _size;
037: private int[] _bbd_list;
038: protected int[] _big_block_depot;
039: protected int[] _small_block_depot;
040: Hashtable _propertySetsHT = new Hashtable();
041: Vector _propertySetsV = new Vector();
042:
043: public NewOleFile(String fileName, String mode)
044: throws FileNotFoundException {
045: super (fileName, mode);
046: try {
047: init();
048: } catch (Throwable e) {
049: e.printStackTrace();
050: }
051: }
052:
053: private void init() throws IOException {
054:
055: for (int x = 0; x < LAOLA_ID_ARRAY.length; x++) {
056: if (LAOLA_ID_ARRAY[x] != readByte()) {
057: throw new IOException("Not an OLE file");
058: }
059: }
060: _size = length();
061: _num_bbd_blocks = readInt(0x2c);
062: _root_startblock = readInt(0x30);
063: _sbd_startblock = readInt(0x3c);
064: _bbd_list = new int[_num_bbd_blocks];
065: //populate bbd_list. If _num_bbd_blocks > 109 I have to do it
066: //differently
067: if (_num_bbd_blocks <= 109) {
068: seek(0x4c);
069: for (int x = 0; x < _num_bbd_blocks; x++) {
070: _bbd_list[x] = readIntLE();
071: }
072: } else {
073: populateBbdList();
074: }
075: //populate the big block depot
076: _big_block_depot = new int[_num_bbd_blocks * 128];
077: int counter = 0;
078: for (int x = 0; x < _num_bbd_blocks; x++) {
079: byte[] bigBlock = new byte[512];
080: int offset = (_bbd_list[x] + 1) * 512;
081: seek(offset);
082: for (int y = 0; y < 128; y++) {
083: _big_block_depot[counter++] = readIntLE();
084: }
085: }
086: _small_block_depot = createSmallBlockDepot();
087: int[] rootChain = readChain(_big_block_depot, _root_startblock);
088: initializePropertySets(rootChain);
089:
090: }
091:
092: public static void main(String args[]) {
093: try {
094: NewOleFile file = new NewOleFile(args[0], "r");
095: } catch (Exception e) {
096: }
097: }
098:
099: protected int[] readChain(int[] blockChain, int startBlock)
100: throws IOException {
101:
102: int[] tempChain = new int[blockChain.length];
103: tempChain[0] = startBlock;
104: int x = 1;
105: for (;; x++) {
106: int nextVal = blockChain[tempChain[x - 1]];
107: if (nextVal != -2) {
108: tempChain[x] = nextVal;
109: } else {
110: break;
111: }
112: }
113: int[] newChain = new int[x];
114: System.arraycopy(tempChain, 0, newChain, 0, x);
115:
116: return newChain;
117: }
118:
119: private void initializePropertySets(int[] rootChain)
120: throws IOException {
121: for (int x = 0; x < rootChain.length; x++) {
122: int offset = (rootChain[x] + 1) * 512;
123: seek(offset);
124: for (int y = 0; y < 4; y++) {
125: //read the block the makes up the property set
126: byte[] propArray = new byte[128];
127: read(propArray);
128:
129: //parse the byte array for properties
130: int nameSize = Utils.convertBytesToShort(
131: propArray[0x41], propArray[0x40]) / 2 - 1;
132: if (nameSize > 0) {
133: StringBuffer nameBuffer = new StringBuffer(nameSize);
134: for (int z = 0; z < nameSize; z++) {
135: nameBuffer.append((char) propArray[z * 2]);
136: }
137: int type = propArray[0x42];
138: int previous_pps = Utils.convertBytesToInt(
139: propArray[0x47], propArray[0x46],
140: propArray[0x45], propArray[0x44]);
141: int next_pps = Utils.convertBytesToInt(
142: propArray[0x4b], propArray[0x4a],
143: propArray[0x49], propArray[0x48]);
144: int pps_dir = Utils.convertBytesToInt(
145: propArray[0x4f], propArray[0x4e],
146: propArray[0x4d], propArray[0x4c]);
147: int pps_sb = Utils.convertBytesToInt(
148: propArray[0x77], propArray[0x76],
149: propArray[0x75], propArray[0x74]);
150: int pps_size = Utils.convertBytesToInt(
151: propArray[0x7b], propArray[0x7a],
152: propArray[0x79], propArray[0x78]);
153:
154: PropertySet propSet = new PropertySet(nameBuffer
155: .toString(), type, previous_pps, next_pps,
156: pps_dir, pps_sb, pps_size, (x * 4) + y);
157: _propertySetsHT.put(nameBuffer.toString(), propSet);
158: _propertySetsV.add(propSet);
159: }
160: }
161: }
162:
163: }
164:
165: private int[] createSmallBlockDepot() throws IOException {
166:
167: int[] sbd_list = readChain(_big_block_depot, _sbd_startblock);
168: int[] small_block_depot = new int[sbd_list.length * 128];
169:
170: for (int x = 0; x < sbd_list.length && sbd_list[x] != -2; x++) {
171: int offset = ((sbd_list[x] + 1) * 512);
172: seek(offset);
173: for (int y = 0; y < 128; y++) {
174: small_block_depot[y] = readIntLE();
175: }
176: }
177: return small_block_depot;
178: }
179:
180: private void populateBbdList() throws IOException {
181: seek(0x4c);
182: for (int x = 0; x < 109; x++) {
183: _bbd_list[x] = readIntLE();
184: }
185: int pos = 109;
186: int remainder = _num_bbd_blocks - 109;
187: seek(0x48);
188: int numLists = readIntLE();
189: seek(0x44);
190: int firstList = readIntLE();
191:
192: firstList = (firstList + 1) * 512;
193:
194: for (int y = 0; y < numLists; y++) {
195: int size = Math.min(127, remainder);
196: for (int z = 0; z < size; z++) {
197: seek(firstList + (z * 4));
198: _bbd_list[pos++] = readIntLE();
199: }
200: if (size == 127) {
201: seek(firstList + (127 * 4));
202: firstList = readIntLE();
203: firstList = (firstList + 1) * 512;
204: remainder -= 127;
205: }
206: }
207:
208: }
209:
210: private int readInt(long offset) throws IOException {
211: seek(offset);
212: return readIntLE();
213: }
214:
215: private int readIntLE() throws IOException {
216: byte[] intBytes = new byte[4];
217: read(intBytes);
218: return Utils.convertBytesToInt(intBytes[3], intBytes[2],
219: intBytes[1], intBytes[0]);
220: }
221:
222: }
|