You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

POIFSHeaderDumper.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.dev;
  16. import java.io.FileInputStream;
  17. import java.io.InputStream;
  18. import java.lang.reflect.Field;
  19. import java.lang.reflect.Method;
  20. import org.apache.poi.poifs.common.POIFSBigBlockSize;
  21. import org.apache.poi.poifs.common.POIFSConstants;
  22. import org.apache.poi.poifs.property.DirectoryProperty;
  23. import org.apache.poi.poifs.property.Property;
  24. import org.apache.poi.poifs.property.PropertyTable;
  25. import org.apache.poi.poifs.storage.BlockAllocationTableReader;
  26. import org.apache.poi.poifs.storage.HeaderBlock;
  27. import org.apache.poi.poifs.storage.ListManagedBlock;
  28. import org.apache.poi.poifs.storage.RawDataBlockList;
  29. import org.apache.poi.poifs.storage.SmallBlockTableReader;
  30. import org.apache.poi.util.HexDump;
  31. import org.apache.poi.util.IntList;
  32. /**
  33. * A very low level debugging tool, for printing out core
  34. * information on the headers and FAT blocks.
  35. * You probably only want to use this if you're trying
  36. * to understand POIFS, or if you're trying to track
  37. * down the source of corruption in a file.
  38. */
  39. public class POIFSHeaderDumper {
  40. /**
  41. * Display the entries of multiple POIFS files
  42. *
  43. * @param args the names of the files to be displayed
  44. */
  45. public static void main(final String args[]) throws Exception {
  46. if (args.length == 0) {
  47. System.err.println("Must specify at least one file to view");
  48. System.exit(1);
  49. }
  50. for (int j = 0; j < args.length; j++) {
  51. viewFile(args[j]);
  52. }
  53. }
  54. public static void viewFile(final String filename) throws Exception {
  55. System.out.println("Dumping headers from: " + filename);
  56. InputStream inp = new FileInputStream(filename);
  57. // Header
  58. HeaderBlock header_block = new HeaderBlock(inp);
  59. displayHeader(header_block);
  60. // Raw blocks
  61. POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
  62. RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
  63. displayRawBlocksSummary(data_blocks);
  64. // Main FAT Table
  65. BlockAllocationTableReader batReader =
  66. new BlockAllocationTableReader(
  67. header_block.getBigBlockSize(),
  68. header_block.getBATCount(),
  69. header_block.getBATArray(),
  70. header_block.getXBATCount(),
  71. header_block.getXBATIndex(),
  72. data_blocks);
  73. displayBATReader("Big Blocks", batReader);
  74. // Properties Table
  75. PropertyTable properties =
  76. new PropertyTable(header_block, data_blocks);
  77. // Mini Fat
  78. BlockAllocationTableReader sbatReader =
  79. SmallBlockTableReader._getSmallDocumentBlockReader(
  80. bigBlockSize, data_blocks, properties.getRoot(),
  81. header_block.getSBATStart()
  82. );
  83. displayBATReader("Small Blocks", sbatReader);
  84. // Summary of the properties
  85. displayPropertiesSummary(properties);
  86. }
  87. public static void displayHeader(HeaderBlock header_block) throws Exception {
  88. System.out.println("Header Details:");
  89. System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize());
  90. System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length);
  91. System.out.println(" BAT (FAT) block count: " + header_block.getBATCount());
  92. if (header_block.getBATCount() > 0)
  93. System.out.println(" BAT (FAT) block 1 at: " + header_block.getBATArray()[0]);
  94. System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount());
  95. System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex());
  96. System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount());
  97. System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart());
  98. System.out.println(" Property table at: " + header_block.getPropertyStart());
  99. System.out.println("");
  100. }
  101. public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
  102. System.out.println("Raw Blocks Details:");
  103. System.out.println(" Number of blocks: " + data_blocks.blockCount());
  104. Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
  105. gbm.setAccessible(true);
  106. for(int i=0; i<Math.min(16, data_blocks.blockCount()); i++) {
  107. ListManagedBlock block = (ListManagedBlock)gbm.invoke(data_blocks, Integer.valueOf(i));
  108. byte[] data = new byte[Math.min(48, block.getData().length)];
  109. System.arraycopy(block.getData(), 0, data, 0, data.length);
  110. System.out.println(" Block #" + i + ":");
  111. System.out.println(HexDump.dump(data, 0, 0));
  112. }
  113. System.out.println("");
  114. }
  115. public static void displayBATReader(String type, BlockAllocationTableReader batReader) throws Exception {
  116. System.out.println("Sectors, as referenced from the "+type+" FAT:");
  117. Field entriesF = batReader.getClass().getDeclaredField("_entries");
  118. entriesF.setAccessible(true);
  119. IntList entries = (IntList)entriesF.get(batReader);
  120. for(int i=0; i<entries.size(); i++) {
  121. int bn = entries.get(i);
  122. String bnS = Integer.toString(bn);
  123. if(bn == POIFSConstants.END_OF_CHAIN) {
  124. bnS = "End Of Chain";
  125. } else if(bn == POIFSConstants.DIFAT_SECTOR_BLOCK) {
  126. bnS = "DI Fat Block";
  127. } else if(bn == POIFSConstants.FAT_SECTOR_BLOCK) {
  128. bnS = "Normal Fat Block";
  129. } else if(bn == POIFSConstants.UNUSED_BLOCK) {
  130. bnS = "Block Not Used (Free)";
  131. }
  132. System.out.println(" Block # " + i + " -> " + bnS);
  133. }
  134. System.out.println("");
  135. }
  136. public static void displayPropertiesSummary(PropertyTable properties) {
  137. System.out.println("Mini Stream starts at " + properties.getRoot().getStartBlock());
  138. System.out.println("Mini Stream length is " + properties.getRoot().getSize());
  139. System.out.println();
  140. System.out.println("Properties and their block start:");
  141. displayProperties(properties.getRoot(), "");
  142. System.out.println("");
  143. }
  144. public static void displayProperties(DirectoryProperty prop, String indent) {
  145. String nextIndent = indent + " ";
  146. System.out.println(indent + "-> " + prop.getName());
  147. for (Property cp : prop) {
  148. if (cp instanceof DirectoryProperty) {
  149. displayProperties((DirectoryProperty)cp, nextIndent);
  150. } else {
  151. System.out.println(nextIndent + "=> " + cp.getName());
  152. System.out.print(nextIndent + " " + cp.getSize() + " bytes in ");
  153. if (cp.shouldUseSmallBlocks()) {
  154. System.out.print("mini");
  155. } else {
  156. System.out.print("main");
  157. }
  158. System.out.println(" stream, starts at " + cp.getStartBlock());
  159. }
  160. }
  161. }
  162. }