162 lines
6.5 KiB
Java
162 lines
6.5 KiB
Java
/* ====================================================================
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==================================================================== */
|
|
|
|
package org.apache.poi.poifs.dev;
|
|
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
import java.util.Iterator;
|
|
|
|
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
|
import org.apache.poi.poifs.common.POIFSConstants;
|
|
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
|
import org.apache.poi.poifs.filesystem.DocumentNode;
|
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|
import org.apache.poi.poifs.property.PropertyTable;
|
|
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
|
import org.apache.poi.poifs.storage.BlockList;
|
|
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
|
import org.apache.poi.poifs.storage.ListManagedBlock;
|
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
|
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
|
import org.apache.poi.util.HexDump;
|
|
import org.apache.poi.util.IntList;
|
|
|
|
/**
|
|
* A very low level debugging tool, for printing out core
|
|
* information on the headers and FAT blocks.
|
|
* You probably only want to use this if you're trying
|
|
* to understand POIFS, or if you're trying to track
|
|
* down the source of corruption in a file.
|
|
*/
|
|
public class POIFSHeaderDumper {
|
|
/**
|
|
* Display the entries of multiple POIFS files
|
|
*
|
|
* @param args the names of the files to be displayed
|
|
*/
|
|
public static void main(final String args[]) throws Exception {
|
|
if (args.length == 0) {
|
|
System.err.println("Must specify at least one file to view");
|
|
System.exit(1);
|
|
}
|
|
|
|
for (int j = 0; j < args.length; j++) {
|
|
viewFile(args[j]);
|
|
}
|
|
}
|
|
|
|
public static void viewFile(final String filename) throws Exception {
|
|
InputStream inp = new FileInputStream(filename);
|
|
|
|
// Header
|
|
HeaderBlockReader header_block_reader =
|
|
new HeaderBlockReader(inp);
|
|
displayHeader(header_block_reader);
|
|
|
|
// Raw blocks
|
|
POIFSBigBlockSize bigBlockSize = header_block_reader.getBigBlockSize();
|
|
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
|
displayRawBlocksSummary(data_blocks);
|
|
|
|
// Main FAT Table
|
|
BlockAllocationTableReader batReader =
|
|
new BlockAllocationTableReader(
|
|
header_block_reader.getBigBlockSize(),
|
|
header_block_reader.getBATCount(),
|
|
header_block_reader.getBATArray(),
|
|
header_block_reader.getXBATCount(),
|
|
header_block_reader.getXBATIndex(),
|
|
data_blocks);
|
|
displayBATReader(batReader);
|
|
|
|
// Properties Table
|
|
PropertyTable properties =
|
|
new PropertyTable(
|
|
header_block_reader.getBigBlockSize(),
|
|
header_block_reader.getPropertyStart(),
|
|
data_blocks);
|
|
|
|
// Mini Fat
|
|
BlockList sbat =
|
|
SmallBlockTableReader.getSmallDocumentBlocks(
|
|
bigBlockSize, data_blocks, properties.getRoot(),
|
|
header_block_reader.getSBATStart()
|
|
);
|
|
}
|
|
|
|
public static void displayHeader(HeaderBlockReader header_block_reader) throws Exception {
|
|
System.out.println("Header Details:");
|
|
System.out.println(" Block size: " + header_block_reader.getBigBlockSize());
|
|
System.out.println(" BAT (FAT) header blocks: " + header_block_reader.getBATArray().length);
|
|
System.out.println(" BAT (FAT) block count: " + header_block_reader.getBATCount());
|
|
System.out.println(" XBAT (FAT) block count: " + header_block_reader.getXBATCount());
|
|
System.out.println(" XBAT (FAT) block 1 at: " + header_block_reader.getXBATIndex());
|
|
System.out.println(" SBAT (MiniFAT) block count: " + header_block_reader.getSBATCount());
|
|
System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block_reader.getSBATStart());
|
|
System.out.println(" Property table at: " + header_block_reader.getPropertyStart());
|
|
System.out.println("");
|
|
}
|
|
|
|
public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
|
|
System.out.println("Raw Blocks Details:");
|
|
System.out.println(" Number of blocks: " + data_blocks.blockCount());
|
|
|
|
Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
|
|
gbm.setAccessible(true);
|
|
|
|
for(int i=0; i<Math.min(16, data_blocks.blockCount()); i++) {
|
|
ListManagedBlock block = (ListManagedBlock)gbm.invoke(data_blocks, Integer.valueOf(i));
|
|
byte[] data = new byte[Math.min(48, block.getData().length)];
|
|
System.arraycopy(block.getData(), 0, data, 0, data.length);
|
|
|
|
System.out.println(" Block #" + i + ":");
|
|
System.out.println(HexDump.dump(data, 0, 0));
|
|
}
|
|
|
|
System.out.println("");
|
|
}
|
|
|
|
public static void displayBATReader(BlockAllocationTableReader batReader) throws Exception {
|
|
System.out.println("Sectors, as referenced from the FAT:");
|
|
Field entriesF = batReader.getClass().getDeclaredField("_entries");
|
|
entriesF.setAccessible(true);
|
|
IntList entries = (IntList)entriesF.get(batReader);
|
|
|
|
for(int i=0; i<entries.size(); i++) {
|
|
int bn = entries.get(i);
|
|
String bnS = Integer.toString(bn);
|
|
if(bn == POIFSConstants.END_OF_CHAIN) {
|
|
bnS = "End Of Chain";
|
|
} else if(bn == POIFSConstants.DIFAT_SECTOR_BLOCK) {
|
|
bnS = "DI Fat Block";
|
|
} else if(bn == POIFSConstants.FAT_SECTOR_BLOCK) {
|
|
bnS = "Normal Fat Block";
|
|
} else if(bn == POIFSConstants.UNUSED_BLOCK) {
|
|
bnS = "Block Not Used (Free)";
|
|
}
|
|
|
|
System.out.println(" Block # " + i + " -> " + bnS);
|
|
}
|
|
|
|
System.out.println("");
|
|
}
|
|
}
|