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 423 void setLastObjectDescription(std::string const& description,
424 424 int objid, int generation);
425 425 QPDFObjectHandle readObject(
426   - InputSource*, std::string const& description,
  426 + PointerHolder<InputSource>, std::string const& description,
427 427 int objid, int generation, bool in_object_stream);
428 428 QPDFObjectHandle readObjectInternal(
429   - InputSource* input, int objid, int generation,
  429 + PointerHolder<InputSource> input, int objid, int generation,
430 430 bool in_object_stream,
431 431 bool in_array, bool in_dictionary);
432 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 437 QPDFObjectHandle readObjectAtOffset(
437 438 bool attempt_recovery,
... ... @@ -785,7 +786,7 @@ class QPDF
785 786  
786 787  
787 788 QPDFTokenizer tokenizer;
788   - FileInputSource file;
  789 + PointerHolder<InputSource> file;
789 790 std::string last_object_description;
790 791 bool encrypted;
791 792 bool encryption_initialized;
... ...
libqpdf/QPDF.cc
... ... @@ -303,7 +303,9 @@ QPDF::~QPDF()
303 303 void
304 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 309 if (password)
308 310 {
309 311 this->provided_password = password;
... ... @@ -343,7 +345,7 @@ QPDF::parse()
343 345 static PCRE header_re("^%PDF-(1.\\d+)\\b");
344 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 349 PCRE::Match m1 = header_re.match(line.c_str());
348 350 if (m1)
349 351 {
... ... @@ -356,7 +358,7 @@ QPDF::parse()
356 358 else
357 359 {
358 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 362 "", 0, "not a PDF file");
361 363 }
362 364  
... ... @@ -364,14 +366,14 @@ QPDF::parse()
364 366 // the file. We add an extra 30 characters to leave room for the
365 367 // startxref stuff.
366 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 374 else
373 375 {
374   - this->file.rewind();
  376 + this->file->rewind();
375 377 }
376 378 char* buf = new char[tbuf_size + 1];
377 379 // Put buf in a PointerHolder to guarantee deletion of buf. This
... ... @@ -379,7 +381,7 @@ QPDF::parse()
379 381 // an array of fundamental types.
380 382 PointerHolder<char> b(buf);
381 383 memset(buf, '\0', tbuf_size + 1);
382   - this->file.read(buf, tbuf_size);
  384 + this->file->read(buf, tbuf_size);
383 385  
384 386 // Since buf may contain null characters, we can't do a regexp
385 387 // search on buf directly. Find the last occurrence within buf
... ... @@ -401,7 +403,7 @@ QPDF::parse()
401 403 if (! m2)
402 404 {
403 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 407 "can't find startxref");
406 408 }
407 409 off_t xref_offset = atoi(m2.getMatch(1).c_str());
... ... @@ -450,10 +452,10 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
450 452 static PCRE endobj_re("^\\s*endobj\\b");
451 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 456 "file is damaged"));
455 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 459 "Attempting to reconstruct cross-reference table"));
458 460  
459 461 // Delete all references to type 1 (uncompressed) objects
... ... @@ -473,13 +475,13 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
473 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 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 485 if (in_obj)
484 486 {
485 487 if (endobj_re.match(line.c_str()))
... ... @@ -495,17 +497,17 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
495 497 in_obj = true;
496 498 int obj = atoi(m.getMatch(1).c_str());
497 499 int gen = atoi(m.getMatch(2).c_str());
498   - int offset = this->file.getLastOffset();
  500 + int offset = this->file->getLastOffset();
499 501 insertXrefEntry(obj, 1, offset, gen, true);
500 502 }
501 503 else if ((! this->trailer.isInitialized()) &&
502 504 trailer_re.match(line.c_str()))
503 505 {
504 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 509 QPDFObjectHandle t =
508   - readObject(&this->file, "trailer", 0, 0, false);
  510 + readObject(this->file, "trailer", 0, 0, false);
509 511 if (! t.isDictionary())
510 512 {
511 513 // Oh well. It was worth a try.
... ... @@ -526,7 +528,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
526 528 // with bad startxref pointers even when they have object
527 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 532 "unable to find trailer "
531 533 "dictionary while recovering damaged file");
532 534 }
... ... @@ -546,11 +548,11 @@ QPDF::read_xref(off_t xref_offset)
546 548 std::map<int, int> free_table;
547 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 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 557 else
556 558 {
... ... @@ -571,7 +573,7 @@ QPDF::read_xref(off_t xref_offset)
571 573 if (size != max_obj + 1)
572 574 {
573 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 577 std::string("reported number of objects (") +
576 578 QUtil::int_to_string(size) +
577 579 ") inconsistent with actual number of objects (" +
... ... @@ -591,17 +593,17 @@ QPDF::read_xrefTable(off_t xref_offset)
591 593  
592 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 597 bool done = false;
596 598 while (! done)
597 599 {
598   - std::string line = this->file.readLine();
  600 + std::string line = this->file->readLine();
599 601 PCRE::Match m1 = xref_first_re.match(line.c_str());
600 602 if (! m1)
601 603 {
602 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 607 "xref syntax invalid");
606 608 }
607 609 int obj = atoi(m1.getMatch(1).c_str());
... ... @@ -613,17 +615,17 @@ QPDF::read_xrefTable(off_t xref_offset)
613 615 if (i == 0)
614 616 {
615 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 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 622 PCRE::Match m2 = xref_entry_re.match(xref_entry);
621 623 if (! m2)
622 624 {
623 625 QTC::TC("qpdf", "QPDF invalid xref entry");
624 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 629 "invalid xref entry (obj=" +
628 630 QUtil::int_to_string(i) + ")");
629 631 }
... ... @@ -642,26 +644,26 @@ QPDF::read_xrefTable(off_t xref_offset)
642 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 649 if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))
648 650 {
649 651 done = true;
650 652 }
651 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 659 // Set offset to previous xref table if any
658 660 QPDFObjectHandle cur_trailer =
659   - readObject(&this->file, "trailer", 0, 0, false);
  661 + readObject(this->file, "trailer", 0, 0, false);
