Author: jahewson
Date: Sat Aug  1 02:25:42 2015
New Revision: 1693678

URL: http://svn.apache.org/r1693678
Log:
PDFBOX-2530: Display content stream strings with correct escapes

Modified:
    
pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java

Modified: 
pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java?rev=1693678&r1=1693677&r2=1693678&view=diff
==============================================================================
--- 
pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java
 (original)
+++ 
pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java
 Sat Aug  1 02:25:42 2015
@@ -228,12 +228,12 @@ public class StreamPane implements Actio
 
             for (Object obj : parser.getTokens())
             {
-                writeObject(obj, docu);
+                writeToken(obj, docu);
             }
             return docu;
         }
 
-        private void writeObject(Object obj, StyledDocument docu)
+        private void writeToken(Object obj, StyledDocument docu)
         {
             try
             {
@@ -243,40 +243,72 @@ public class StreamPane implements Actio
                 }
                 else
                 {
-                    String str;
-                    if (obj instanceof COSName)
-                    {
-                        str = "/" + ((COSName) obj).getName();
-                    }
-                    else if (obj instanceof COSBoolean)
+                    docu.insertString(docu.getLength(), operandToString(obj) + 
" ", null);
+                }
+            }
+            catch (BadLocationException e)
+            {
+                e.printStackTrace();
+            }
+        }
+        
+        private String operandToString(Object obj)
+        {
+            if (obj instanceof COSName)
+            {
+                return "/" + ((COSName) obj).getName();
+            }
+            else if (obj instanceof COSBoolean)
+            {
+                return obj.toString();
+            }
+            else if (obj instanceof COSArray)
+            {
+                StringBuilder sb = new StringBuilder("[ ");
+                for (COSBase elem : (COSArray) obj)
+                {
+                    sb.append(operandToString(elem));
+                    sb.append(", ");
+                }
+                if (((COSArray) obj).size() > 0)
+                {
+                    sb.delete(sb.lastIndexOf(","), sb.length());
+                }
+                sb.append("]");
+                return sb.toString();
+            }
+            else if (obj instanceof COSString)
+            {
+                StringBuilder sb = new StringBuilder();
+                sb.append("(");
+                byte[] bytes = ((COSString) obj).getBytes();
+                for (byte b : bytes)
+                {
+                    int chr = b & 0xff;
+                    if (chr < 0x20 || chr > 0x7e)
                     {
-                        str = obj.toString();
+                        // non-printable ASCII is shown as an octal escape
+                        sb.append(String.format("\\%03o", chr));
                     }
-                    else if (obj instanceof COSArray)
+                    else if (chr == '(' || chr == ')' || chr == '\n' || chr == 
'\r'|| chr == '\t' ||
+                            chr == '\b' || chr == '\f' || chr == '\\')
                     {
-                        StringBuilder builder = new StringBuilder("[ ");
-                        for (COSBase base : (COSArray) obj)
-                        {
-                            builder.append(getCOSValue(base));
-                            builder.append(", ");
-                        }
-                        if (((COSArray) obj).size() > 0)
-                        {
-                            builder.delete(builder.lastIndexOf(","), 
builder.length());
-                        }
-                        builder.append("]");
-                        str = builder.toString();
+                        // PDF reserved characters must be escaped
+                        sb.append('\\');
+                        sb.append((char)chr);
                     }
                     else
                     {
-                        str = getCOSValue(obj);
+                        sb.append((char)chr);
                     }
-                    docu.insertString(docu.getLength(), str + " ", null);
                 }
+                return sb.append(")").toString();
             }
-            catch (BadLocationException e)
+            else
             {
-                e.printStackTrace();
+                String str = obj.toString();
+                str = str.substring(str.indexOf('{') + 1, str.length() - 1);
+                return str;
             }
         }
 
@@ -294,7 +326,7 @@ public class StreamPane implements Actio
                     {
                         Object value = dic.getDictionaryObject(key);
                         docu.insertString(docu.getLength(), "/" + 
key.getName() + " ", null);
-                        writeObject(value, docu);
+                        writeToken(value, docu);
                         docu.insertString(docu.getLength(), "\n", null);
                     }
                     docu.insertString(docu.getLength(), 
OperatorMarker.IMAGE_DATA + "\n",
@@ -319,16 +351,5 @@ public class StreamPane implements Actio
                 ex.printStackTrace();
             }
         }
-
-        private String getCOSValue(Object obj)
-        {
-            String str = obj.toString();
-            str = str.substring(str.indexOf('{')+1, str.length()-1);
-            if (obj instanceof COSString)
-            {
-                str = "(" + str + ")";
-            }
-            return str;
-        }
     }
 }


Reply via email to