1 2 /* ==================================================================== 3 * The Apache Software License, Version 1.1 4 * 5 * Copyright (c) 2002 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" and 28 * "Apache POI" must not be used to endorse or promote products 29 * derived from this software without prior written permission. For 30 * written permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * "Apache POI", nor may "Apache" appear in their name, without 34 * prior written 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 56 package org.apache.poi.poifs.storage; 57 58 import java.io.*; 59 60 import java.util.*; 61 62 import org.apache.poi.poifs.common.POIFSConstants; 63 import org.apache.poi.util.IntegerField; 64 import org.apache.poi.util.LittleEndianConsts; 65 import org.apache.poi.util.LongField; 66 import org.apache.poi.util.ShortField; 67 68 /** 69 * The block containing the archive header 70 * 71 * @author Marc Johnson (mjohnson at apache dot org) 72 */ 73 74 public class HeaderBlockWriter 75 extends BigBlock 76 implements HeaderBlockConstants 77 { 78 private static final byte _default_value = ( byte ) 0xFF; 79 80 // number of big block allocation table blocks (int) 81 private IntegerField _bat_count; 82 83 // start of the property set block (int index of the property set 84 // chain's first big block) 85 private IntegerField _property_start; 86 87 // start of the small block allocation table (int index of small 88 // block allocation table's first big block) 89 private IntegerField _sbat_start; 90 91 // number of big blocks holding the small block allocation table 92 private IntegerField _sbat_block_count; 93 94 // big block index for extension to the big block allocation table 95 private IntegerField _xbat_start; 96 private IntegerField _xbat_count; 97 private byte[] _data; 98 99 /** 100 * Create a single instance initialized with default values 101 */ 102 103 public HeaderBlockWriter() 104 { 105 _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ]; 106 Arrays.fill(_data, _default_value); 107 new LongField(_signature_offset, _signature, _data); 108 new IntegerField(0x08, 0, _data); 109 new IntegerField(0x0c, 0, _data); 110 new IntegerField(0x10, 0, _data); 111 new IntegerField(0x14, 0, _data); 112 new ShortField(0x18, ( short ) 0x3b, _data); 113 new ShortField(0x1a, ( short ) 0x3, _data); 114 new ShortField(0x1c, ( short ) -2, _data); 115 new ShortField(0x1e, ( short ) 0x9, _data); 116 new IntegerField(0x20, 0x6, _data); 117 new IntegerField(0x24, 0, _data); 118 new IntegerField(0x28, 0, _data); 119 _bat_count = new IntegerField(_bat_count_offset, 0, _data); 120 _property_start = new IntegerField(_property_start_offset, 121 POIFSConstants.END_OF_CHAIN, 122 _data); 123 new IntegerField(0x34, 0, _data); 124 new IntegerField(0x38, 0x1000, _data); 125 _sbat_start = new IntegerField(_sbat_start_offset, 126 POIFSConstants.END_OF_CHAIN, _data); 127 _sbat_block_count = new IntegerField(_sbat_block_count_offset, 0, 128 _data); 129 _xbat_start = new IntegerField(_xbat_start_offset, 130 POIFSConstants.END_OF_CHAIN, _data); 131 _xbat_count = new IntegerField(_xbat_count_offset, 0, _data); 132 } 133 134 /** 135 * Set BAT block parameters. Assumes that all BAT blocks are 136 * contiguous. Will construct XBAT blocks if necessary and return 137 * the array of newly constructed XBAT blocks. 138 * 139 * @param blockCount count of BAT blocks 140 * @param startBlock index of first BAT block 141 * 142 * @return array of XBAT blocks; may be zero length, will not be 143 * null 144 */ 145 146 public BATBlock [] setBATBlocks(final int blockCount, 147 final int startBlock) 148 { 149 BATBlock[] rvalue; 150 151 _bat_count.set(blockCount, _data); 152 int limit = Math.min(blockCount, _max_bats_in_header); 153 int offset = _bat_array_offset; 154 155 for (int j = 0; j < limit; j++) 156 { 157 new IntegerField(offset, startBlock + j, _data); 158 offset += LittleEndianConsts.INT_SIZE; 159 } 160 if (blockCount > _max_bats_in_header) 161 { 162 int excess_blocks = blockCount - _max_bats_in_header; 163 int[] excess_block_array = new int[ excess_blocks ]; 164 165 for (int j = 0; j < excess_blocks; j++) 166 { 167 excess_block_array[ j ] = startBlock + j 168 + _max_bats_in_header; 169 } 170 rvalue = BATBlock.createXBATBlocks(excess_block_array, 171 startBlock + blockCount); 172 _xbat_start.set(startBlock + blockCount, _data); 173 } 174 else 175 { 176 rvalue = BATBlock.createXBATBlocks(new int[ 0 ], 0); 177 _xbat_start.set(POIFSConstants.END_OF_CHAIN, _data); 178 } 179 _xbat_count.set(rvalue.length, _data); 180 return rvalue; 181 } 182 183 /** 184 * Set start of Property Table 185 * 186 * @param startBlock the index of the first block of the Property 187 * Table 188 */ 189 190 public void setPropertyStart(final int startBlock) 191 { 192 _property_start.set(startBlock, _data); 193 } 194 195 /** 196 * Set start of small block allocation table 197 * 198 * @param startBlock the index of the first big block of the small 199 * block allocation table 200 */ 201 202 public void setSBATStart(final int startBlock) 203 { 204 _sbat_start.set(startBlock, _data); 205 } 206 207 /** 208 * Set count of SBAT blocks 209 * 210 * @param count the number of SBAT blocks 211 */ 212 213 public void setSBATBlockCount(final int count) 214 { 215 _sbat_block_count.set(count, _data); 216 } 217 218 /** 219 * For a given number of BAT blocks, calculate how many XBAT 220 * blocks will be needed 221 * 222 * @param blockCount number of BAT blocks 223 * 224 * @return number of XBAT blocks needed 225 */ 226 227 static int calculateXBATStorageRequirements(final int blockCount) 228 { 229 return (blockCount > _max_bats_in_header) 230 ? BATBlock.calculateXBATStorageRequirements(blockCount 231 - _max_bats_in_header) 232 : 0; 233 } 234 235 /* ********** START extension of BigBlock ********** */ 236 237 /** 238 * Write the block's data to an OutputStream 239 * 240 * @param stream the OutputStream to which the stored data should 241 * be written 242 * 243 * @exception IOException on problems writing to the specified 244 * stream 245 */ 246 247 void writeData(final OutputStream stream) 248 throws IOException 249 { 250 doWriteData(stream, _data); 251 } 252 253 /* ********** END extension of BigBlock ********** */ 254 } // end public class HeaderBlockWriter 255 256