660 662 if (! cur_trailer.isDictionary())
661 663 {
662 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 667 "expected trailer dictionary");
666 668 }
667 669  
... ... @@ -672,15 +674,15 @@ QPDF::read_xrefTable(off_t xref_offset)
672 674 if (! this->trailer.hasKey("/Size"))
673 675 {
674 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 679 "trailer dictionary lacks /Size key");
678 680 }
679 681 if (! this->trailer.getKey("/Size").isInteger())
680 682 {
681 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 686 "/Size key in trailer dictionary is not "
685 687 "an integer");
686 688 }
... ... @@ -704,7 +706,7 @@ QPDF::read_xrefTable(off_t xref_offset)
704 706 }
705 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 710 "xref stream", xref_offset,
709 711 "invalid /XRefStm");
710 712 }
... ... @@ -724,8 +726,8 @@ QPDF::read_xrefTable(off_t xref_offset)
724 726 if (! cur_trailer.getKey("/Prev").isInteger())
725 727 {
726 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 731 "/Prev key in trailer dictionary is not "
730 732 "an integer");
731 733 }
... ... @@ -772,7 +774,7 @@ QPDF::read_xrefStream(off_t xref_offset)
772 774 if (! found)
773 775 {
774 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 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 795 dict.getKey("/Size").isInteger() &&
794 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 799 "xref stream", xref_offset,
798 800 "Cross-reference stream does not have"
799 801 " proper /W and /Index keys");
... ... @@ -804,7 +806,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
804 806 int n_index = Index_obj.getArrayNItems();
805 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 810 "xref stream", xref_offset,
809 811 "Cross-reference stream's /Index has an"
810 812 " invalid number of values");
... ... @@ -817,7 +819,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
817 819 }
818 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 823 "xref stream", xref_offset,
822 824 "Cross-reference stream's /Index's item " +
823 825 QUtil::int_to_string(i) +
... ... @@ -856,7 +858,7 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
856 858  
857 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 862 "xref stream", xref_offset,
861 863 "Cross-reference stream data has the wrong size;"
862 864 " expected = " + QUtil::int_to_string(expected_size) +
... ... @@ -938,8 +940,8 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
938 940 {
939 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 945 "/Prev key in xref stream dictionary is not "
944 946 "an integer");
945 947 }
... ... @@ -1008,8 +1010,8 @@ QPDF::insertXrefEntry(int obj, int f0, int f1, int f2, bool overwrite)
1008 1010 break;
1009 1011  
1010 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 1015 "unknown xref stream entry type " +
1014 1016 QUtil::int_to_string(f0));
1015 1017 break;
... ... @@ -1068,7 +1070,8 @@ QPDF::setLastObjectDescription(std::string const&amp; description,
1068 1070 }
1069 1071  
1070 1072 QPDFObjectHandle
1071   -QPDF::readObject(InputSource* input, std::string const& description,
  1073 +QPDF::readObject(PointerHolder<InputSource> input,
  1074 + std::string const& description,
1072 1075 int objid, int generation, bool in_object_stream)
1073 1076 {
1074 1077 setLastObjectDescription(description, objid, generation);
... ... @@ -1082,7 +1085,7 @@ QPDF::readObject(InputSource* input, std::string const&amp; description,
1082 1085 }
1083 1086  
1084 1087 QPDFObjectHandle
1085   -QPDF::readObjectInternal(InputSource* input,
  1088 +QPDF::readObjectInternal(PointerHolder<InputSource> input,
1086 1089 int objid, int generation,
1087 1090 bool in_object_stream,
1088 1091 bool in_array, bool in_dictionary)
... ... @@ -1197,20 +1200,6 @@ QPDF::readObjectInternal(InputSource* input,
1197 1200 olist.pop_back();
1198 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 1203 else
1215 1204 {
1216 1205 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
... ... @@ -1386,7 +1375,7 @@ QPDF::readObjectInternal(InputSource* input,
1386 1375 }
1387 1376  
1388 1377 int
1389   -QPDF::recoverStreamLength(InputSource* input,
  1378 +QPDF::recoverStreamLength(PointerHolder<InputSource> input,
1390 1379 int objid, int generation, off_t stream_offset)
1391 1380 {
1392 1381 static PCRE endobj_re("^\\s*endobj\\b");
... ... @@ -1473,7 +1462,7 @@ QPDF::recoverStreamLength(InputSource* input,
1473 1462 }
1474 1463  
1475 1464 QPDFTokenizer::Token
1476   -QPDF::readToken(InputSource* input)
  1465 +QPDF::readToken(PointerHolder<InputSource> input)
1477 1466 {
1478 1467 off_t offset = input->tell();
1479 1468 QPDFTokenizer::Token token;
... ... @@ -1523,11 +1512,11 @@ QPDF::readObjectAtOffset(bool try_recovery,
1523 1512 int& objid, int& generation)
1524 1513 {
1525 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 1521 bool objidok = (tobjid.getType() == QPDFTokenizer::tt_integer);
1533 1522 int genok = (tgen.getType() == QPDFTokenizer::tt_integer);
... ... @@ -1542,7 +1531,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1542 1531 if (! (objidok && genok && objok))
1543 1532 {
1544 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 1535 this->last_object_description, offset,
1547 1536 "expected n n obj");
1548 1537 }
... ... @@ -1553,7 +1542,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1553 1542 (! ((objid == exp_objid) && (generation == exp_generation))))
1554 1543 {
1555 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 1546 this->last_object_description, offset,
1558 1547 std::string("expected ") +
1559 1548 QUtil::int_to_string(exp_objid) + " " +
... ... @@ -1581,7 +1570,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1581 1570 {
1582 1571 QTC::TC("qpdf", "QPDF object gone after xref reconstruction");
1583 1572 warn(QPDFExc(
1584   - qpdf_e_damaged_pdf, this->file.getName(),
  1573 + qpdf_e_damaged_pdf, this->file->getName(),
1585 1574 "", 0,
1586 1575 std::string(
1587 1576 "object " +
... ... @@ -1600,14 +1589,14 @@ QPDF::readObjectAtOffset(bool try_recovery,
1600 1589 }
1601 1590  
1602 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 1595 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj")))
1607 1596 {
1608 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 1600 "expected endobj"));
1612 1601 }
1613 1602  
... ... @@ -1624,28 +1613,28 @@ QPDF::readObjectAtOffset(bool try_recovery,
1624 1613 // linearization hint tables. Offsets and lengths of objects
1625 1614 // may imply the end of an object to be anywhere between these
1626 1615 // values.
1627   - off_t end_before_space = this->file.tell();
  1616 + off_t end_before_space = this->file->tell();
1628 1617  
1629 1618 // skip over spaces
1630 1619 while (true)
1631 1620 {
1632 1621 char ch;
1633   - if (this->file.read(&ch, 1))
  1622 + if (this->file->read(&ch, 1))
1634 1623 {
1635 1624 if (! isspace((unsigned char)ch))
1636 1625 {
1637   - this->file.seek(-1, SEEK_CUR);
  1626 + this->file->seek(-1, SEEK_CUR);
1638 1627 break;
1639 1628 }
1640 1629 }
1641 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 1633 this->last_object_description, offset,
1645 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 1639 this->obj_cache[og] =
1651 1640 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh),
... ... @@ -1690,7 +1679,7 @@ QPDF::resolve(int objid, int generation)
1690 1679 break;
1691 1680  
1692 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 1683 "object " +
1695 1684 QUtil::int_to_string(objid) + "/" +
1696 1685 QUtil::int_to_string(generation) +
... ... @@ -1708,9 +1697,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1708 1697 QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0);
1709 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 1701 this->last_object_description,
1713   - this->file.getLastOffset(),
  1702 + this->file->getLastOffset(),
1714 1703 "supposed object stream " +
1715 1704 QUtil::int_to_string(obj_stream_number) +
1716 1705 " is not a stream");
... ... @@ -1727,9 +1716,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1727 1716 dict.getKey("/Type").getName() == "/ObjStm"))
1728 1717 {
1729 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 1720 this->last_object_description,
1732   - this->file.getLastOffset(),
  1721 + this->file->getLastOffset(),
1733 1722 "supposed object stream " +
1734 1723 QUtil::int_to_string(obj_stream_number) +
1735 1724 " has wrong type");
... ... @@ -1738,9 +1727,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1738 1727 if (! (dict.getKey("/N").isInteger() &&
1739 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 1731 this->last_object_description,
1743   - this->file.getLastOffset(),
  1732 + this->file->getLastOffset(),
1744 1733 "object stream " +
1745 1734 QUtil::int_to_string(obj_stream_number) +
1746 1735 " has incorrect keys");
... ... @@ -1752,19 +1741,19 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1752 1741 std::map<int, int> offsets;
1753 1742  
1754 1743 PointerHolder<Buffer> bp = obj_stream.getStreamData();
1755   - BufferInputSource input(
  1744 + PointerHolder<InputSource> input = new BufferInputSource(
1756 1745 "object stream " + QUtil::int_to_string(obj_stream_number),
1757 1746 bp.getPointer());
1758 1747  
1759 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 1752 if (! ((tnum.getType() == QPDFTokenizer::tt_integer) &&
1764 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 1757 "expected integer in object stream header");
1769 1758 }
1770 1759  
... ... @@ -1778,8 +1767,8 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1778 1767 {
1779 1768 int obj = (*iter).first;
1780 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 1773 // Store in cache
1785 1774 ObjGen og(obj, 0);
... ... @@ -1839,7 +1828,7 @@ QPDF::trimTrailerForWrite()
1839 1828 std::string
1840 1829 QPDF::getFilename() const
1841 1830 {
1842   - return this->file.getName();
  1831 + return this->file->getName();
1843 1832 }
1844 1833  
1845 1834 std::string
... ... @@ -1988,18 +1977,18 @@ QPDF::pipeStreamData(int objid, int generation,
1988 1977  
1989 1978 try
1990 1979 {
1991   - this->file.seek(offset, SEEK_SET);
  1980 + this->file->seek(offset, SEEK_SET);
1992 1981 char buf[10240];
1993 1982 while (length > 0)
1994 1983 {
1995 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 1986 if (len == 0)
1998 1987 {
1999 1988 throw QPDFExc(qpdf_e_damaged_pdf,
2000   - this->file.getName(),
  1989 + this->file->getName(),
2001 1990 this->last_object_description,
2002   - this->file.getLastOffset(),
  1991 + this->file->getLastOffset(),
2003 1992 "unexpected EOF reading stream data");
2004 1993 }
2005 1994 length -= len;
... ... @@ -2013,8 +2002,8 @@ QPDF::pipeStreamData(int objid, int generation,
2013 2002 catch (std::runtime_error& e)
2014 2003 {
2015 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 2007 "error decoding stream data for object " +
2019 2008 QUtil::int_to_string(objid) + " " +
2020 2009 QUtil::int_to_string(generation) + ": " + e.what()));
... ... @@ -2070,9 +2059,9 @@ QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages,
2070 2059 }
2071 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 2063 this->last_object_description,
2075   - this->file.getLastOffset(),
  2064 + this->file->getLastOffset(),
2076 2065 ": invalid Type in page tree");
2077 2066 }
2078 2067 }
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -336,8 +336,8 @@ QPDF::initializeEncryption()
336 336 (id_obj.getArrayNItems() == 2) &&
337 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 341 "invalid /ID in trailer dictionary");
342 342 }
343 343  
... ... @@ -345,23 +345,23 @@ QPDF::initializeEncryption()
345 345 QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt");
346 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 349 this->last_object_description,
350   - this->file.getLastOffset(),
  350 + this->file->getLastOffset(),
351 351 "/Encrypt in trailer dictionary is not a dictionary");
352 352 }
353 353  
354 354 if (! (encryption_dict.getKey("/Filter").isName() &&
355 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 359 "unsupported encryption filter");
360 360 }
361 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 365 "file uses encryption SubFilters,"
366 366 " which qpdf does not support"));
367 367 }
... ... @@ -372,8 +372,8 @@ QPDF::initializeEncryption()
372 372 encryption_dict.getKey("/U").isString() &&
373 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 377 "some encryption dictionary parameters are missing "
378 378 "or the wrong type");
379 379 }
... ... @@ -387,8 +387,8 @@ QPDF::initializeEncryption()
387 387 if (! (((R == 2) || (R == 3) || (R == 4)) &&
388 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 392 "Unsupported /R or /V in encryption dictionary");
393 393 }
394 394  
... ... @@ -396,8 +396,8 @@ QPDF::initializeEncryption()
396 396  
397 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 401 "incorrect length for /O and/or /P in "
402 402 "encryption dictionary");
403 403 }
... ... @@ -408,8 +408,8 @@ QPDF::initializeEncryption()
408 408 Length = encryption_dict.getKey("/Length").getIntValue();
409 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 413 "invalid /Length value in encryption dictionary");
414 414 }
415 415 }
... ... @@ -472,8 +472,8 @@ QPDF::initializeEncryption()
472 472 }
473 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 477 "This document has embedded files that are"
478 478 " encrypted differently from the rest of the file."
479 479 " qpdf does not presently support this due to"
... ... @@ -494,7 +494,7 @@ QPDF::initializeEncryption()
494 494 }
495 495 else
496 496 {
497   - throw QPDFExc(qpdf_e_password, this->file.getName(),
  497 + throw QPDFExc(qpdf_e_password, this->file->getName(),
498 498 "", 0, "invalid password");
499 499 }
500 500  
... ... @@ -545,9 +545,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
545 545 break;
546 546  
547 547 default:
548   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
  548 + warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
549 549 this->last_object_description,
550   - this->file.getLastOffset(),
  550 + this->file->getLastOffset(),
551 551 "unknown encryption filter for strings"
552 552 " (check /StrF in /Encrypt dictionary);"
553 553 " strings may be decrypted improperly"));
... ... @@ -595,8 +595,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
595 595 }
596 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 601 "error decrypting string for object " +
601 602 QUtil::int_to_string(objid) + " " +
602 603 QUtil::int_to_string(generation) + ": " + e.what());
... ... @@ -669,9 +670,9 @@ QPDF::decryptStream(Pipeline*&amp; pipeline, int objid, int generation,
669 670  
670 671 default:
671 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 674 this->last_object_description,
674   - this->file.getLastOffset(),
  675 + this->file->getLastOffset(),
675 676 "unknown encryption filter for streams"
676 677 " (check " + method_source + ");"
677 678 " streams may be decrypted improperly"));
... ...
libqpdf/QPDF_linearization.cc
... ... @@ -87,10 +87,10 @@ QPDF::isLinearized()
87 87 static int const tbuf_size = 1025;
88 88  
89 89 char* buf = new char[tbuf_size];
90   - this->file.seek(0, SEEK_SET);
  90 + this->file->seek(0, SEEK_SET);
