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 // big block index for extension to the big block allocation table 92 private IntegerField _xbat_start; 93 private IntegerField _xbat_count; 94 private byte[] _data; 95 96 /** 97 * Create a single instance initialized with default values 98 */ 99 100 public HeaderBlockWriter() 101 { 102 _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ]; 103 Arrays.fill(_data, _default_value); 104 new LongField(_signature_offset, _signature, _data); 105 new IntegerField(0x08, 0, _data); 106 new IntegerField(0x0c, 0, _data); 107 new IntegerField(0x10, 0, _data); 108 new IntegerField(0x14, 0, _data); 109 new ShortField(0x18, ( short ) 0x3b, _data); 110 new ShortField(0x1a, ( short ) 0x3, _data); 111 new ShortField(0x1c, ( short ) -2, _data); 112 new ShortField(0x1e, ( short ) 0x9, _data); 113 new IntegerField(0x20, 0x6, _data); 114 new IntegerField(0x24, 0, _data); 115 new IntegerField(0x28, 0, _data); 116 _bat_count = new IntegerField(_bat_count_offset, 0, _data); 117 _property_start = new IntegerField(_property_start_offset, 118 POIFSConstants.END_OF_CHAIN, 119 _data); 120 new IntegerField(0x34, 0, _data); 121 new IntegerField(0x38, 0x1000, _data); 122 _sbat_start = new IntegerField(_sbat_start_offset, 123 POIFSConstants.END_OF_CHAIN, _data); 124 new IntegerField(0x40, 1, _data); 125 _xbat_start = new IntegerField(_xbat_start_offset, 126 POIFSConstants.END_OF_CHAIN, _data); 127 _xbat_count = new IntegerField(_xbat_count_offset, 0, _data); 128 } 129 130 /** 131 * Set BAT block parameters. Assumes that all BAT blocks are 132 * contiguous. Will construct XBAT blocks if necessary and return 133 * the array of newly constructed XBAT blocks. 134 * 135 * @param blockCount count of BAT blocks 136 * @param startBlock index of first BAT block 137 * 138 * @return array of XBAT blocks; may be zero length, will not be 139 * null 140 */ 141 142 public BATBlock [] setBATBlocks(final int blockCount, 143 final int startBlock) 144 { 145 BATBlock[] rvalue; 146 147 _bat_count.set(blockCount, _data); 148 int limit = Math.min(blockCount, _max_bats_in_header); 149 int offset = _bat_array_offset; 150 151 for (int j = 0; j < limit; j++) 152 { 153 new IntegerField(offset, startBlock + j, _data); 154 offset += LittleEndianConsts.INT_SIZE; 155 } 156 if (blockCount > _max_bats_in_header) 157 { 158 int excess_blocks = blockCount - _max_bats_in_header; 159 int[] excess_block_array = new int[ excess_blocks ]; 160 161 for (int j = 0; j < excess_blocks; j++) 162 { 163 excess_block_array[ j ] = startBlock + j 164 + _max_bats_in_header; 165 } 166 rvalue = BATBlock.createXBATBlocks(excess_block_array, 167 startBlock + blockCount); 168 _xbat_start.set(startBlock + blockCount, _data); 169 } 170 else 171 { 172 rvalue = BATBlock.createXBATBlocks(new int[ 0 ], 0); 173 _xbat_start.set(POIFSConstants.END_OF_CHAIN, _data); 174 } 175 _xbat_count.set(rvalue.length, _data); 176 return rvalue; 177 } 178 179 /** 180 * Set start of Property Table 181 * 182 * @param startBlock the index of the first block of the Property 183 * Table 184 */ 185 186 public void setPropertyStart(final int startBlock) 187 { 188 _property_start.set(startBlock, _data); 189 } 190 191 /** 192 * Set start of small block allocation table 193 * 194 * @param startBlock the index of the first big block of the small 195 * block allocation table 196 */ 197 198 public void setSBATStart(final int startBlock) 199 { 200 _sbat_start.set(startBlock, _data); 201 } 202 203 /** 204 * For a given number of BAT blocks, calculate how many XBAT 205 * blocks will be needed 206 * 207 * @param blockCount number of BAT blocks 208 * 209 * @return number of XBAT blocks needed 210 */ 211 212 static int calculateXBATStorageRequirements(final int blockCount) 213 { 214 return (blockCount > _max_bats_in_header) 215 ? BATBlock.calculateXBATStorageRequirements(blockCount 216 - _max_bats_in_header) 217 : 0; 218 } 219 220 /* ********** START extension of BigBlock ********** */ 221 222 /** 223 * Write the block's data to an OutputStream 224 * 225 * @param stream the OutputStream to which the stored data should 226 * be written 227 * 228 * @exception IOException on problems writing to the specified 229 * stream 230 */ 231 232 void writeData(final OutputStream stream) 233 throws IOException 234 { 235 doWriteData(stream, _data); 236 } 237 238 /* ********** END extension of BigBlock ********** */ 239 } // end public class HeaderBlockWriter 240 241