Commit ce8b1ba6a5a5650d90571f5c39855af341dfad47

Authored by Jay Berkenbilt
1 parent aa035961

convert file to a PointerHolder<InputSource> so it could be either a file or a b…

…uffer; also fix a bug in BufferInputSource::seek

git-svn-id: svn+q:///qpdf/trunk@1030 71b93d88-0707-0410-a8cf-f5a4172ac649
include/qpdf/QPDF.hh
@@ -423,15 +423,16 @@ class QPDF @@ -423,15 +423,16 @@ class QPDF
423 void setLastObjectDescription(std::string const& description, 423 void setLastObjectDescription(std::string const& description,
424 int objid, int generation); 424 int objid, int generation);
425 QPDFObjectHandle readObject( 425 QPDFObjectHandle readObject(
426 - InputSource*, std::string const& description, 426 + PointerHolder<InputSource>, std::string const& description,
427 int objid, int generation, bool in_object_stream); 427 int objid, int generation, bool in_object_stream);
428 QPDFObjectHandle readObjectInternal( 428 QPDFObjectHandle readObjectInternal(
429 - InputSource* input, int objid, int generation, 429 + PointerHolder<InputSource> input, int objid, int generation,
430 bool in_object_stream, 430 bool in_object_stream,
431 bool in_array, bool in_dictionary); 431 bool in_array, bool in_dictionary);
432 int recoverStreamLength( 432 int recoverStreamLength(
433 - InputSource* input, int objid, int generation, off_t stream_offset);  
434 - QPDFTokenizer::Token readToken(InputSource*); 433 + PointerHolder<InputSource> input, int objid, int generation,
  434 + off_t stream_offset);
  435 + QPDFTokenizer::Token readToken(PointerHolder<InputSource>);
435 436
436 QPDFObjectHandle readObjectAtOffset( 437 QPDFObjectHandle readObjectAtOffset(
437 bool attempt_recovery, 438 bool attempt_recovery,
@@ -785,7 +786,7 @@ class QPDF @@ -785,7 +786,7 @@ class QPDF
785 786
786 787
787 QPDFTokenizer tokenizer; 788 QPDFTokenizer tokenizer;
788 - FileInputSource file; 789 + PointerHolder<InputSource> file;
789 std::string last_object_description; 790 std::string last_object_description;
790 bool encrypted; 791 bool encrypted;
791 bool encryption_initialized; 792 bool encryption_initialized;
libqpdf/QPDF.cc
@@ -303,7 +303,9 @@ QPDF::~QPDF() @@ -303,7 +303,9 @@ QPDF::~QPDF()
303 void 303 void
304 QPDF::processFile(char const* filename, char const* password) 304 QPDF::processFile(char const* filename, char const* password)
305 { 305 {
306 - this->file.setFilename(filename); 306 + FileInputSource* fi = new FileInputSource();
  307 + this->file = fi;
  308 + fi->setFilename(filename);
307 if (password) 309 if (password)
308 { 310 {
309 this->provided_password = password; 311 this->provided_password = password;
@@ -343,7 +345,7 @@ QPDF::parse() @@ -343,7 +345,7 @@ QPDF::parse()
343 static PCRE header_re("^%PDF-(1.\\d+)\\b"); 345 static PCRE header_re("^%PDF-(1.\\d+)\\b");
344 static PCRE eof_re("(?s:startxref\\s+(\\d+)\\s+%%EOF\\b)"); 346 static PCRE eof_re("(?s:startxref\\s+(\\d+)\\s+%%EOF\\b)");
345 347
346 - std::string line = this->file.readLine(); 348 + std::string line = this->file->readLine();
347 PCRE::Match m1 = header_re.match(line.c_str()); 349 PCRE::Match m1 = header_re.match(line.c_str());
348 if (m1) 350 if (m1)
349 { 351 {
@@ -356,7 +358,7 @@ QPDF::parse() @@ -356,7 +358,7 @@ QPDF::parse()
356 else 358 else
357 { 359 {
358 QTC::TC("qpdf", "QPDF not a pdf file"); 360 QTC::TC("qpdf", "QPDF not a pdf file");
359 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 361 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
360 "", 0, "not a PDF file"); 362 "", 0, "not a PDF file");
361 } 363 }
362 364
@@ -364,14 +366,14 @@ QPDF::parse() @@ -364,14 +366,14 @@ QPDF::parse()
364 // the file. We add an extra 30 characters to leave room for the 366 // the file. We add an extra 30 characters to leave room for the
365 // startxref stuff. 367 // startxref stuff.
366 static int const tbuf_size = 1054; 368 static int const tbuf_size = 1054;
367 - this->file.seek(0, SEEK_END);  
368 - if (this->file.tell() > tbuf_size) 369 + this->file->seek(0, SEEK_END);
  370 + if (this->file->tell() > tbuf_size)
369 { 371 {
370 - this->file.seek(-tbuf_size, SEEK_END); 372 + this->file->seek(-tbuf_size, SEEK_END);
371 } 373 }
372 else 374 else
373 { 375 {
374 - this->file.rewind(); 376 + this->file->rewind();
375 } 377 }
376 char* buf = new char[tbuf_size + 1]; 378 char* buf = new char[tbuf_size + 1];
377 // Put buf in a PointerHolder to guarantee deletion of buf. This 379 // Put buf in a PointerHolder to guarantee deletion of buf. This
@@ -379,7 +381,7 @@ QPDF::parse() @@ -379,7 +381,7 @@ QPDF::parse()
379 // an array of fundamental types. 381 // an array of fundamental types.
380 PointerHolder<char> b(buf); 382 PointerHolder<char> b(buf);
381 memset(buf, '\0', tbuf_size + 1); 383 memset(buf, '\0', tbuf_size + 1);
382 - this->file.read(buf, tbuf_size); 384 + this->file->read(buf, tbuf_size);
383 385
384 // Since buf may contain null characters, we can't do a regexp 386 // Since buf may contain null characters, we can't do a regexp
385 // search on buf directly. Find the last occurrence within buf 387 // search on buf directly. Find the last occurrence within buf
@@ -401,7 +403,7 @@ QPDF::parse() @@ -401,7 +403,7 @@ QPDF::parse()
401 if (! m2) 403 if (! m2)
402 { 404 {
403 QTC::TC("qpdf", "QPDF can't find startxref"); 405 QTC::TC("qpdf", "QPDF can't find startxref");
404 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), "", 0, 406 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
405 "can't find startxref"); 407 "can't find startxref");
406 } 408 }
407 off_t xref_offset = atoi(m2.getMatch(1).c_str()); 409 off_t xref_offset = atoi(m2.getMatch(1).c_str());
@@ -450,10 +452,10 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -450,10 +452,10 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
450 static PCRE endobj_re("^\\s*endobj\\b"); 452 static PCRE endobj_re("^\\s*endobj\\b");
451 static PCRE trailer_re("^\\s*trailer\\b"); 453 static PCRE trailer_re("^\\s*trailer\\b");
452 454
453 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), "", 0, 455 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
454 "file is damaged")); 456 "file is damaged"));
455 warn(e); 457 warn(e);
456 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), "", 0, 458 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
457 "Attempting to reconstruct cross-reference table")); 459 "Attempting to reconstruct cross-reference table"));
458 460
459 // Delete all references to type 1 (uncompressed) objects 461 // Delete all references to type 1 (uncompressed) objects
@@ -473,13 +475,13 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -473,13 +475,13 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
473 this->xref_table.erase(*iter); 475 this->xref_table.erase(*iter);
474 } 476 }
475 477
476 - this->file.seek(0, SEEK_END);  
477 - off_t eof = this->file.tell();  
478 - this->file.seek(0, SEEK_SET); 478 + this->file->seek(0, SEEK_END);
  479 + off_t eof = this->file->tell();
  480 + this->file->seek(0, SEEK_SET);