91 91 PointerHolder<char> b(buf); // guarantee deletion
92 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 95 static PCRE lindict_re("(?s:(\\d+)\\s+0\\s+obj\\s*<<)");
96 96  
... ... @@ -147,8 +147,8 @@ QPDF::isLinearized()
147 147 if (L.isInteger())
148 148 {
149 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 153 QTC::TC("qpdf", "QPDF /L mismatch");
154 154 return false;
... ... @@ -194,9 +194,9 @@ QPDF::readLinearizationData()
194 194 T.isInteger() &&
195 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 198 "linearization dictionary",
199   - this->file.getLastOffset(),
  199 + this->file->getLastOffset(),
200 200 "some keys in linearization dictionary are of "
201 201 "the wrong type");
202 202 }
... ... @@ -205,9 +205,9 @@ QPDF::readLinearizationData()
205 205 unsigned int n_H_items = H.getArrayNItems();
206 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 209 "linearization dictionary",
210   - this->file.getLastOffset(),
  210 + this->file->getLastOffset(),
211 211 "H has the wrong number of items");
212 212 }
213 213  
... ... @@ -221,9 +221,9 @@ QPDF::readLinearizationData()
221 221 }
222 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 225 "linearization dictionary",
226   - this->file.getLastOffset(),
  226 + this->file->getLastOffset(),
