1 import org.faceless.pdf2.*; 2 import java.io.*; 3 import java.util.*; 4 import java.text.DecimalFormat ; 5 import java.security.KeyStore ; 6 import java.security.cert.X509Certificate ; 7 8 16 public class Dump 17 { 18 PDF pdf; 19 20 public static void main(String [] args) throws Exception 21 { 22 29 30 if (args.length==0) { 31 System.err.println("USAGE: java Dump <infile.pdf> [<password>]\n"); 32 System.exit(1); 33 } 34 35 if (args.length==1) { 36 new Dump(args[0]); 37 } else { 38 new Dump(args[0], args[1]); 39 } 40 } 41 42 public Dump(String file) throws Exception 43 { 44 this(file, ""); 45 } 46 47 public Dump(String file, String password) throws Exception 48 { 49 PDFReader rd = new PDFReader(new File(file), password); 50 pdf = new PDF(rd); 51 52 System.out.println("DUMPING \""+file+"\"\n----------------------------------------------------------------------\n"); 53 54 getInfoDictionary().show(System.out); 55 getEncryption().show(System.out); 56 getDocumentActions().show(System.out); 57 getMetaData(pdf.getMetaData()).show(System.out); 58 getBookmarks().show(System.out); 59 getNamedActions().show(System.out); 60 getPages().show(System.out); 61 getForm().show(System.out); 62 } 63 64 public Printer getEncryption() 65 { 66 Printer out = new Printer("Encryption"); 67 EncryptionHandler handler = pdf.getEncryptionHandler(); 68 if (handler!=null) { 69 if (handler instanceof StandardEncryptionHandler) { 70 int version = ((StandardEncryptionHandler)handler).getVersion(); 71 int change = ((StandardEncryptionHandler)handler).getChange(); 72 int print = ((StandardEncryptionHandler)handler).getPrint(); 73 int extract = ((StandardEncryptionHandler)handler).getExtract(); 74 out.println("Standard PDF encryption version "+version+": (Acrobat "+(version==1?3:version==2?5:6)+".x)"); 75 out.println("CanChange:\t"+(change==StandardEncryptionHandler.CHANGE_NONE ? "None" : change==StandardEncryptionHandler.CHANGE_LAYOUT ? "Layout" : change==StandardEncryptionHandler.CHANGE_FORMS ? "Forms" : change==StandardEncryptionHandler.CHANGE_ANNOTATIONS ? "Annotations" : "All")); 76 out.println("CanPrint:\t"+(print==StandardEncryptionHandler.PRINT_NONE ? "None" : print==StandardEncryptionHandler.PRINT_LOWRES ? "Low-res" : "High-res")); 77 out.println("CanExtract:\t"+(extract==StandardEncryptionHandler.EXTRACT_NONE ? "None" : extract==StandardEncryptionHandler.EXTRACT_ACCESSIBILITY ? "Accessibility" : "All")); 78 } else { 79 out.println("Non-standard Encryption Handler: "+handler.getClass()); 80 } 81 } 82 return out; 83 } 84 85 public Printer getBookmarks() 86 { 87 Printer out = new Printer("Bookmarks"); 88 getBookmarks(out, pdf.getBookmarks(), "... "); 89 return out; 90 } 91 92 private void getBookmarks(Printer out, List l, String indent) 93 { 94 for (int i=0;l!=null && i<l.size();i++) { 95 PDFBookmark b = (PDFBookmark)l.get(i); 96 out.println(indent+b.getName()+":\t"+getAction(b.getAction())); 97 getBookmarks(out, b.getBookmarks(), "..."+indent); 98 } 99 } 100 101 public String getAction(PDFAction action) 102 { 103 return action==null ? "null" : action.toString(); 104 } 105 106 public Printer getAnnotation(PDFAnnotation annot, String title) 107 { 108 Printer out = new Printer(title); 109 out.println("Type:\t"+annot.getType()); 110 float[] r = annot.getRectangle(); 111 out.println("Rect:\t"+fmt(r[0])+", "+fmt(r[1])+" - "+fmt(r[2])+", "+fmt(r[3])); 112 if (annot instanceof WidgetAnnotation) { 113 out.println("Field:\t"+pdf.getForm().getName(((WidgetAnnotation)annot).getField())); 114 for (int i=0;i<Event.ALL.length;i++) { 115 PDFAction act = ((WidgetAnnotation)annot).getAction(Event.ALL[i]); 116 if (act!=null) out.println(Event.ALL[i]+":\t"+getAction(act)); 117 } 118 } else { 119 if (annot.getSubject()!=null) out.println("Subject:\t"+annot.getSubject()); 120 if (annot.getAuthor()!=null) out.println("Author:\t"+annot.getAuthor()); 121 } 122 if (annot.getUniqueID()!=null) out.println("Unique ID:\t"+annot.getUniqueID()); 123 if (annot.getModifyDate()!=null) out.println("Modified:\t"+annot.getModifyDate().getTime()); 124 if (annot.getCreationDate()!=null) out.println("Created:\t"+annot.getCreationDate().getTime()); 125 if (annot.isReadOnly()) out.println("Locked:\ttrue"); 126 if (!annot.isVisible()) out.println("Invisible:\ttrue"); 127 if (!annot.isPrintable()) out.println("Printable:\tfalse"); 128 if (annot instanceof AnnotationFile) { 129 out.println("Attachment\tFilename:\t"+((AnnotationFile)annot).getFileName()); 130 out.println("Attachment\tCreated:\t"+((AnnotationFile)annot).getFileCreationDate()); 131 out.println("Attachment\tModified:\t"+((AnnotationFile)annot).getFileModDate()); 132 out.println("Attachment\tLength:\t"+((AnnotationFile)annot).getFileSize()); 133 } 134 out.println(""); 135 if (annot.getContents()!=null) out.println(annot.getContents().trim()); 136 List l = annot.getReviews(); 137 for (int i=0;i<l.size();i++) { 138 AnnotationNote note = (AnnotationNote)l.get(i); 139 out.println(" * "+note.getStatus()+" set by "+note.getAuthor()+" at "+note.getModifyDate().getTime()); 140 } 141 if (l.size()>0) out.println(""); 142 l = annot.getReplies(); 143 for (int i=0;i<l.size();i++) { 144 out.append(getAnnotation((PDFAnnotation)l.get(i), "Reply "+(i+1)+"/"+l.size())); 145 } 146 return out; 147 } 148 149 public Printer getInfoDictionary() 150 { 151 Printer out = new Printer("Info Dictionary"); 152 out.println("DocumentID:\t"+pdf.getDocumentID(true)+" "+pdf.getDocumentID(false)); 153 for (Iterator i = pdf.getInfo().entrySet().iterator();i.hasNext();) { 154 Map.Entry e = (Map.Entry)i.next(); 155 if (!(e.getValue() instanceof Calendar)) { 156 out.println(e.getKey()+":\t"+fmt(e.getValue().toString())); 157 } 158 } 159 return out; 160 } 161 162 public Printer getDocumentActions() 163 { 164 Printer out = new Printer("Document Actions"); 165 for (int i=0;i<Event.ALL.length;i++) { 166 PDFAction act = pdf.getAction(Event.ALL[i]); 167 if (act!=null) { 168 out.println(Event.ALL[i]+":\t"+getAction(act)); 169 } 170 } 171 return out; 172 } 173 174 public Printer getMetaData(Reader metadata) 175 { 176 Printer out = new Printer("MetaData"); 177 if (metadata!=null) { 178 try { 179 BufferedReader br = new BufferedReader(metadata); 180 String s; 181 while ((s=br.readLine())!=null) out.println(s); 182 } catch (IOException e) { } 183 } 184 return out; 185 } 186 187 public Printer getNamedActions() 188 { 189 Printer out = new Printer("Named Actions"); 190 Map actions = pdf.getNamedActions(); 191 for (Iterator i = actions.keySet().iterator();i.hasNext();) { 192 String name = (String )i.next(); 193 out.println(name+":\t"+getAction((PDFAction)actions.get(name))); 194 } 195 return out; 196 } 197 198 public Printer getPages() 199 throws Exception 200 { 201 Printer out = new Printer("Pages"); 202 List l = pdf.getPages(); 203 for (int i=0;i<l.size();i++) { 204 PDFPage page = (PDFPage)l.get(i); 205 out.append(getPage(page)); 206 } 207 return out; 208 } 209 210 public Printer getPage(PDFPage page) 211 throws Exception 212 { 213 Printer out = new Printer("Page "+page.getPageNumber()+"/"+pdf.getNumberOfPages()); 214 out.println("Page Size:\t"+page.getWidth()+" x "+page.getHeight()); 215 if (page.getAction(Event.OPEN)!=null) out.println("onOpen:\t"+getAction(page.getAction(Event.OPEN))); 216 if (page.getAction(Event.CLOSE)!=null) out.println("onClose:\t"+getAction(page.getAction(Event.CLOSE))); 217 String [] boxes = { "CropBox", "ArtBox", "BleedBox", "TrimBox" }; 218 for (int i=0;i<boxes.length;i++) { 219 float[] box = page.getBox(boxes[i]); 220 if (box!=null) { 221 out.println(boxes[i]+":\t"+fmt(box[0])+", "+fmt(box[1])+" - "+fmt(box[2])+", "+fmt(box[3])); 222 } 223 } 224 225 List annots = page.getAnnotations(); 226 for (int j=0;j<annots.size();j++) { 227 PDFAnnotation annot = (PDFAnnotation)annots.get(j); 228 if (annot.getInReplyTo()==null && annot.getType()!="Popup") { 229 out.append(getAnnotation(annot, "Annotation "+(j+1)+"/"+annots.size())); 230 } 231 } 232 out.append(getMetaData(page.getMetaData())); 233 return out; 234 } 235 236 public Printer getForm() 237 throws Exception 238 { 239 Printer out = new Printer("Form"); 240 Map form = pdf.getForm().getElements(); 241 242 for (Iterator i=form.keySet().iterator(); i.hasNext();) { 243 String name=(String )i.next(); 244 FormElement el = pdf.getForm().getElement(name); 245 Printer sub = null; 246 if (el instanceof FormSignature) { 247 sub = getFormSignature((FormSignature)el, name); 248 } else if (el instanceof FormText) { 249 sub = getFormText((FormText)el, name); 250 } else if (el instanceof FormButton) { 251 sub = getFormButton((FormButton)el, name); 252 } else if (el instanceof FormCheckbox || el instanceof FormRadioButton) { 253 sub = getFormRadioBox(el, name); 254 } else if (el instanceof FormChoice) { 255 sub = getFormChoice((FormChoice)el, name); 256 } 257 if (el.getDescription()!=null) sub.println("Description:\t"+el.getDescription()); 258 if (el.isReadOnly()) sub.println("Read-Only:\ttrue"); 259 if (el.isRequired()) sub.println("Required:\ttrue"); 260 if (!el.isSubmitted()) sub.println("Submitted:\tfalse"); 261 for (int j=0;j<Event.ALL.length;j++) { 262 PDFAction act = el.getAction(Event.ALL[j]); 263 if (act!=null) sub.println(Event.ALL[j]+":\t"+getAction(act)); 264 } 265 out.append(sub); 266 } 267 return out; 268 } 269 270 public Printer getFormSignature(FormSignature sig, String name) 271 throws Exception 272 { 273 Printer out = new Printer("Signature \""+name+"\""); 274 if (sig.getState()==sig.STATE_BLANK) { 275 out.println("State:\tBlank"); 276 } else { 277 KeyStore keystore = FormSignature.loadDefaultKeyStore(); 278 X509Certificate cert=null; 279 boolean verified=false, verifiable=false; 280 try { 281 verified = sig.verify(); 282 verifiable=true; 283 if (sig.getSignatureHandler() instanceof PKCS7SignatureHandler) { 284 PKCS7SignatureHandler handler = (PKCS7SignatureHandler)sig.getSignatureHandler(); 285 Calendar when = sig.getSignDate(); 286 X509Certificate [] certs = handler.getCertificates(); 287 cert = FormSignature.verifyCertificates(certs,keystore,null,when); 288 } else if (sig.getSignatureHandler() instanceof DSE200Handler) { 289 } else { 290 verifiable=false; 291 } 292 } catch (Exception e) { 293 System.out.println("ERROR: Verifying certificate: "+e); 294 } 295 String validity=""; 296 if (sig.getNumberOfRevisionsCovered()!=pdf.getNumberOfRevisions()) { 297 validity = "Partial - covers the first "+sig.getNumberOfRevisionsCovered()+" of "+pdf.getNumberOfRevisions()+" revisions. Those covered are "; 298 } 299 if (verified && verifiable && cert==null) { 300 validity += "Perfect (signature and certificates verified)"; 301 } else if (verified && verifiable) { 302 validity += "Good (signature verified, but not certificates)"; 303 } else if (verifiable) { 304 validity += "Bad (signature not verified - document has been altered)"; 305 } else { 306 validity += "Unknown (not a PKCS#7 Signature, unable to parse)"; 307 } 308 out.println("Type:\t"+sig.getFilter()); 309 out.println("Signed:\t"+sig.getSignDate().getTime()); 310 if (sig.getName()!=null) out.println("Signed by:\t"+sig.getName()); 311 if (sig.getReason()!=null) out.println("Reason:\t"+sig.getReason()); 312 if (sig.getLocation()!=null) out.println("Location:\t"+sig.getLocation()); 313 out.println("Validity:\t"+validity); 314 if (cert!=null) { 315 Printer p = new Printer("Unverifiable Certificate"); 316 p.println(cert.toString()); 317 out.append(p); 318 } 319 } 320 return out; 321 } 322 323 public Printer getFormText(FormText text, String name) 324 throws Exception 325 { 326 Printer out = new Printer("Text \""+name+"\""); 327 if (text.getValue()!=null) out.println("Value:\t"+fmt(text.getValue())); 328 if (text.getDefaultValue()!=null) out.println("DefaultValue:\t"+fmt(text.getDefaultValue())); 329 if (text.getType()==FormText.TYPE_PASSWORD) out.println("Password:\ttrue"); 330 if (text.getType()==FormText.TYPE_MULTILINE) out.println("Multi-line:\ttrue"); 331 return out; 332 } 333 334 public Printer getFormButton(FormButton button, String name) 335 throws Exception 336 { 337 Printer out = new Printer("Button \""+name+"\""); 338 out.println("Buttons have no attributes"); 339 return out; 340 } 341 342 public Printer getFormRadioBox(FormElement box, String name) 343 throws Exception 344 { 345 Printer out = new Printer((box instanceof FormRadioButton ? "RadioButton" : "Checkbox")+" \""+name+"\""); 346 if (box.getValue()!=null) out.println("Value:\t"+box.getValue()); 347 return out; 348 } 349 350 public Printer getFormChoice(FormChoice choice, String name) 351 throws Exception 352 { 353 Printer out = new Printer("Choice \""+name+"\""); 354 int type = choice.getType(); 355 out.println("Type:\t"+(type==FormChoice.TYPE_COMBO ? "Combo" : type==FormChoice.TYPE_SCROLLABLE ? "Scrollable" : "DropDown")); 356 if (choice.getValue()!=null) out.println("Value:\t"+choice.getValue()); 357 358 Map opts = choice.getOptions(); 359 for (Iterator j=opts.keySet().iterator();j.hasNext();) { 360 String optkey = (String )j.next(); 361 String optval = (String )opts.get(j); 362 if (optval==null) { 363 out.println(" * "+optkey); 364 } else { 365 out.println(" * "+optkey+" = "+optval); 366 } 367 } 368 return out; 369 } 370 371 372 378 private static final DecimalFormat fmt = new DecimalFormat ("#0.00"); 379 private static String fmt(double f) 380 { 381 return f==(int)f ? Integer.toString((int)f) : fmt.format(f); 382 } 383 private static String fmt(String in) 384 { 385 StringBuffer st = new StringBuffer (in.length()); 386 for (int i=0;i<in.length();i++) { 387 char c = in.charAt(i); 388 if (c>=32 && c<=255) { 389 st.append(c); 390 } else if (c=='\n') { 391 st.append("\\n"); 392 } else if (c=='\r') { 393 st.append("\\r"); 394 } else if (c=='\t') { 395 st.append("\\t"); 396 } else { 397 String z = "0000"+Integer.toHexString(c); 398 st.append("\\u"+z.substring(z.length()-4, z.length())); 399 } 400 } 401 return st.toString(); 402 } 403 404 public static class Printer 405 { 406 StringBuffer out; 407 String header; 408 boolean lastline=false; 409 Printer(String header) 410 { 411 this.header=header; 412 out = new StringBuffer (); 413 } 414 public void print(String s) 415 { 416 out.append(s); 417 lastline=false; 418 } 419 public void println(String s) 420 { 421 out.append(s+"\n"); 422 lastline=false; 423 } 424 public void println(StringBuffer s) 425 { 426 out.append(s+"\n"); 427 lastline=false; 428 } 429 public void print(StringBuffer s) 430 { 431 out.append(s); 432 lastline=false; 433 } 434 public void append(Printer printer) 435 { 436 String val = printer.out.toString().trim(); 437 if (val.length()!=0) { 438 439 int lasti=0, ml=printer.header.length(); 440 for (int i=0;i<val.length();i++) { 441 if (val.charAt(i)=='\n') { 442 if (i-lasti > ml) ml = i-lasti; 443 lasti=i; 444 } 445 } 446 if (val.length()-lasti > ml) ml = val.length()-lasti; 447 StringBuffer div = new StringBuffer (ml); 448 for (int i=0;i<ml;i++) div.append('-'); 449 450 if (!lastline) out.append("+-"+div+"\n"); 451 out.append("| => "+printer.header+"\n| "); 452 for (int i=0;i<val.length();i++) { 453 char c = val.charAt(i); 454 out.append(c); 455 if (c=='\n') out.append("| "); 456 } 457 out.append("\n+-"+div+"\n"); 458 lastline=true; 459 } 460 } 461 public void show(PrintStream writer) 462 { 463 if (out.length()!=0) { 464 writer.println("=> "+header); 465 writer.println("------------------------------------------------------------".substring(0,header.length()+3)); 466 writer.println(out); 467 } 468 } 469 } 470 } 471 | Popular Tags |