479 bool in_obj = false; 481 bool in_obj = false;
480 - while (this->file.tell() < eof) 482 + while (this->file->tell() < eof)
481 { 483 {
482 - std::string line = this->file.readLine(); 484 + std::string line = this->file->readLine();
483 if (in_obj) 485 if (in_obj)
484 { 486 {
485 if (endobj_re.match(line.c_str())) 487 if (endobj_re.match(line.c_str()))
@@ -495,17 +497,17 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -495,17 +497,17 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
495 in_obj = true; 497 in_obj = true;
496 int obj = atoi(m.getMatch(1).c_str()); 498 int obj = atoi(m.getMatch(1).c_str());
497 int gen = atoi(m.getMatch(2).c_str()); 499 int gen = atoi(m.getMatch(2).c_str());
498 - int offset = this->file.getLastOffset(); 500 + int offset = this->file->getLastOffset();
499 insertXrefEntry(obj, 1, offset, gen, true); 501 insertXrefEntry(obj, 1, offset, gen, true);
500 } 502 }
501 else if ((! this->trailer.isInitialized()) && 503 else if ((! this->trailer.isInitialized()) &&
502 trailer_re.match(line.c_str())) 504 trailer_re.match(line.c_str()))
503 { 505 {
504 // read "trailer" 506 // read "trailer"
505 - this->file.seek(this->file.getLastOffset(), SEEK_SET);  
506 - readToken(&this->file); 507 + this->file->seek(this->file->getLastOffset(), SEEK_SET);
  508 + readToken(this->file);
507 QPDFObjectHandle t = 509 QPDFObjectHandle t =
508 - readObject(&this->file, "trailer", 0, 0, false); 510 + readObject(this->file, "trailer", 0, 0, false);
509 if (! t.isDictionary()) 511 if (! t.isDictionary())
510 { 512 {
511 // Oh well. It was worth a try. 513 // Oh well. It was worth a try.
@@ -526,7 +528,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -526,7 +528,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
526 // with bad startxref pointers even when they have object 528 // with bad startxref pointers even when they have object
527 // streams. 529 // streams.
528 530
529 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), "", 0, 531 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
530 "unable to find trailer " 532 "unable to find trailer "
531 "dictionary while recovering damaged file"); 533 "dictionary while recovering damaged file");
532 } 534 }
@@ -546,11 +548,11 @@ QPDF::read_xref(off_t xref_offset) @@ -546,11 +548,11 @@ QPDF::read_xref(off_t xref_offset)
546 std::map<int, int> free_table; 548 std::map<int, int> free_table;
547 while (xref_offset) 549 while (xref_offset)
548 { 550 {
549 - this->file.seek(xref_offset, SEEK_SET);  
550 - std::string line = this->file.readLine(); 551 + this->file->seek(xref_offset, SEEK_SET);
  552 + std::string line = this->file->readLine();
551 if (line == "xref") 553 if (line == "xref")
552 { 554 {
553 - xref_offset = read_xrefTable(this->file.tell()); 555 + xref_offset = read_xrefTable(this->file->tell());
554 } 556 }
555 else 557 else
556 { 558 {
@@ -571,7 +573,7 @@ QPDF::read_xref(off_t xref_offset) @@ -571,7 +573,7 @@ QPDF::read_xref(off_t xref_offset)
571 if (size != max_obj + 1) 573 if (size != max_obj + 1)
572 { 574 {
573 QTC::TC("qpdf", "QPDF xref size mismatch"); 575 QTC::TC("qpdf", "QPDF xref size mismatch");
574 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), "", 0, 576 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
575 std::string("reported number of objects (") + 577 std::string("reported number of objects (") +
576 QUtil::int_to_string(size) + 578 QUtil::int_to_string(size) +
577 ") inconsistent with actual number of objects (" + 579 ") inconsistent with actual number of objects (" +
@@ -591,17 +593,17 @@ QPDF::read_xrefTable(off_t xref_offset) @@ -591,17 +593,17 @@ QPDF::read_xrefTable(off_t xref_offset)
591 593
592 std::vector<ObjGen> deleted_items; 594 std::vector<ObjGen> deleted_items;
593 595
594 - this->file.seek(xref_offset, SEEK_SET); 596 + this->file->seek(xref_offset, SEEK_SET);
595 bool done = false; 597 bool done = false;
596 while (! done) 598 while (! done)
597 { 599 {
598 - std::string line = this->file.readLine(); 600 + std::string line = this->file->readLine();
599 PCRE::Match m1 = xref_first_re.match(line.c_str()); 601 PCRE::Match m1 = xref_first_re.match(line.c_str());
600 if (! m1) 602 if (! m1)
601 { 603 {
602 QTC::TC("qpdf", "QPDF invalid xref"); 604 QTC::TC("qpdf", "QPDF invalid xref");
603 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
604 - "xref table", this->file.getLastOffset(), 605 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  606 + "xref table", this->file->getLastOffset(),
605 "xref syntax invalid"); 607 "xref syntax invalid");
606 } 608 }
607 int obj = atoi(m1.getMatch(1).c_str()); 609 int obj = atoi(m1.getMatch(1).c_str());
@@ -613,17 +615,17 @@ QPDF::read_xrefTable(off_t xref_offset) @@ -613,17 +615,17 @@ QPDF::read_xrefTable(off_t xref_offset)
613 if (i == 0) 615 if (i == 0)
614 { 616 {
615 // This is needed by checkLinearization() 617 // This is needed by checkLinearization()
616 - this->first_xref_item_offset = this->file.tell(); 618 + this->first_xref_item_offset = this->file->tell();
617 } 619 }
618 memset(xref_entry, 0, sizeof(xref_entry)); 620 memset(xref_entry, 0, sizeof(xref_entry));
619 - this->file.read(xref_entry, xref_entry_size); 621 + this->file->read(xref_entry, xref_entry_size);
620 PCRE::Match m2 = xref_entry_re.match(xref_entry); 622 PCRE::Match m2 = xref_entry_re.match(xref_entry);
621 if (! m2) 623 if (! m2)
622 { 624 {
623 QTC::TC("qpdf", "QPDF invalid xref entry"); 625 QTC::TC("qpdf", "QPDF invalid xref entry");
624 throw QPDFExc( 626 throw QPDFExc(
625 - qpdf_e_damaged_pdf, this->file.getName(),  
626 - "xref table", this->file.getLastOffset(), 627 + qpdf_e_damaged_pdf, this->file->getName(),
  628 + "xref table", this->file->getLastOffset(),
627 "invalid xref entry (obj=" + 629 "invalid xref entry (obj=" +
628 QUtil::int_to_string(i) + ")"); 630 QUtil::int_to_string(i) + ")");
629 } 631 }
@@ -642,26 +644,26 @@ QPDF::read_xrefTable(off_t xref_offset) @@ -642,26 +644,26 @@ QPDF::read_xrefTable(off_t xref_offset)
642 insertXrefEntry(i, 1, f1, f2); 644 insertXrefEntry(i, 1, f1, f2);
643 } 645 }
644 } 646 }
645 - off_t pos = this->file.tell();  
646 - QPDFTokenizer::Token t = readToken(&this->file); 647 + off_t pos = this->file->tell();
  648 + QPDFTokenizer::Token t = readToken(this->file);
647 if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer")) 649 if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))
648 { 650 {
649 done = true; 651 done = true;
650 } 652 }
651 else 653 else
652 { 654 {
653 - this->file.seek(pos, SEEK_SET); 655 + this->file->seek(pos, SEEK_SET);
654 } 656 }
655 } 657 }
656 658
657 // Set offset to previous xref table if any 659 // Set offset to previous xref table if any
658 QPDFObjectHandle cur_trailer = 660 QPDFObjectHandle cur_trailer =
659 - readObject(&this->file, "trailer", 0, 0, false); 661 + readObject(this->file, "trailer", 0, 0, false);
660 if (! cur_trailer.isDictionary()) 662 if (! cur_trailer.isDictionary())
661 { 663 {
662 QTC::TC("qpdf", "QPDF missing trailer"); 664 QTC::TC("qpdf", "QPDF missing trailer");
663 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
664 - "", this->file.getLastOffset(), 665 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  666 + "", this->file->getLastOffset(),
665 "expected trailer dictionary"); 667 "expected trailer dictionary");
666 } 668 }
667 669
@@ -672,15 +674,15 @@ QPDF::read_xrefTable(off_t xref_offset) @@ -672,15 +674,15 @@ QPDF::read_xrefTable(off_t xref_offset)
672 if (! this->trailer.hasKey("/Size")) 674 if (! this->trailer.hasKey("/Size"))
673 { 675 {
674 QTC::TC("qpdf", "QPDF trailer lacks size"); 676 QTC::TC("qpdf", "QPDF trailer lacks size");
675 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
676 - "trailer", this->file.getLastOffset(), 677 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  678 + "trailer", this->file->getLastOffset(),
677 "trailer dictionary lacks /Size key"); 679 "trailer dictionary lacks /Size key");
678 } 680 }
679 if (! this->trailer.getKey("/Size").isInteger()) 681 if (! this->trailer.getKey("/Size").isInteger())
680 { 682 {
681 QTC::TC("qpdf", "QPDF trailer size not integer"); 683 QTC::TC("qpdf", "QPDF trailer size not integer");
682 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
683 - "trailer", this->file.getLastOffset(), 684 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  685 + "trailer", this->file->getLastOffset(),
684 "/Size key in trailer dictionary is not " 686 "/Size key in trailer dictionary is not "
685 "an integer"); 687 "an integer");
686 } 688 }
@@ -704,7 +706,7 @@ QPDF::read_xrefTable(off_t xref_offset) @@ -704,7 +706,7 @@ QPDF::read_xrefTable(off_t xref_offset)
704 } 706 }
705 else 707 else
706 { 708 {
707 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 709 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
708 "xref stream", xref_offset, 710 "xref stream", xref_offset,
709 "invalid /XRefStm"); 711 "invalid /XRefStm");
710 } 712 }
@@ -724,8 +726,8 @@ QPDF::read_xrefTable(off_t xref_offset) @@ -724,8 +726,8 @@ QPDF::read_xrefTable(off_t xref_offset)
724 if (! cur_trailer.getKey("/Prev").isInteger()) 726 if (! cur_trailer.getKey("/Prev").isInteger())
725 { 727 {
726 QTC::TC("qpdf", "QPDF trailer prev not integer"); 728 QTC::TC("qpdf", "QPDF trailer prev not integer");
727 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
728 - "trailer", this->file.getLastOffset(), 729 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  730 + "trailer", this->file->getLastOffset(),
729 "/Prev key in trailer dictionary is not " 731 "/Prev key in trailer dictionary is not "
730 "an integer"); 732 "an integer");
731 } 733 }
@@ -772,7 +774,7 @@ QPDF::read_xrefStream(off_t xref_offset) @@ -772,7 +774,7 @@ QPDF::read_xrefStream(off_t xref_offset)
772 if (! found) 774 if (! found)
773 { 775 {
774 QTC::TC("qpdf", "QPDF can't find xref"); 776 QTC::TC("qpdf", "QPDF can't find xref");
775 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 777 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
776 "", xref_offset, "xref not found"); 778 "", xref_offset, "xref not found");
777 } 779 }
778 780
@@ -793,7 +795,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -793,7 +795,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
793 dict.getKey("/Size").isInteger() && 795 dict.getKey("/Size").isInteger() &&
794 (Index_obj.isArray() || Index_obj.isNull()))) 796 (Index_obj.isArray() || Index_obj.isNull())))
795 { 797 {
796 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 798 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
797 "xref stream", xref_offset, 799 "xref stream", xref_offset,
798 "Cross-reference stream does not have" 800 "Cross-reference stream does not have"
799 " proper /W and /Index keys"); 801 " proper /W and /Index keys");
@@ -804,7 +806,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -804,7 +806,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
804 int n_index = Index_obj.getArrayNItems(); 806 int n_index = Index_obj.getArrayNItems();
805 if ((n_index % 2) || (n_index < 2)) 807 if ((n_index % 2) || (n_index < 2))
806 { 808 {
807 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 809 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
808 "xref stream", xref_offset, 810 "xref stream", xref_offset,
809 "Cross-reference stream's /Index has an" 811 "Cross-reference stream's /Index has an"
810 " invalid number of values"); 812 " invalid number of values");
@@ -817,7 +819,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -817,7 +819,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
817 } 819 }
818 else 820 else
819 { 821 {
820 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 822 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
821 "xref stream", xref_offset, 823 "xref stream", xref_offset,
822 "Cross-reference stream's /Index's item " + 824 "Cross-reference stream's /Index's item " +
823 QUtil::int_to_string(i) + 825 QUtil::int_to_string(i) +
@@ -856,7 +858,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -856,7 +858,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
856 858
857 if (expected_size != actual_size) 859 if (expected_size != actual_size)
858 { 860 {
859 - QPDFExc x(qpdf_e_damaged_pdf, this->file.getName(), 861 + QPDFExc x(qpdf_e_damaged_pdf, this->file->getName(),
860 "xref stream", xref_offset, 862 "xref stream", xref_offset,
861 "Cross-reference stream data has the wrong size;" 863 "Cross-reference stream data has the wrong size;"
862 " expected = " + QUtil::int_to_string(expected_size) + 864 " expected = " + QUtil::int_to_string(expected_size) +
@@ -938,8 +940,8 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -938,8 +940,8 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
938 { 940 {
939 if (! dict.getKey("/Prev").isInteger()) 941 if (! dict.getKey("/Prev").isInteger())
940 { 942 {
941 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
942 - "xref stream", this->file.getLastOffset(), 943 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  944 + "xref stream", this->file->getLastOffset(),
943 "/Prev key in xref stream dictionary is not " 945 "/Prev key in xref stream dictionary is not "
944 "an integer"); 946 "an integer");
945 } 947 }
@@ -1008,8 +1010,8 @@ QPDF::insertXrefEntry(int obj, int f0, int f1, int f2, bool overwrite) @@ -1008,8 +1010,8 @@ QPDF::insertXrefEntry(int obj, int f0, int f1, int f2, bool overwrite)
1008 break; 1010 break;
1009 1011
1010 default: 1012 default:
1011 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
1012 - "xref stream", this->file.getLastOffset(), 1013 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  1014 + "xref stream", this->file->getLastOffset(),
1013 "unknown xref stream entry type " + 1015 "unknown xref stream entry type " +
1014 QUtil::int_to_string(f0)); 1016 QUtil::int_to_string(f0));
1015 break; 1017 break;
@@ -1068,7 +1070,8 @@ QPDF::setLastObjectDescription(std::string const&amp; description, @@ -1068,7 +1070,8 @@ QPDF::setLastObjectDescription(std::string const&amp; description,
1068 } 1070 }
1069 1071
1070 QPDFObjectHandle 1072 QPDFObjectHandle
1071 -QPDF::readObject(InputSource* input, std::string const& description, 1073 +QPDF::readObject(PointerHolder<InputSource> input,
  1074 + std::string const& description,
1072 int objid, int generation, bool in_object_stream) 1075 int objid, int generation, bool in_object_stream)
1073 { 1076 {
1074 setLastObjectDescription(description, objid, generation); 1077 setLastObjectDescription(description, objid, generation);
@@ -1082,7 +1085,7 @@ QPDF::readObject(InputSource* input, std::string const&amp; description, @@ -1082,7 +1085,7 @@ QPDF::readObject(InputSource* input, std::string const&amp; description,
1082 } 1085 }
1083 1086
1084 QPDFObjectHandle 1087 QPDFObjectHandle
1085 -QPDF::readObjectInternal(InputSource* input, 1088 +QPDF::readObjectInternal(PointerHolder<InputSource> input,
1086 int objid, int generation, 1089 int objid, int generation,
1087 bool in_object_stream, 1090 bool in_object_stream,
1088 bool in_array, bool in_dictionary) 1091 bool in_array, bool in_dictionary)
@@ -1197,20 +1200,6 @@ QPDF::readObjectInternal(InputSource* input, @@ -1197,20 +1200,6 @@ QPDF::readObjectInternal(InputSource* input,
1197 olist.pop_back(); 1200 olist.pop_back();
1198 olist.pop_back(); 1201 olist.pop_back();
1199 } 1202 }
1200 - else if ((value == "endobj") &&  
1201 - (! (in_array || in_dictionary)))  
1202 - {  
1203 - // Nothing in the PDF spec appears to allow empty  
1204 - // objects, but they have been encountered in  
1205 - // actual PDF files and Adobe Reader appears to  
1206 - // ignore them.  
1207 - warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(),  
1208 - this->last_object_description,  
1209 - input->getLastOffset(),  
1210 - "empty object treated as null"));  
1211 - object = QPDFObjectHandle::newNull();  
1212 - input->seek(input->getLastOffset(), SEEK_SET);  
1213 - }  
1214 else 1203 else
1215 { 1204 {
1216 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(), 1205 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
@@ -1386,7 +1375,7 @@ QPDF::readObjectInternal(InputSource* input, @@ -1386,7 +1375,7 @@ QPDF::readObjectInternal(InputSource* input,
1386 } 1375 }
1387 1376
1388 int 1377 int
1389 -QPDF::recoverStreamLength(InputSource* input, 1378 +QPDF::recoverStreamLength(PointerHolder<InputSource> input,
1390 int objid, int generation, off_t stream_offset) 1379 int objid, int generation, off_t stream_offset)
1391 { 1380 {
1392 static PCRE endobj_re("^\\s*endobj\\b"); 1381 static PCRE endobj_re("^\\s*endobj\\b");
@@ -1473,7 +1462,7 @@ QPDF::recoverStreamLength(InputSource* input, @@ -1473,7 +1462,7 @@ QPDF::recoverStreamLength(InputSource* input,
1473 } 1462 }
1474 1463
1475 QPDFTokenizer::Token 1464 QPDFTokenizer::Token
1476 -QPDF::readToken(InputSource* input) 1465 +QPDF::readToken(PointerHolder<InputSource> input)
1477 { 1466 {
1478 off_t offset = input->tell(); 1467 off_t offset = input->tell();
1479 QPDFTokenizer::Token token; 1468 QPDFTokenizer::Token token;
@@ -1523,11 +1512,11 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1523,11 +1512,11 @@ QPDF::readObjectAtOffset(bool try_recovery,
1523 int& objid, int& generation) 1512 int& objid, int& generation)
1524 { 1513 {
1525 setLastObjectDescription(description, exp_objid, exp_generation); 1514 setLastObjectDescription(description, exp_objid, exp_generation);
1526 - this->file.seek(offset, SEEK_SET); 1515 + this->file->seek(offset, SEEK_SET);
1527 1516
1528 - QPDFTokenizer::Token tobjid = readToken(&this->file);  
1529 - QPDFTokenizer::Token tgen = readToken(&this->file);  
1530 - QPDFTokenizer::Token tobj = readToken(&this->file); 1517 + QPDFTokenizer::Token tobjid = readToken(this->file);
  1518 + QPDFTokenizer::Token tgen = readToken(this->file);
  1519 + QPDFTokenizer::Token tobj = readToken(this->file);
1531 1520
1532 bool objidok = (tobjid.getType() == QPDFTokenizer::tt_integer); 1521 bool objidok = (tobjid.getType() == QPDFTokenizer::tt_integer);
1533 int genok = (tgen.getType() == QPDFTokenizer::tt_integer); 1522 int genok = (tgen.getType() == QPDFTokenizer::tt_integer);
@@ -1542,7 +1531,7 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1542,7 +1531,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1542 if (! (objidok && genok && objok)) 1531 if (! (objidok && genok && objok))
1543 { 1532 {
1544 QTC::TC("qpdf", "QPDF expected n n obj"); 1533 QTC::TC("qpdf", "QPDF expected n n obj");
1545 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 1534 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1546 this->last_object_description, offset, 1535 this->last_object_description, offset,
1547 "expected n n obj"); 1536 "expected n n obj");
1548 } 1537 }
@@ -1553,7 +1542,7 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1553,7 +1542,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1553 (! ((objid == exp_objid) && (generation == exp_generation)))) 1542 (! ((objid == exp_objid) && (generation == exp_generation))))
1554 { 1543 {
1555 QTC::TC("qpdf", "QPDF err wrong objid/generation"); 1544 QTC::TC("qpdf", "QPDF err wrong objid/generation");
1556 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 1545 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1557 this->last_object_description, offset, 1546 this->last_object_description, offset,
1558 std::string("expected ") + 1547 std::string("expected ") +
1559 QUtil::int_to_string(exp_objid) + " " + 1548 QUtil::int_to_string(exp_objid) + " " +
@@ -1581,7 +1570,7 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1581,7 +1570,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1581 { 1570 {
1582 QTC::TC("qpdf", "QPDF object gone after xref reconstruction"); 1571 QTC::TC("qpdf", "QPDF object gone after xref reconstruction");
1583 warn(QPDFExc( 1572 warn(QPDFExc(
1584 - qpdf_e_damaged_pdf, this->file.getName(), 1573 + qpdf_e_damaged_pdf, this->file->getName(),
1585 "", 0, 1574 "", 0,
1586 std::string( 1575 std::string(
1587 "object " + 1576 "object " +
@@ -1600,14 +1589,14 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1600,14 +1589,14 @@ QPDF::readObjectAtOffset(bool try_recovery,
1600 } 1589 }
1601 1590
1602 QPDFObjectHandle oh = readObject( 1591 QPDFObjectHandle oh = readObject(
1603 - &this->file, description, objid, generation, false); 1592 + this->file, description, objid, generation, false);
1604 1593
1605 - if (! (readToken(&this->file) == 1594 + if (! (readToken(this->file) ==
1606 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) 1595 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj")))
1607 { 1596 {
1608 QTC::TC("qpdf", "QPDF err expected endobj"); 1597 QTC::TC("qpdf", "QPDF err expected endobj");
1609 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
1610 - this->last_object_description, this->file.getLastOffset(), 1598 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  1599 + this->last_object_description, this->file->getLastOffset(),
1611 "expected endobj")); 1600 "expected endobj"));
1612 } 1601 }
1613 1602
@@ -1624,28 +1613,28 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1624,28 +1613,28 @@ QPDF::readObjectAtOffset(bool try_recovery,
1624 // linearization hint tables. Offsets and lengths of objects 1613 // linearization hint tables. Offsets and lengths of objects
1625 // may imply the end of an object to be anywhere between these 1614 // may imply the end of an object to be anywhere between these
1626 // values. 1615 // values.
1627 - off_t end_before_space = this->file.tell(); 1616 + off_t end_before_space = this->file->tell();
1628 1617
1629 // skip over spaces 1618 // skip over spaces
1630 while (true) 1619 while (true)
1631 { 1620 {
1632 char ch; 1621 char ch;
1633 - if (this->file.read(&ch, 1)) 1622 + if (this->file->read(&ch, 1))
1634 { 1623 {
1635 if (! isspace((unsigned char)ch)) 1624 if (! isspace((unsigned char)ch))
1636 { 1625 {
1637 - this->file.seek(-1, SEEK_CUR); 1626 + this->file->seek(-1, SEEK_CUR);
1638 break; 1627 break;
1639 } 1628 }
1640 } 1629 }
1641 else 1630 else
1642 { 1631 {
1643 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 1632 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1644 this->last_object_description, offset, 1633 this->last_object_description, offset,
1645 "EOF after endobj"); 1634 "EOF after endobj");
1646 } 1635 }
1647 } 1636 }
1648 - off_t end_after_space = this->file.tell(); 1637 + off_t end_after_space = this->file->tell();
1649 1638
1650 this->obj_cache[og] = 1639 this->obj_cache[og] =
1651 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), 1640 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh),
@@ -1690,7 +1679,7 @@ QPDF::resolve(int objid, int generation) @@ -1690,7 +1679,7 @@ QPDF::resolve(int objid, int generation)
1690 break; 1679 break;
1691 1680
1692 default: 1681 default:
1693 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), "", 0, 1682 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
1694 "object " + 1683 "object " +
1695 QUtil::int_to_string(objid) + "/" + 1684 QUtil::int_to_string(objid) + "/" +
1696 QUtil::int_to_string(generation) + 1685 QUtil::int_to_string(generation) +
@@ -1708,9 +1697,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1708,9 +1697,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1708 QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0); 1697 QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0);
1709 if (! obj_stream.isStream()) 1698 if (! obj_stream.isStream())
1710 { 1699 {
1711 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 1700 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1712 this->last_object_description, 1701 this->last_object_description,
1713 - this->file.getLastOffset(), 1702 + this->file->getLastOffset(),
1714 "supposed object stream " + 1703 "supposed object stream " +
1715 QUtil::int_to_string(obj_stream_number) + 1704 QUtil::int_to_string(obj_stream_number) +
1716 " is not a stream"); 1705 " is not a stream");
@@ -1727,9 +1716,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1727,9 +1716,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1727 dict.getKey("/Type").getName() == "/ObjStm")) 1716 dict.getKey("/Type").getName() == "/ObjStm"))
1728 { 1717 {
1729 QTC::TC("qpdf", "QPDF ERR object stream with wrong type"); 1718 QTC::TC("qpdf", "QPDF ERR object stream with wrong type");
1730 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 1719 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1731 this->last_object_description, 1720 this->last_object_description,
1732 - this->file.getLastOffset(), 1721 + this->file->getLastOffset(),
1733 "supposed object stream " + 1722 "supposed object stream " +
1734 QUtil::int_to_string(obj_stream_number) + 1723 QUtil::int_to_string(obj_stream_number) +
1735 " has wrong type"); 1724 " has wrong type");
@@ -1738,9 +1727,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1738,9 +1727,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1738 if (! (dict.getKey("/N").isInteger() && 1727 if (! (dict.getKey("/N").isInteger() &&
1739 dict.getKey("/First").isInteger())) 1728 dict.getKey("/First").isInteger()))
1740 { 1729 {
1741 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 1730 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1742 this->last_object_description, 1731 this->last_object_description,
1743 - this->file.getLastOffset(), 1732 + this->file->getLastOffset(),
1744 "object stream " + 1733 "object stream " +
1745 QUtil::int_to_string(obj_stream_number) + 1734 QUtil::int_to_string(obj_stream_number) +
1746 " has incorrect keys"); 1735 " has incorrect keys");
@@ -1752,19 +1741,19 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1752,19 +1741,19 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1752 std::map<int, int> offsets; 1741 std::map<int, int> offsets;
1753 1742
1754 PointerHolder<Buffer> bp = obj_stream.getStreamData(); 1743 PointerHolder<Buffer> bp = obj_stream.getStreamData();
1755 - BufferInputSource input( 1744 + PointerHolder<InputSource> input = new BufferInputSource(
1756 "object stream " + QUtil::int_to_string(obj_stream_number), 1745 "object stream " + QUtil::int_to_string(obj_stream_number),
1757 bp.getPointer()); 1746 bp.getPointer());
1758 1747
1759 for (int i = 0; i < n; ++i) 1748 for (int i = 0; i < n; ++i)
1760 { 1749 {
1761 - QPDFTokenizer::Token tnum = readToken(&input);  
1762 - QPDFTokenizer::Token toffset = readToken(&input); 1750 + QPDFTokenizer::Token tnum = readToken(input);
  1751 + QPDFTokenizer::Token toffset = readToken(input);
1763 if (! ((tnum.getType() == QPDFTokenizer::tt_integer) && 1752 if (! ((tnum.getType() == QPDFTokenizer::tt_integer) &&
1764 (toffset.getType() == QPDFTokenizer::tt_integer))) 1753 (toffset.getType() == QPDFTokenizer::tt_integer)))
1765 { 1754 {
1766 - throw QPDFExc(qpdf_e_damaged_pdf, input.getName(),  
1767 - this->last_object_description, input.getLastOffset(), 1755 + throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
  1756 + this->last_object_description, input->getLastOffset(),
1768 "expected integer in object stream header"); 1757 "expected integer in object stream header");
1769 } 1758 }
1770 1759
@@ -1778,8 +1767,8 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1778,8 +1767,8 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1778 { 1767 {
1779 int obj = (*iter).first; 1768 int obj = (*iter).first;
1780 int offset = (*iter).second; 1769 int offset = (*iter).second;
1781 - input.seek(offset, SEEK_SET);  
1782 - QPDFObjectHandle oh = readObject(&input, "", obj, 0, true); 1770 + input->seek(offset, SEEK_SET);
  1771 + QPDFObjectHandle oh = readObject(input, "", obj, 0, true);
1783 1772
1784 // Store in cache 1773 // Store in cache
1785 ObjGen og(obj, 0); 1774 ObjGen og(obj, 0);
@@ -1839,7 +1828,7 @@ QPDF::trimTrailerForWrite() @@ -1839,7 +1828,7 @@ QPDF::trimTrailerForWrite()
1839 std::string 1828 std::string
1840 QPDF::getFilename() const 1829 QPDF::getFilename() const
1841 { 1830 {
1842 - return this->file.getName(); 1831 + return this->file->getName();
1843 } 1832 }
1844 1833
1845 std::string 1834 std::string
@@ -1988,18 +1977,18 @@ QPDF::pipeStreamData(int objid, int generation, @@ -1988,18 +1977,18 @@ QPDF::pipeStreamData(int objid, int generation,
1988 1977
1989 try 1978 try
1990 { 1979 {
1991 - this->file.seek(offset, SEEK_SET); 1980 + this->file->seek(offset, SEEK_SET);
1992 char buf[10240]; 1981 char buf[10240];
1993 while (length > 0) 1982 while (length > 0)
1994 { 1983 {
1995 size_t to_read = (sizeof(buf) < length ? sizeof(buf) : length); 1984 size_t to_read = (sizeof(buf) < length ? sizeof(buf) : length);
1996 - size_t len = this->file.read(buf, to_read); 1985 + size_t len = this->file->read(buf, to_read);
1997 if (len == 0) 1986 if (len == 0)
1998 { 1987 {
1999 throw QPDFExc(qpdf_e_damaged_pdf, 1988 throw QPDFExc(qpdf_e_damaged_pdf,
2000 - this->file.getName(), 1989 + this->file->getName(),
2001 this->last_object_description, 1990 this->last_object_description,
2002 - this->file.getLastOffset(), 1991 + this->file->getLastOffset(),
2003 "unexpected EOF reading stream data"); 1992 "unexpected EOF reading stream data");
2004 } 1993 }
2005 length -= len; 1994 length -= len;
@@ -2013,8 +2002,8 @@ QPDF::pipeStreamData(int objid, int generation, @@ -2013,8 +2002,8 @@ QPDF::pipeStreamData(int objid, int generation,
2013 catch (std::runtime_error& e) 2002 catch (std::runtime_error& e)
2014 { 2003 {
2015 QTC::TC("qpdf", "QPDF decoding error warning"); 2004 QTC::TC("qpdf", "QPDF decoding error warning");
2016 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
2017 - "", this->file.getLastOffset(), 2005 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  2006 + "", this->file->getLastOffset(),
2018 "error decoding stream data for object " + 2007 "error decoding stream data for object " +
2019 QUtil::int_to_string(objid) + " " + 2008 QUtil::int_to_string(objid) + " " +
2020 QUtil::int_to_string(generation) + ": " + e.what())); 2009 QUtil::int_to_string(generation) + ": " + e.what()));
@@ -2070,9 +2059,9 @@ QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages, @@ -2070,9 +2059,9 @@ QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages,
2070 } 2059 }
2071 else 2060 else
2072 { 2061 {
2073 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 2062 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
2074 this->last_object_description, 2063 this->last_object_description,
2075 - this->file.getLastOffset(), 2064 + this->file->getLastOffset(),
2076 ": invalid Type in page tree"); 2065 ": invalid Type in page tree");
2077 } 2066 }
2078 } 2067 }
libqpdf/QPDF_encryption.cc
@@ -336,8 +336,8 @@ QPDF::initializeEncryption() @@ -336,8 +336,8 @@ QPDF::initializeEncryption()
336 (id_obj.getArrayNItems() == 2) && 336 (id_obj.getArrayNItems() == 2) &&
337 id_obj.getArrayItem(0).isString())) 337 id_obj.getArrayItem(0).isString()))
338 { 338 {
339 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
340 - "trailer", this->file.getLastOffset(), 339 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  340 + "trailer", this->file->getLastOffset(),
341 "invalid /ID in trailer dictionary"); 341 "invalid /ID in trailer dictionary");
342 } 342 }
343 343
@@ -345,23 +345,23 @@ QPDF::initializeEncryption() @@ -345,23 +345,23 @@ QPDF::initializeEncryption()
345 QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt"); 345 QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt");
346 if (! encryption_dict.isDictionary()) 346 if (! encryption_dict.isDictionary())
347 { 347 {
348 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 348 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
349 this->last_object_description, 349 this->last_object_description,
350 - this->file.getLastOffset(), 350 + this->file->getLastOffset(),
351 "/Encrypt in trailer dictionary is not a dictionary"); 351 "/Encrypt in trailer dictionary is not a dictionary");
352 } 352 }
353 353
354 if (! (encryption_dict.getKey("/Filter").isName() && 354 if (! (encryption_dict.getKey("/Filter").isName() &&
355 (encryption_dict.getKey("/Filter").getName() == "/Standard"))) 355 (encryption_dict.getKey("/Filter").getName() == "/Standard")))
356 { 356 {
357 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
358 - "encryption dictionary", this->file.getLastOffset(), 357 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  358 + "encryption dictionary", this->file->getLastOffset(),
359 "unsupported encryption filter"); 359 "unsupported encryption filter");
360 } 360 }
361 if (! encryption_dict.getKey("/SubFilter").isNull()) 361 if (! encryption_dict.getKey("/SubFilter").isNull())
362 { 362 {
363 - warn(QPDFExc(qpdf_e_unsupported, this->file.getName(),  
364 - "encryption dictionary", this->file.getLastOffset(), 363 + warn(QPDFExc(qpdf_e_unsupported, this->file->getName(),
  364 + "encryption dictionary", this->file->getLastOffset(),
365 "file uses encryption SubFilters," 365 "file uses encryption SubFilters,"
366 " which qpdf does not support")); 366 " which qpdf does not support"));
367 } 367 }
@@ -372,8 +372,8 @@ QPDF::initializeEncryption() @@ -372,8 +372,8 @@ QPDF::initializeEncryption()
372 encryption_dict.getKey("/U").isString() && 372 encryption_dict.getKey("/U").isString() &&
373 encryption_dict.getKey("/P").isInteger())) 373 encryption_dict.getKey("/P").isInteger()))
374 { 374 {
375 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
376 - "encryption dictionary", this->file.getLastOffset(), 375 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  376 + "encryption dictionary", this->file->getLastOffset(),
377 "some encryption dictionary parameters are missing " 377 "some encryption dictionary parameters are missing "
378 "or the wrong type"); 378 "or the wrong type");
379 } 379 }
@@ -387,8 +387,8 @@ QPDF::initializeEncryption() @@ -387,8 +387,8 @@ QPDF::initializeEncryption()
387 if (! (((R == 2) || (R == 3) || (R == 4)) && 387 if (! (((R == 2) || (R == 3) || (R == 4)) &&
388 ((V == 1) || (V == 2) || (V == 4)))) 388 ((V == 1) || (V == 2) || (V == 4))))
389 { 389 {
390 - throw QPDFExc(qpdf_e_unsupported, this->file.getName(),  
391 - "encryption dictionary", this->file.getLastOffset(), 390 + throw QPDFExc(qpdf_e_unsupported, this->file->getName(),
  391 + "encryption dictionary", this->file->getLastOffset(),
392 "Unsupported /R or /V in encryption dictionary"); 392 "Unsupported /R or /V in encryption dictionary");
393 } 393 }
394 394
@@ -396,8 +396,8 @@ QPDF::initializeEncryption() @@ -396,8 +396,8 @@ QPDF::initializeEncryption()
396 396
397 if (! ((O.length() == key_bytes) && (U.length() == key_bytes))) 397 if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
398 { 398 {
399 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
400 - "encryption dictionary", this->file.getLastOffset(), 399 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  400 + "encryption dictionary", this->file->getLastOffset(),
401 "incorrect length for /O and/or /P in " 401 "incorrect length for /O and/or /P in "
402 "encryption dictionary"); 402 "encryption dictionary");
403 } 403 }
@@ -408,8 +408,8 @@ QPDF::initializeEncryption() @@ -408,8 +408,8 @@ QPDF::initializeEncryption()
408 Length = encryption_dict.getKey("/Length").getIntValue(); 408 Length = encryption_dict.getKey("/Length").getIntValue();
409 if ((Length % 8) || (Length < 40) || (Length > 128)) 409 if ((Length % 8) || (Length < 40) || (Length > 128))
410 { 410 {
411 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
412 - "encryption dictionary", this->file.getLastOffset(), 411 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  412 + "encryption dictionary", this->file->getLastOffset(),
413 "invalid /Length value in encryption dictionary"); 413 "invalid /Length value in encryption dictionary");
414 } 414 }
415 } 415 }
@@ -472,8 +472,8 @@ QPDF::initializeEncryption() @@ -472,8 +472,8 @@ QPDF::initializeEncryption()
472 } 472 }
473 if (this->cf_file != this->cf_stream) 473 if (this->cf_file != this->cf_stream)
474 { 474 {
475 - throw QPDFExc(qpdf_e_unsupported, this->file.getName(),  
476 - "encryption dictionary", this->file.getLastOffset(), 475 + throw QPDFExc(qpdf_e_unsupported, this->file->getName(),
  476 + "encryption dictionary", this->file->getLastOffset(),
477 "This document has embedded files that are" 477 "This document has embedded files that are"
478 " encrypted differently from the rest of the file." 478 " encrypted differently from the rest of the file."
479 " qpdf does not presently support this due to" 479 " qpdf does not presently support this due to"
@@ -494,7 +494,7 @@ QPDF::initializeEncryption() @@ -494,7 +494,7 @@ QPDF::initializeEncryption()
494 } 494 }
495 else 495 else
496 { 496 {
497 - throw QPDFExc(qpdf_e_password, this->file.getName(), 497 + throw QPDFExc(qpdf_e_password, this->file->getName(),
498 "", 0, "invalid password"); 498 "", 0, "invalid password");
499 } 499 }
500 500
@@ -545,9 +545,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation) @@ -545,9 +545,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
545 break; 545 break;
546 546
547 default: 547 default:
548 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 548 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
549 this->last_object_description, 549 this->last_object_description,
550 - this->file.getLastOffset(), 550 + this->file->getLastOffset(),
551 "unknown encryption filter for strings" 551 "unknown encryption filter for strings"
552 " (check /StrF in /Encrypt dictionary);" 552 " (check /StrF in /Encrypt dictionary);"
553 " strings may be decrypted improperly")); 553 " strings may be decrypted improperly"));
@@ -595,8 +595,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation) @@ -595,8 +595,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
595 } 595 }
596 catch (std::runtime_error& e) 596 catch (std::runtime_error& e)
597 { 597 {
598 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),  
599 - this->last_object_description, this->file.getLastOffset(), 598 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  599 + this->last_object_description,
  600 + this->file->getLastOffset(),
600 "error decrypting string for object " + 601 "error decrypting string for object " +
601 QUtil::int_to_string(objid) + " " + 602 QUtil::int_to_string(objid) + " " +
602 QUtil::int_to_string(generation) + ": " + e.what()); 603 QUtil::int_to_string(generation) + ": " + e.what());
@@ -669,9 +670,9 @@ QPDF::decryptStream(Pipeline*&amp; pipeline, int objid, int generation, @@ -669,9 +670,9 @@ QPDF::decryptStream(Pipeline*&amp; pipeline, int objid, int generation,
669 670
670 default: 671 default:
671 // filter local to this stream. 672 // filter local to this stream.
672 - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 673 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
673 this->last_object_description, 674 this->last_object_description,
674 - this->file.getLastOffset(), 675 + this->file->getLastOffset(),
675 "unknown encryption filter for streams" 676 "unknown encryption filter for streams"
676 " (check " + method_source + ");" 677 " (check " + method_source + ");"
677 " streams may be decrypted improperly")); 678 " streams may be decrypted improperly"));
libqpdf/QPDF_linearization.cc
@@ -87,10 +87,10 @@ QPDF::isLinearized() @@ -87,10 +87,10 @@ QPDF::isLinearized()
87 static int const tbuf_size = 1025; 87 static int const tbuf_size = 1025;
88 88
89 char* buf = new char[tbuf_size]; 89 char* buf = new char[tbuf_size];
90 - this->file.seek(0, SEEK_SET); 90 + this->file->seek(0, SEEK_SET);
91 PointerHolder<char> b(buf); // guarantee deletion 91 PointerHolder<char> b(buf); // guarantee deletion
92 memset(buf, '\0', tbuf_size); 92 memset(buf, '\0', tbuf_size);
93 - this->file.read(buf, tbuf_size - 1); 93 + this->file->read(buf, tbuf_size - 1);
94 94
95 static PCRE lindict_re("(?s:(\\d+)\\s+0\\s+obj\\s*<<)"); 95 static PCRE lindict_re("(?s:(\\d+)\\s+0\\s+obj\\s*<<)");
96 96
@@ -147,8 +147,8 @@ QPDF::isLinearized() @@ -147,8 +147,8 @@ QPDF::isLinearized()
147 if (L.isInteger()) 147 if (L.isInteger())
148 { 148 {
149 int Li = L.getIntValue(); 149 int Li = L.getIntValue();
150 - this->file.seek(0, SEEK_END);  
151 - if (Li != this->file.tell()) 150 + this->file->seek(0, SEEK_END);
  151 + if (Li != this->file->tell())
152 { 152 {
153 QTC::TC("qpdf", "QPDF /L mismatch"); 153 QTC::TC("qpdf", "QPDF /L mismatch");
154 return false; 154 return false;
@@ -194,9 +194,9 @@ QPDF::readLinearizationData() @@ -194,9 +194,9 @@ QPDF::readLinearizationData()
194 T.isInteger() && 194 T.isInteger() &&
195 (P.isInteger() || P.isNull()))) 195 (P.isInteger() || P.isNull())))
196 { 196 {
197 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 197 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
198 "linearization dictionary", 198 "linearization dictionary",
199 - this->file.getLastOffset(), 199 + this->file->getLastOffset(),
200 "some keys in linearization dictionary are of " 200 "some keys in linearization dictionary are of "
201 "the wrong type"); 201 "the wrong type");
202 } 202 }
@@ -205,9 +205,9 @@ QPDF::readLinearizationData() @@ -205,9 +205,9 @@ QPDF::readLinearizationData()
205 unsigned int n_H_items = H.getArrayNItems(); 205 unsigned int n_H_items = H.getArrayNItems();
206 if (! ((n_H_items == 2) || (n_H_items == 4))) 206 if (! ((n_H_items == 2) || (n_H_items == 4)))
207 { 207 {
208 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 208 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
209 "linearization dictionary", 209 "linearization dictionary",
210 - this->file.getLastOffset(), 210 + this->file->getLastOffset(),
211 "H has the wrong number of items"); 211 "H has the wrong number of items");
212 } 212 }
213 213
@@ -221,9 +221,9 @@ QPDF::readLinearizationData() @@ -221,9 +221,9 @@ QPDF::readLinearizationData()
221 } 221 }
222 else 222 else
223 { 223 {
224 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 224 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
225 "linearization dictionary", 225 "linearization dictionary",
226 - this->file.getLastOffset(), 226 + this->file->getLastOffset(),
227 "some H items are of the wrong type"); 227 "some H items are of the wrong type");
228 } 228 }
229 } 229 }
@@ -318,9 +318,9 @@ QPDF::readHintStream(Pipeline&amp; pl, off_t offset, size_t length) @@ -318,9 +318,9 @@ QPDF::readHintStream(Pipeline&amp; pl, off_t offset, size_t length)
318 off_t max_end_offset = oc.end_after_space; 318 off_t max_end_offset = oc.end_after_space;
319 if (! H.isStream()) 319 if (! H.isStream())
320 { 320 {
321 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 321 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
322 "linearization dictionary", 322 "linearization dictionary",
323 - this->file.getLastOffset(), 323 + this->file->getLastOffset(),
324 "hint table is not a stream"); 324 "hint table is not a stream");
325 } 325 }
326 326
@@ -354,9 +354,9 @@ QPDF::readHintStream(Pipeline&amp; pl, off_t offset, size_t length) @@ -354,9 +354,9 @@ QPDF::readHintStream(Pipeline&amp; pl, off_t offset, size_t length)
354 std::cout << "expected = " << computed_end 354 std::cout << "expected = " << computed_end
355 << "; actual = " << min_end_offset << ".." 355 << "; actual = " << min_end_offset << ".."
356 << max_end_offset << std::endl; 356 << max_end_offset << std::endl;
357 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 357 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
358 "linearization dictionary", 358 "linearization dictionary",
359 - this->file.getLastOffset(), 359 + this->file->getLastOffset(),
360 "hint table length mismatch"); 360 "hint table length mismatch");
361 } 361 }
362 H.pipeStreamData(&pl, true, false, false); 362 H.pipeStreamData(&pl, true, false, false);
@@ -509,24 +509,25 @@ QPDF::checkLinearizationInternal() @@ -509,24 +509,25 @@ QPDF::checkLinearizationInternal()
509 } 509 }
510 510
511 // T: offset of whitespace character preceding xref entry for object 0 511 // T: offset of whitespace character preceding xref entry for object 0
512 - this->file.seek(p.xref_zero_offset, SEEK_SET); 512 + this->file->seek(p.xref_zero_offset, SEEK_SET);
513 while (1) 513 while (1)
514 { 514 {
515 char ch; 515 char ch;
516 - this->file.read(&ch, 1); 516 + this->file->read(&ch, 1);
517 if (! ((ch == ' ') || (ch == '\r') || (ch == '\n'))) 517 if (! ((ch == ' ') || (ch == '\r') || (ch == '\n')))
518 { 518 {
519 - this->file.seek(-1, SEEK_CUR); 519 + this->file->seek(-1, SEEK_CUR);
520 break; 520 break;
521 } 521 }
522 } 522 }
523 - if (this->file.tell() != this->first_xref_item_offset) 523 + if (this->file->tell() != this->first_xref_item_offset)
524 { 524 {
525 QTC::TC("qpdf", "QPDF err /T mismatch"); 525 QTC::TC("qpdf", "QPDF err /T mismatch");
526 errors.push_back("space before first xref item (/T) mismatch " 526 errors.push_back("space before first xref item (/T) mismatch "
527 "(computed = " + 527 "(computed = " +
528 QUtil::int_to_string(this->first_xref_item_offset) + 528 QUtil::int_to_string(this->first_xref_item_offset) +
529 - "; file = " + QUtil::int_to_string(this->file.tell())); 529 + "; file = " +
  530 + QUtil::int_to_string(this->file->tell()));
530 } 531 }
531 532
532 // P: first page number -- Implementation note 124 says Acrobat 533 // P: first page number -- Implementation note 124 says Acrobat
@@ -1014,7 +1015,7 @@ QPDF::showLinearizationData() @@ -1014,7 +1015,7 @@ QPDF::showLinearizationData()
1014 void 1015 void
1015 QPDF::dumpLinearizationDataInternal() 1016 QPDF::dumpLinearizationDataInternal()
1016 { 1017 {
1017 - std::cout << this->file.getName() << ": linearization data:" << std::endl 1018 + std::cout << this->file->getName() << ": linearization data:" << std::endl
1018 << std::endl; 1019 << std::endl;
1019 1020
1020 std::cout 1021 std::cout
libqpdf/QPDF_optimization.cc
@@ -246,9 +246,9 @@ QPDF::optimizePagesTree( @@ -246,9 +246,9 @@ QPDF::optimizePagesTree(
246 { 246 {
247 if (! allow_changes) 247 if (! allow_changes)
248 { 248 {
249 - throw QPDFExc(qpdf_e_internal, this->file.getName(), 249 + throw QPDFExc(qpdf_e_internal, this->file->getName(),
250 this->last_object_description, 250 this->last_object_description,
251 - this->file.getLastOffset(), 251 + this->file->getLastOffset(),
252 "optimize detected an " 252 "optimize detected an "
253 "inheritable resource when called " 253 "inheritable resource when called "
254 "in no-change mode"); 254 "in no-change mode");
@@ -354,9 +354,9 @@ QPDF::optimizePagesTree( @@ -354,9 +354,9 @@ QPDF::optimizePagesTree(
354 } 354 }
355 else 355 else
356 { 356 {
357 - throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(), 357 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
358 this->last_object_description, 358 this->last_object_description,
359 - this->file.getLastOffset(), 359 + this->file->getLastOffset(),
360 "invalid Type in page tree"); 360 "invalid Type in page tree");
361 } 361 }
362 } 362 }