227 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 318 off_t max_end_offset = oc.end_after_space;
319 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 322 "linearization dictionary",
323   - this->file.getLastOffset(),
  323 + this->file->getLastOffset(),
324 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 354 std::cout << "expected = " << computed_end
355 355 << "; actual = " << min_end_offset << ".."
356 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 358 "linearization dictionary",
359   - this->file.getLastOffset(),
  359 + this->file->getLastOffset(),
360 360 "hint table length mismatch");
361 361 }
362 362 H.pipeStreamData(&pl, true, false, false);
... ... @@ -509,24 +509,25 @@ QPDF::checkLinearizationInternal()
509 509 }
510 510  
511 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 513 while (1)
514 514 {
515 515 char ch;
516   - this->file.read(&ch, 1);
  516 + this->file->read(&ch, 1);
517 517 if (! ((ch == ' ') || (ch == '\r') || (ch == '\n')))
518 518 {
519   - this->file.seek(-1, SEEK_CUR);
  519 + this->file->seek(-1, SEEK_CUR);
520 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 525 QTC::TC("qpdf", "QPDF err /T mismatch");
526 526 errors.push_back("space before first xref item (/T) mismatch "
527 527 "(computed = " +
528 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 533 // P: first page number -- Implementation note 124 says Acrobat
... ... @@ -1014,7 +1015,7 @@ QPDF::showLinearizationData()
1014 1015 void
1015 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 1019 << std::endl;
1019 1020  
1020 1021 std::cout
... ...
libqpdf/QPDF_optimization.cc
... ... @@ -246,9 +246,9 @@ QPDF::optimizePagesTree(
246 246 {
247 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 250 this->last_object_description,
251   - this->file.getLastOffset(),
  251 + this->file->getLastOffset(),
252 252 "optimize detected an "
253 253 "inheritable resource when called "
254 254 "in no-change mode");
... ... @@ -354,9 +354,9 @@ QPDF::optimizePagesTree(
354 354 }
355 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 358 this->last_object_description,
359   - this->file.getLastOffset(),
  359 + this->file->getLastOffset(),
360 360 "invalid Type in page tree");
361 361 }
362 362 }
... ...