]> source.dussan.org Git - poi.git/commitdiff
patch from bug #45844: Addtional diagnostics for SlideShowRecordDumper
authorYegor Kozlov <yegor@apache.org>
Sun, 21 Sep 2008 14:14:34 +0000 (14:14 +0000)
committerYegor Kozlov <yegor@apache.org>
Sun, 21 Sep 2008 14:14:34 +0000 (14:14 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@697520 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowRecordDumper.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java
src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/TextBytesAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/TextCharsAtom.java

index 7f17a4a8d1f498415864e1aa4b9347e8ff4ddb4f..4bcbce240cf544fa72099bc07ecc43fcea327a66 100644 (file)
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.2-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="add">45844 - Addtional diagnostics for HSLF SlideShowRecordDumper</action>
+           <action dev="POI-DEVELOPERS" type="fix">45829 - HSSFPicture.getImageDimension() failed when DPI of image is zero</action>
+           <action dev="POI-DEVELOPERS" type="fix">45815 - Bit mask values in StyleTextPropAtom were not preserved across read-write</action>
+           <action dev="POI-DEVELOPERS" type="add">45814 - Specify RecordType for slide show Handout (4041)</action>
            <action dev="POI-DEVELOPERS" type="fix">45805 - Fixed 16-bit signed/unsigned bug in HSSFSheet.getColWidth etc</action>
            <action dev="POI-DEVELOPERS" type="fix">45780 - Fixed HSSFSheet.shiftRows to also update Area refs</action>
            <action dev="POI-DEVELOPERS" type="fix">45804 - Update HSMF to handle Outlook 3.0 msg files, which have a different string chunk type</action>
index 743e6d05b91eb4b4d14a8c0bc7e534565dd0edcd..d78b3fe7b3b83b5c401f1dac722cf489fb93743f 100644 (file)
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.2-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="add">45844 - Addtional diagnostics for HSLF SlideShowRecordDumper</action>
+           <action dev="POI-DEVELOPERS" type="fix">45829 - HSSFPicture.getImageDimension() failed when DPI of image is zero</action>
+           <action dev="POI-DEVELOPERS" type="fix">45815 - Bit mask values in StyleTextPropAtom were not preserved across read-write</action>
+           <action dev="POI-DEVELOPERS" type="add">45814 - Specify RecordType for slide show Handout (4041)</action>
            <action dev="POI-DEVELOPERS" type="fix">45805 - Fixed 16-bit signed/unsigned bug in HSSFSheet.getColWidth etc</action>
            <action dev="POI-DEVELOPERS" type="fix">45780 - Fixed HSSFSheet.shiftRows to also update Area refs</action>
            <action dev="POI-DEVELOPERS" type="fix">45804 - Update HSMF to handle Outlook 3.0 msg files, which have a different string chunk type</action>
index 74b20993a08263c3523d13d36c9dfb8be75011b1..46860213c9e84f3374b0106d96c9778d2dff6a68 100644 (file)
@@ -20,8 +20,20 @@ package org.apache.poi.hslf.dev;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
+import java.util.Iterator;
+
 import org.apache.poi.hslf.HSLFSlideShow;
 import org.apache.poi.hslf.record.Record;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.ddf.DefaultEscherRecordFactory;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherTextboxRecord;
+import org.apache.poi.hslf.record.EscherTextboxWrapper;
+import org.apache.poi.hslf.record.TextCharsAtom;
+import org.apache.poi.hslf.record.TextBytesAtom;
+import org.apache.poi.hslf.record.StyleTextPropAtom;
+import org.apache.poi.hslf.record.Record;
 
 /**
  * This class provides a way to view the contents of a powerpoint file.
@@ -31,6 +43,8 @@ import org.apache.poi.hslf.record.Record;
  * @author Nick Burch
  */
 public final class SlideShowRecordDumper {
+  private boolean optVerbose;
+  private boolean optEscher;
   private HSLFSlideShow doc;
 
   /**
@@ -39,17 +53,44 @@ public final class SlideShowRecordDumper {
    */
   public static void main(String args[]) throws IOException
   {
-       if(args.length == 0) {
-               System.err.println("Useage: SlideShowRecordDumper <filename>");
+       String filename = "";
+       boolean verbose = false;
+       boolean escher = false;
+
+       int ndx=0;
+       for (; ndx<args.length; ndx++) {                
+               if (!args[ndx].substring(0,1).equals("-"))
+                       break;
+                               
+               if (args[ndx].equals("-escher")) {
+                       escher = true;
+               } else if (args[ndx].equals("-verbose")) {
+                       verbose = true;
+               } else {
+                       printUsage();
+                       return;
+               }
+       }
+       
+       // parsed any options, expect exactly one remaining arg (filename)
+       if (ndx != args.length-1) {
+               printUsage();
                return;
        }
+       
+       filename = args[ndx];
 
-       String filename = args[0];
-
-       SlideShowRecordDumper foo = new SlideShowRecordDumper(filename);
+       SlideShowRecordDumper foo = new SlideShowRecordDumper(filename, verbose, escher);
 
        foo.printDump();
   }
+  
+  public static void printUsage() {
+               System.err.println("Usage: SlideShowRecordDumper [-escher] [-verbose] <filename>");
+               System.err.println("Valid Options:");
+               System.err.println("-escher\t\t: dump contents of escher records");
+               System.err.println("-verbose\t: dump binary contents of each record");
+  }
 
 
   /**
@@ -59,8 +100,10 @@ public final class SlideShowRecordDumper {
    * @param fileName The name of the file to read.
    * @throws IOException if there is a problem while parsing the document.
    */
-  public SlideShowRecordDumper(String fileName) throws IOException
+  public SlideShowRecordDumper(String fileName, boolean verbose, boolean escher) throws IOException
   {
+       optVerbose = verbose;
+       optEscher = escher;
        doc = new HSLFSlideShow(fileName);
   }
 
@@ -95,12 +138,96 @@ public final class SlideShowRecordDumper {
   }
 
   public int getDiskLen(Record r) throws IOException {
+       if (r == null) return 0;
+       
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        r.writeOut(baos);
        byte[] b = baos.toByteArray();
        return b.length;
   }
 
+  public String getPrintableRecordContents(Record r) throws IOException {
+       if (r==null) return "<<null>>";
+       
+       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+       r.writeOut(baos);
+       byte[] b = baos.toByteArray();
+       return HexDump.dump(b, 0, 0);
+  }
+  
+  public String printEscherRecord( EscherRecord er ) {
+        String nl = System.getProperty( "line.separator" );
+        StringBuffer buf = new StringBuffer();
+
+               if (er instanceof EscherContainerRecord) {
+                       buf.append(printEscherContainerRecord( (EscherContainerRecord)er ));
+               } else if (er instanceof EscherTextboxRecord) {
+                       buf.append("EscherTextboxRecord:" + nl);
+                       
+                       EscherTextboxWrapper etw = new EscherTextboxWrapper((EscherTextboxRecord)er);
+                       Record children[] = etw.getChildRecords();
+                       for (int j=0; j<children.length; j++) {
+                               if (children[j] instanceof StyleTextPropAtom) {
+                                       
+                                       // need preceding Text[Chars|Bytes]Atom to initialize the data structure
+                                       if (j > 0 && (children[j-1] instanceof TextCharsAtom || 
+                                                                 children[j-1] instanceof TextBytesAtom)) {
+                                                                       
+                                               int size = (children[j-1] instanceof TextCharsAtom) ? 
+                                                                               ((TextCharsAtom)children[j-1]).getText().length() : 
+                                                                               ((TextBytesAtom)children[j-1]).getText().length();
+                                                                               
+                                               StyleTextPropAtom tsp = (StyleTextPropAtom)children[j];
+                                               tsp.setParentTextSize(size);
+                                               
+                                       } else {
+                                               buf.append("Error! Couldn't find preceding TextAtom for style\n");
+                                       }
+                                       
+                                       buf.append(children[j].toString() + nl );
+                               } else {                                
+                                       buf.append(children[j].toString() + nl );
+                               }
+                       }
+               } else {
+                       buf.append( er.toString() );
+               }                       
+               return buf.toString();
+  }
+  
+  public String printEscherContainerRecord( EscherContainerRecord ecr ) {
+               String indent = "";
+               
+        String nl = System.getProperty( "line.separator" );
+
+        StringBuffer children = new StringBuffer();
+        if ( ecr.getChildRecords().size() > 0 )
+        {
+            children.append( "  children: " + nl );
+            
+            int count = 0;
+            for ( Iterator iterator = ecr.getChildRecords().iterator(); iterator.hasNext(); )
+            {
+               String newIndent = "   ";
+               
+                EscherRecord record = (EscherRecord) iterator.next();
+                children.append(newIndent + "Child " + count + ":" + nl);
+                
+                       children.append( printEscherRecord(record) );
+
+                count++;
+            }
+        }
+
+        return 
+               indent + ecr.getClass().getName() + " (" + ecr.getRecordName() + "):" + nl +
+            indent + "  isContainer: " + ecr.isContainerRecord() + nl +
+            indent + "  options: 0x" + HexDump.toHex( ecr.getOptions() ) + nl +
+            indent + "  recordId: 0x" + HexDump.toHex( ecr.getRecordId() ) + nl +
+            indent + "  numchildren: " + ecr.getChildRecords().size() + nl +
+            indent + children.toString();
+  }
+
 
   public void walkTree(int depth, int pos, Record[] records) throws IOException {
        int indent = depth;
@@ -109,10 +236,15 @@ public final class SlideShowRecordDumper {
 
        for(int i=0; i<records.length; i++) {
                Record r = records[i];
+               if (r == null) {
+                       System.out.println(ind + "At position " + pos + " (" + makeHex(pos,6) + "):");
+                       System.out.println(ind + "Warning! Null record found.");
+                       continue;
+               }
 
                // Figure out how big it is
                int len = getDiskLen(r);
-
+               
                // Grab the type as hex
                String hexType = makeHex((int)r.getRecordType(),4);
                String rHexType = reverseHex(hexType);
@@ -132,6 +264,25 @@ public final class SlideShowRecordDumper {
                System.out.println(ind + " Record is of type " + cname);
                System.out.println(ind + " Type is " + r.getRecordType() + " (" + hexType + " -> " + rHexType + " )");
                System.out.println(ind + " Len is " + (len-8) + " (" + makeHex((len-8),8) + "), on disk len is " + len );
+
+               // print additional information for drawings and atoms
+               if (optEscher && cname.equals("PPDrawing")) {
+                       DefaultEscherRecordFactory factory = new DefaultEscherRecordFactory();
+
+                       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                       r.writeOut(baos);
+                       byte[] b = baos.toByteArray();
+
+                       EscherRecord er = factory.createRecord(b, 0);
+                       er.fillFields(b, 0, factory);
+                       
+                       System.out.println( printEscherRecord( er ) );
+                                               
+               } else if(optVerbose && r.getChildRecords() == null) {
+                       String recData = getPrintableRecordContents(r);
+                       System.out.println(ind + recData );
+               }
+
                System.out.println();
 
                // If it has children, show them
index f876c7d389413cc05954ec20b8aece96d6d8be18..f90179b9ccc938156b46f48f9af2853969cabc93 100644 (file)
@@ -35,6 +35,8 @@ public class TextPropCollection {
        private short reservedField;
        private LinkedList textPropList;
     private int maskSpecial = 0;
+    
+    public int getSpecialMask() { return maskSpecial; }
 
        /** Fetch the number of characters this styling applies to */
        public int getCharactersCovered() { return charactersCovered; }
@@ -202,4 +204,4 @@ public class TextPropCollection {
     public void setReservedField(short val){
         reservedField = val;
     }
-}
\ No newline at end of file
+}
index 0eebbfc56f202b20cf1d62a91c5ade64a0a34ea8..7f084d82e43e0428ee18fb627667f55775daa292 100644 (file)
@@ -32,6 +32,7 @@ import org.apache.poi.hslf.model.textproperties.TextProp;
 import org.apache.poi.hslf.model.textproperties.TextPropCollection;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.util.HexDump;
 
 /**
  * A StyleTextPropAtom (type 4001). Holds basic character properties 
@@ -417,25 +418,62 @@ public class StyleTextPropAtom extends RecordAtom
      */
     public String toString(){
         StringBuffer out = new StringBuffer();
-        out.append("Paragraph properties\n");
-        for (Iterator it1 = getParagraphStyles().iterator(); it1.hasNext();) {
-            TextPropCollection pr = (TextPropCollection)it1.next();
-            out.append("  chars covered: " + pr.getCharactersCovered() + "\n");
-            for (Iterator it2 = pr.getTextPropList().iterator(); it2.hasNext(); ) {
-                TextProp p = (TextProp)it2.next();
-                out.append("    " + p.getName() + " = " + p.getValue() + "\n");
-            }
-        }
-
-        out.append("Character properties\n");
-        for (Iterator it1 = getCharacterStyles().iterator(); it1.hasNext();) {
-            TextPropCollection pr = (TextPropCollection)it1.next();
-            out.append("  chars covered: " + pr.getCharactersCovered() + "\n");
-            for (Iterator it2 = pr.getTextPropList().iterator(); it2.hasNext(); ) {
-                TextProp p = (TextProp)it2.next();
-                out.append("    " + p.getName() + " = " + p.getValue() + "\n");
-            }
+        
+           out.append("StyleTextPropAtom:\n");
+        if (!initialised) {
+               out.append("Uninitialised, dumping Raw Style Data\n");
+        } else {
+        
+               out.append("Paragraph properties\n");
+               
+               for (Iterator it1 = getParagraphStyles().iterator(); it1.hasNext();) {
+                   TextPropCollection pr = (TextPropCollection)it1.next();
+                   out.append("  chars covered: " + pr.getCharactersCovered());
+                   out.append("  special mask flags: 0x" + HexDump.toHex(pr.getSpecialMask()) + "\n");
+                   for (Iterator it2 = pr.getTextPropList().iterator(); it2.hasNext(); ) {
+                       TextProp p = (TextProp)it2.next();
+                       out.append("    " + p.getName() + " = " + p.getValue() );
+                       out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
+                   }
+                   
+                   out.append("  para bytes that would be written: \n");
+                   
+                   try {
+                                       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                                       pr.writeOut(baos);
+                                       byte[] b = baos.toByteArray();
+                                       out.append(HexDump.dump(b, 0, 0));
+                   } catch (Exception e ) {
+                       e.printStackTrace();
+                   }
+               }
+       
+               out.append("Character properties\n");
+               for (Iterator it1 = getCharacterStyles().iterator(); it1.hasNext();) {
+                   TextPropCollection pr = (TextPropCollection)it1.next();
+                   out.append("  chars covered: " + pr.getCharactersCovered() );
+                   out.append("  special mask flags: 0x" + HexDump.toHex(pr.getSpecialMask()) + "\n");
+                   for (Iterator it2 = pr.getTextPropList().iterator(); it2.hasNext(); ) {
+                       TextProp p = (TextProp)it2.next();
+                       out.append("    " + p.getName() + " = " + p.getValue() );
+                       out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
+                   }
+                   
+                   out.append("  char bytes that would be written: \n");
+                   
+                   try {
+                                       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                                       pr.writeOut(baos);
+                                       byte[] b = baos.toByteArray();
+                                       out.append(HexDump.dump(b, 0, 0));
+                   } catch (Exception e ) {
+                       e.printStackTrace();
+                   }
+               }
         }
+               
+        out.append("  original byte stream \n");
+               out.append( HexDump.dump(rawContents, 0, 0) );
 
         return out.toString();
     }
index a8ade7688578af2206a7c0f87469290e8ee39f8c..3e6cf2cbfdb36cdfe77590e0794f529ec65e84e3 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.apache.poi.hslf.record;
 
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
 import java.io.IOException;
@@ -101,4 +102,15 @@ public class TextBytesAtom extends RecordAtom
                // Write out our text
                out.write(_text);
        }
+
+       /**
+        * dump debug info; use getText() to return a string 
+        * representation of the atom
+        */
+       public String toString() {
+        StringBuffer out = new StringBuffer();
+        out.append( "TextBytesAtom:\n");
+               out.append( HexDump.dump(_text, 0, 0) );
+               return out.toString();
+       }
 }
index 761513ab8d0431f502d3ba9e4d45d2fc73b10e71..0e751a73ada30e15e17607c01ecc39af8e45f88b 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.apache.poi.hslf.record;
 
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
 import java.io.IOException;
@@ -97,4 +98,15 @@ public class TextCharsAtom extends RecordAtom
                // Write out our text
                out.write(_text);
        }
+       
+       /**
+        * dump debug info; use getText() to return a string 
+        * representation of the atom
+        */
+       public String toString() {
+        StringBuffer out = new StringBuffer();
+        out.append( "TextCharsAtom:\n");
+               out.append( HexDump.dump(_text, 0, 0) );
+               return out.toString();
+       }
 }