Commit 5c866633537c603b96a4a070a1498dd1a4976e51

Authored by m-holger
1 parent 807dbf42

Move QPDF inner class definitions to new QPDF_private.hh

include/qpdf/QPDF.hh
... ... @@ -726,167 +726,14 @@ class QPDF
726 726 void removePage(QPDFObjectHandle page);
727 727 // End legacy page helpers
728 728  
729   - // Writer class is restricted to QPDFWriter so that only it can call certain methods.
730   - class Writer
731   - {
732   - friend class QPDFWriter;
733   -
734   - private:
735   - static void
736   - optimize(
737   - QPDF& qpdf,
738   - QPDFWriter::ObjTable const& obj,
739   - std::function<int(QPDFObjectHandle&)> skip_stream_parameters)
740   - {
741   - return qpdf.optimize(obj, skip_stream_parameters);
742   - }
743   -
744   - static void
745   - getLinearizedParts(
746   - QPDF& qpdf,
747   - QPDFWriter::ObjTable const& obj,
748   - std::vector<QPDFObjectHandle>& part4,
749   - std::vector<QPDFObjectHandle>& part6,
750   - std::vector<QPDFObjectHandle>& part7,
751   - std::vector<QPDFObjectHandle>& part8,
752   - std::vector<QPDFObjectHandle>& part9)
753   - {
754   - qpdf.getLinearizedParts(obj, part4, part6, part7, part8, part9);
755   - }
756   -
757   - static void
758   - generateHintStream(
759   - QPDF& qpdf,
760   - QPDFWriter::NewObjTable const& new_obj,
761   - QPDFWriter::ObjTable const& obj,
762   - std::shared_ptr<Buffer>& hint_stream,
763   - int& S,
764   - int& O,
765   - bool compressed)
766   - {
767   - return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed);
768   - }
769   -
770   - static std::vector<QPDFObjGen>
771   - getCompressibleObjGens(QPDF& qpdf)
772   - {
773   - return qpdf.getCompressibleObjVector();
774   - }
775   -
776   - static std::vector<bool>
777   - getCompressibleObjSet(QPDF& qpdf)
778   - {
779   - return qpdf.getCompressibleObjSet();
780   - }
781   -
782   - static std::map<QPDFObjGen, QPDFXRefEntry> const&
783   - getXRefTable(QPDF& qpdf)
784   - {
785   - return qpdf.getXRefTableInternal();
786   - }
  729 + // End of the public API. The following classes and methods are for qpdf internal use only.
787 730  
788   - static size_t
789   - tableSize(QPDF& qpdf)
790   - {
791   - return qpdf.tableSize();
792   - }
793   - };
794   -
795   - // The Resolver class is restricted to QPDFObject so that only it can resolve indirect
796   - // references.
797   - class Resolver
798   - {
799   - friend class QPDFObject;
800   - friend class QPDF_Unresolved;
801   - friend class qpdf::BaseHandle;
802   -
803   - private:
804   - static std::shared_ptr<QPDFObject> const&
805   - resolved(QPDF* qpdf, QPDFObjGen og)
806   - {
807   - return qpdf->resolve(og);
808   - }
809   - };
810   -
811   - // StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data.
812   - class StreamCopier
813   - {
814   - friend class QPDFObjectHandle;
815   -
816   - private:
817   - static void
818   - copyStreamData(QPDF* qpdf, QPDFObjectHandle const& dest, QPDFObjectHandle const& src)
819   - {
820   - qpdf->copyStreamData(dest, src);
821   - }
822   - };
823   -
824   - // The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides
825   - // special access to allow the parser to create unresolved objects and dangling references.
826   - class ParseGuard
827   - {
828   - friend class QPDFParser;
829   -
830   - private:
831   - ParseGuard(QPDF* qpdf) :
832   - qpdf(qpdf)
833   - {
834   - if (qpdf) {
835   - qpdf->inParse(true);
836   - }
837   - }
838   -
839   - static std::shared_ptr<QPDFObject>
840   - getObject(QPDF* qpdf, int id, int gen, bool parse_pdf)
841   - {
842   - return qpdf->getObjectForParser(id, gen, parse_pdf);
843   - }
844   -
845   - ~ParseGuard()
846   - {
847   - if (qpdf) {
848   - qpdf->inParse(false);
849   - }
850   - }
851   - QPDF* qpdf;
852   - };
853   -
854   - // Pipe class is restricted to QPDF_Stream.
855   - class Pipe
856   - {
857   - friend class QPDF_Stream;
858   - friend class qpdf::Stream;
859   -
860   - private:
861   - static bool
862   - pipeStreamData(
863   - QPDF* qpdf,
864   - QPDFObjGen og,
865   - qpdf_offset_t offset,
866   - size_t length,
867   - QPDFObjectHandle dict,
868   - Pipeline* pipeline,
869   - bool suppress_warnings,
870   - bool will_retry)
871   - {
872   - return qpdf->pipeStreamData(
873   - og, offset, length, dict, pipeline, suppress_warnings, will_retry);
874   - }
875   - };
876   -
877   - // JobSetter class is restricted to QPDFJob.
878   - class JobSetter
879   - {
880   - friend class QPDFJob;
881   -
882   - private:
883   - // Enable enhanced warnings for pdf file checking.
884   - static void
885   - setCheckMode(QPDF& qpdf, bool val)
886   - {
887   - qpdf.m->check_mode = val;
888   - }
889   - };
  731 + class Writer;
  732 + class Resolver;
  733 + class StreamCopier;
  734 + class ParseGuard;
  735 + class Pipe;
  736 + class JobSetter;
890 737  
891 738 // For testing only -- do not add to DLL
892 739 static bool test_json_validators();
... ... @@ -901,136 +748,13 @@ class QPDF
901 748  
902 749 static std::string const qpdf_version;
903 750  
904   - class ObjCache
905   - {
906   - public:
907   - ObjCache() :
908   - end_before_space(0),
909   - end_after_space(0)
910   - {
911   - }
912   - ObjCache(
913   - std::shared_ptr<QPDFObject> object,
914   - qpdf_offset_t end_before_space = 0,
915   - qpdf_offset_t end_after_space = 0) :
916   - object(object),
917   - end_before_space(end_before_space),
918   - end_after_space(end_after_space)
919   - {
920   - }
921   -
922   - std::shared_ptr<QPDFObject> object;
923   - qpdf_offset_t end_before_space;
924   - qpdf_offset_t end_after_space;
925   - };
926   -
927   - class ObjCopier
928   - {
929   - public:
930   - std::map<QPDFObjGen, QPDFObjectHandle> object_map;
931   - std::vector<QPDFObjectHandle> to_copy;
932   - QPDFObjGen::set visiting;
933   - };
934   -
935   - class EncryptionParameters
936   - {
937   - friend class QPDF;
938   -
939   - public:
940   - EncryptionParameters();
941   -
942   - private:
943   - bool encrypted;
944   - bool encryption_initialized;
945   - int encryption_V;
946   - int encryption_R;
947   - bool encrypt_metadata;
948   - std::map<std::string, encryption_method_e> crypt_filters;
949   - encryption_method_e cf_stream;
950   - encryption_method_e cf_string;
951   - encryption_method_e cf_file;
952   - std::string provided_password;
953   - std::string user_password;
954   - std::string encryption_key;
955   - std::string cached_object_encryption_key;
956   - QPDFObjGen cached_key_og;
957   - bool user_password_matched;
958   - bool owner_password_matched;
959   - };
960   -
961   - class ForeignStreamData
962   - {
963   - friend class QPDF;
964   -
965   - public:
966   - ForeignStreamData(
967   - std::shared_ptr<EncryptionParameters> encp,
968   - std::shared_ptr<InputSource> file,
969   - QPDFObjGen foreign_og,
970   - qpdf_offset_t offset,
971   - size_t length,
972   - QPDFObjectHandle local_dict);
973   -
974   - private:
975   - std::shared_ptr<EncryptionParameters> encp;
976   - std::shared_ptr<InputSource> file;
977   - QPDFObjGen foreign_og;
978   - qpdf_offset_t offset;
979   - size_t length;
980   - QPDFObjectHandle local_dict;
981   - };
982   -
983   - class CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider
984   - {
985   - public:
986   - CopiedStreamDataProvider(QPDF& destination_qpdf);
987   - ~CopiedStreamDataProvider() override = default;
988   - bool provideStreamData(
989   - QPDFObjGen const& og,
990   - Pipeline* pipeline,
991   - bool suppress_warnings,
992   - bool will_retry) override;
993   - void registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
994   - void registerForeignStream(QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData>);
995   -
996   - private:
997   - QPDF& destination_qpdf;
998   - std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
999   - std::map<QPDFObjGen, std::shared_ptr<ForeignStreamData>> foreign_stream_data;
1000   - };
1001   -
1002   - class StringDecrypter: public QPDFObjectHandle::StringDecrypter
1003   - {
1004   - friend class QPDF;
1005   -
1006   - public:
1007   - StringDecrypter(QPDF* qpdf, QPDFObjGen og);
1008   - ~StringDecrypter() override = default;
1009   - void decryptString(std::string& val) override;
1010   -
1011   - private:
1012   - QPDF* qpdf;
1013   - QPDFObjGen og;
1014   - };
1015   -
1016   - class ResolveRecorder
1017   - {
1018   - public:
1019   - ResolveRecorder(QPDF* qpdf, QPDFObjGen og) :
1020   - qpdf(qpdf),
1021   - iter(qpdf->m->resolving.insert(og).first)
1022   - {
1023   - }
1024   - virtual ~ResolveRecorder()
1025   - {
1026   - this->qpdf->m->resolving.erase(iter);
1027   - }
1028   -
1029   - private:
1030   - QPDF* qpdf;
1031   - std::set<QPDFObjGen>::const_iterator iter;
1032   - };
1033   -
  751 + class ObjCache;
  752 + class ObjCopier;
  753 + class EncryptionParameters;
  754 + class ForeignStreamData;
  755 + class CopiedStreamDataProvider;
  756 + class StringDecrypter;
  757 + class ResolveRecorder;
1034 758 class JSONReactor;
1035 759  
1036 760 void parse(char const* password);
... ... @@ -1200,200 +924,19 @@ class QPDF
1200 924 replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
1201 925 void copyStreamData(QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
1202 926  
1203   - // Linearization Hint table structures.
1204   - // Naming conventions:
1205   -
1206   - // HSomething is the Something Hint Table or table header
1207   - // HSomethingEntry is an entry in the Something table
1208   -
1209   - // delta_something + min_something = something
1210   - // nbits_something = number of bits required for something
1211   -
1212   - // something_offset is the pre-adjusted offset in the file. If >=
1213   - // H0_offset, H0_length must be added to get an actual file
1214   - // offset.
1215   -
1216   - // PDF 1.4: Table F.4
1217   - struct HPageOffsetEntry
1218   - {
1219   - int delta_nobjects{0}; // 1
1220   - qpdf_offset_t delta_page_length{0}; // 2
1221   - // vectors' sizes = nshared_objects
1222   - int nshared_objects{0}; // 3
1223   - std::vector<int> shared_identifiers; // 4
1224   - std::vector<int> shared_numerators; // 5
1225   - qpdf_offset_t delta_content_offset{0}; // 6
1226   - qpdf_offset_t delta_content_length{0}; // 7
1227   - };
1228   -
1229   - // PDF 1.4: Table F.3
1230   - struct HPageOffset
1231   - {
1232   - int min_nobjects{0}; // 1
1233   - qpdf_offset_t first_page_offset{0}; // 2
1234   - int nbits_delta_nobjects{0}; // 3
1235   - int min_page_length{0}; // 4
1236   - int nbits_delta_page_length{0}; // 5
1237   - int min_content_offset{0}; // 6
1238   - int nbits_delta_content_offset{0}; // 7
1239   - int min_content_length{0}; // 8
1240   - int nbits_delta_content_length{0}; // 9
1241   - int nbits_nshared_objects{0}; // 10
1242   - int nbits_shared_identifier{0}; // 11
1243   - int nbits_shared_numerator{0}; // 12
1244   - int shared_denominator{0}; // 13
1245   - // vector size is npages
1246   - std::vector<HPageOffsetEntry> entries;
1247   - };
1248   -
1249   - // PDF 1.4: Table F.6
1250   - struct HSharedObjectEntry
1251   - {
1252   - // Item 3 is a 128-bit signature (unsupported by Acrobat)
1253   - int delta_group_length{0}; // 1
1254   - int signature_present{0}; // 2 -- always 0
1255   - int nobjects_minus_one{0}; // 4 -- always 0
1256   - };
1257   -
1258   - // PDF 1.4: Table F.5
1259   - struct HSharedObject
1260   - {
1261   - int first_shared_obj{0}; // 1
1262   - qpdf_offset_t first_shared_offset{0}; // 2
1263   - int nshared_first_page{0}; // 3
1264   - int nshared_total{0}; // 4
1265   - int nbits_nobjects{0}; // 5
1266   - int min_group_length{0}; // 6
1267   - int nbits_delta_group_length{0}; // 7
1268   - // vector size is nshared_total
1269   - std::vector<HSharedObjectEntry> entries;
1270   - };
1271   -
1272   - // PDF 1.4: Table F.9
1273   - struct HGeneric
1274   - {
1275   - int first_object{0}; // 1
1276   - qpdf_offset_t first_object_offset{0}; // 2
1277   - int nobjects{0}; // 3
1278   - int group_length{0}; // 4
1279   - };
1280   -
1281   - // Other linearization data structures
1282   -
1283   - // Initialized from Linearization Parameter dictionary
1284   - struct LinParameters
1285   - {
1286   - qpdf_offset_t file_size{0}; // /L
1287   - int first_page_object{0}; // /O
1288   - qpdf_offset_t first_page_end{0}; // /E
1289   - int npages{0}; // /N
1290   - qpdf_offset_t xref_zero_offset{0}; // /T
1291   - int first_page{0}; // /P
1292   - qpdf_offset_t H_offset{0}; // offset of primary hint stream
1293   - qpdf_offset_t H_length{0}; // length of primary hint stream
1294   - };
1295   -
1296   - // Computed hint table value data structures. These tables contain the computed values on which
1297   - // the hint table values are based. They exclude things like number of bits and store actual
1298   - // values instead of mins and deltas. File offsets are also absolute rather than being offset
1299   - // by the size of the primary hint table. We populate the hint table structures from these
1300   - // during writing and compare the hint table values with these during validation. We ignore
1301   - // some values for various reasons described in the code. Those values are omitted from these
1302   - // structures. Note also that object numbers are object numbers from the input file, not the
1303   - // output file.
1304   -
1305   - // Naming convention: CHSomething is analogous to HSomething above. "CH" is computed hint.
1306   -
1307   - struct CHPageOffsetEntry
1308   - {
1309   - int nobjects{0};
1310   - int nshared_objects{0};
1311   - // vectors' sizes = nshared_objects
1312   - std::vector<int> shared_identifiers;
1313   - };
1314   -
1315   - struct CHPageOffset
1316   - {
1317   - // vector size is npages
1318   - std::vector<CHPageOffsetEntry> entries;
1319   - };
1320   -
1321   - struct CHSharedObjectEntry
1322   - {
1323   - CHSharedObjectEntry(int object) :
1324   - object(object)
1325   - {
1326   - }
1327   -
1328   - int object;
1329   - };
1330   -
1331   - // PDF 1.4: Table F.5
1332   - struct CHSharedObject
1333   - {
1334   - int first_shared_obj{0};
1335   - int nshared_first_page{0};
1336   - int nshared_total{0};
1337   - // vector size is nshared_total
1338   - std::vector<CHSharedObjectEntry> entries;
1339   - };
1340   -
1341   - // No need for CHGeneric -- HGeneric is fine as is.
1342   -
1343   - // Data structures to support optimization -- implemented in QPDF_optimization.cc
1344   -
1345   - class ObjUser
1346   - {
1347   - public:
1348   - enum user_e { ou_bad, ou_page, ou_thumb, ou_trailer_key, ou_root_key, ou_root };
1349   -
1350   - // type is set to ou_bad
1351   - ObjUser();
1352   -
1353   - // type must be ou_root
1354   - ObjUser(user_e type);
1355   -
1356   - // type must be one of ou_page or ou_thumb
1357   - ObjUser(user_e type, int pageno);
1358   -
1359   - // type must be one of ou_trailer_key or ou_root_key
1360   - ObjUser(user_e type, std::string const& key);
1361   -
1362   - bool operator<(ObjUser const&) const;
1363   -
1364   - user_e ou_type;
1365   - int pageno; // if ou_page;
1366   - std::string key; // if ou_trailer_key or ou_root_key
1367   - };
1368   -
1369   - struct UpdateObjectMapsFrame
1370   - {
1371   - UpdateObjectMapsFrame(ObjUser const& ou, QPDFObjectHandle oh, bool top);
1372   -
1373   - ObjUser const& ou;
1374   - QPDFObjectHandle oh;
1375   - bool top;
1376   - };
1377   -
1378   - class PatternFinder: public InputSource::Finder
1379   - {
1380   - public:
1381   - PatternFinder(QPDF& qpdf, bool (QPDF::*checker)()) :
1382   - qpdf(qpdf),
1383   - checker(checker)
1384   - {
1385   - }
1386   - ~PatternFinder() override = default;
1387   - bool
1388   - check() override
1389   - {
1390   - return (this->qpdf.*checker)();
1391   - }
1392   -
1393   - private:
1394   - QPDF& qpdf;
1395   - bool (QPDF::*checker)();
1396   - };
  927 + struct HPageOffsetEntry;
  928 + struct HPageOffset;
  929 + struct HSharedObjectEntry;
  930 + struct HSharedObject;
  931 + struct HGeneric;
  932 + struct LinParameters;
  933 + struct CHPageOffsetEntry;
  934 + struct CHPageOffset;
  935 + struct CHSharedObjectEntry;
  936 + struct CHSharedObject;
  937 + class ObjUser;
  938 + struct UpdateObjectMapsFrame;
  939 + class PatternFinder;
1397 940  
1398 941 // Methods to support pattern finding
1399 942 static bool validatePDFVersion(char const*&, std::string& version);
... ... @@ -1490,88 +1033,7 @@ class QPDF
1490 1033 return QIntC::to_ulonglong(i);
1491 1034 }
1492 1035  
1493   - class Members
1494   - {
1495   - friend class QPDF;
1496   - friend class ResolveRecorder;
1497   -
1498   - public:
1499   - Members();
1500   - Members(Members const&) = delete;
1501   - ~Members() = default;
1502   -
1503   - private:
1504   - std::shared_ptr<QPDFLogger> log;
1505   - unsigned long long unique_id{0};
1506   - QPDFTokenizer tokenizer;
1507   - std::shared_ptr<InputSource> file;
1508   - std::string last_object_description;
1509   - bool provided_password_is_hex_key{false};
1510   - bool ignore_xref_streams{false};
1511   - bool suppress_warnings{false};
1512   - size_t max_warnings{0};
1513   - bool attempt_recovery{true};
1514   - bool check_mode{false};
1515   - std::shared_ptr<EncryptionParameters> encp;
1516   - std::string pdf_version;
1517   - std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
1518   - // Various tables are indexed by object id, with potential size id + 1
1519   - int xref_table_max_id{std::numeric_limits<int>::max() - 1};
1520   - qpdf_offset_t xref_table_max_offset{0};
1521   - std::set<int> deleted_objects;
1522   - std::map<QPDFObjGen, ObjCache> obj_cache;
1523   - std::set<QPDFObjGen> resolving;
1524   - QPDFObjectHandle trailer;
1525   - std::vector<QPDFObjectHandle> all_pages;
1526   - bool invalid_page_found{false};
1527   - std::map<QPDFObjGen, int> pageobj_to_pages_pos;
1528   - bool pushed_inherited_attributes_to_pages{false};
1529   - bool ever_pushed_inherited_attributes_to_pages{false};
1530   - bool ever_called_get_all_pages{false};
1531   - std::vector<QPDFExc> warnings;
1532   - std::map<unsigned long long, ObjCopier> object_copiers;
1533   - std::shared_ptr<QPDFObjectHandle::StreamDataProvider> copied_streams;
1534   - // copied_stream_data_provider is owned by copied_streams
1535   - CopiedStreamDataProvider* copied_stream_data_provider{nullptr};
1536   - bool reconstructed_xref{false};
1537   - bool fixed_dangling_refs{false};
1538   - bool immediate_copy_from{false};
1539   - bool in_parse{false};
1540   - bool parsed{false};
1541   - std::set<int> resolved_object_streams;
1542   -
1543   - // Linearization data
1544   - qpdf_offset_t first_xref_item_offset{0}; // actual value from file
1545   - bool uncompressed_after_compressed{false};
1546   - bool linearization_warnings{false};
1547   -
1548   - // Linearization parameter dictionary and hint table data: may be read from file or computed
1549   - // prior to writing a linearized file
1550   - QPDFObjectHandle lindict;
1551   - LinParameters linp;
1552   - HPageOffset page_offset_hints;
1553   - HSharedObject shared_object_hints;
1554   - HGeneric outline_hints;
1555   -
1556   - // Computed linearization data: used to populate above tables during writing and to compare
1557   - // with them during validation. c_ means computed.
1558   - LinParameters c_linp;
1559   - CHPageOffset c_page_offset_data;
1560   - CHSharedObject c_shared_object_data;
1561   - HGeneric c_outline_data;
1562   -
1563   - // Object ordering data for linearized files: initialized by calculateLinearizationData().
1564   - // Part numbers refer to the PDF 1.4 specification.
1565   - std::vector<QPDFObjectHandle> part4;
1566   - std::vector<QPDFObjectHandle> part6;
1567   - std::vector<QPDFObjectHandle> part7;
1568   - std::vector<QPDFObjectHandle> part8;
1569   - std::vector<QPDFObjectHandle> part9;
1570   -
1571   - // Optimization data
1572   - std::map<ObjUser, std::set<QPDFObjGen>> obj_user_to_objects;
1573   - std::map<QPDFObjGen, std::set<ObjUser>> object_to_obj_users;
1574   - };
  1036 + class Members;
1575 1037  
1576 1038 // Keep all member variables inside the Members object, which we dynamically allocate. This
1577 1039 // makes it possible to add new private members without breaking binary compatibility.
... ...
libqpdf/QPDF.cc
1 1 #include <qpdf/qpdf-config.h> // include first for large file support
2 2  
3   -#include <qpdf/QPDF.hh>
  3 +#include <qpdf/QPDF_private.hh>
4 4  
5 5 #include <array>
6 6 #include <atomic>
... ...
libqpdf/QPDFJob.cc
... ... @@ -13,7 +13,6 @@
13 13 #include <qpdf/Pl_StdioFile.hh>
14 14 #include <qpdf/Pl_String.hh>
15 15 #include <qpdf/QIntC.hh>
16   -#include <qpdf/QPDF.hh>
17 16 #include <qpdf/QPDFAcroFormDocumentHelper.hh>
18 17 #include <qpdf/QPDFCryptoProvider.hh>
19 18 #include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
... ... @@ -27,6 +26,7 @@
27 26 #include <qpdf/QPDFSystemError.hh>
28 27 #include <qpdf/QPDFUsage.hh>
29 28 #include <qpdf/QPDFWriter.hh>
  29 +#include <qpdf/QPDF_private.hh>
30 30 #include <qpdf/QTC.hh>
31 31 #include <qpdf/QUtil.hh>
32 32 #include <qpdf/Util.hh>
... ...
libqpdf/QPDFWriter.cc
... ... @@ -14,9 +14,9 @@
14 14 #include <qpdf/Pl_RC4.hh>
15 15 #include <qpdf/Pl_StdioFile.hh>
16 16 #include <qpdf/QIntC.hh>
17   -#include <qpdf/QPDF.hh>
18 17 #include <qpdf/QPDFObjectHandle_private.hh>
19 18 #include <qpdf/QPDFObject_private.hh>
  19 +#include <qpdf/QPDF_private.hh>
20 20 #include <qpdf/QTC.hh>
21 21 #include <qpdf/QUtil.hh>
22 22 #include <qpdf/RC4.hh>
... ...
libqpdf/QPDF_Stream.cc
... ... @@ -10,8 +10,8 @@
10 10 #include <qpdf/Pl_Flate.hh>
11 11 #include <qpdf/Pl_QPDFTokenizer.hh>
12 12 #include <qpdf/QIntC.hh>
13   -#include <qpdf/QPDF.hh>
14 13 #include <qpdf/QPDFExc.hh>
  14 +#include <qpdf/QPDF_private.hh>
15 15 #include <qpdf/QTC.hh>
16 16 #include <qpdf/QUtil.hh>
17 17 #include <qpdf/SF_ASCII85Decode.hh>
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -3,7 +3,7 @@
3 3  
4 4 #include <qpdf/assert_debug.h>
5 5  
6   -#include <qpdf/QPDF.hh>
  6 +#include <qpdf/QPDF_private.hh>
7 7  
8 8 #include <qpdf/QPDFExc.hh>
9 9  
... ...
libqpdf/QPDF_linearization.cc
1 1 // See doc/linearization.
2 2  
3   -#include <qpdf/QPDF.hh>
  3 +#include <qpdf/QPDF_private.hh>
4 4  
5 5 #include <qpdf/BitStream.hh>
6 6 #include <qpdf/BitWriter.hh>
... ...
libqpdf/QPDF_optimization.cc
... ... @@ -2,7 +2,7 @@
2 2  
3 3 #include <qpdf/assert_debug.h>
4 4  
5   -#include <qpdf/QPDF.hh>
  5 +#include <qpdf/QPDF_private.hh>
6 6  
7 7 #include <qpdf/QPDFExc.hh>
8 8 #include <qpdf/QPDFObjectHandle_private.hh>
... ...
libqpdf/QPDF_pages.cc
1   -#include <qpdf/QPDF.hh>
  1 +#include <qpdf/QPDF_private.hh>
2 2  
3 3 #include <qpdf/QPDFExc.hh>
4 4 #include <qpdf/QPDFObjectHandle_private.hh>
... ...
libqpdf/qpdf/QPDFObject_private.hh
... ... @@ -7,8 +7,8 @@
7 7 #include <qpdf/Constants.h>
8 8 #include <qpdf/JSON.hh>
9 9 #include <qpdf/JSON_writer.hh>
10   -#include <qpdf/QPDF.hh>
11 10 #include <qpdf/QPDFObjGen.hh>
  11 +#include <qpdf/QPDF_private.hh>
12 12 #include <qpdf/Types.h>
13 13  
14 14 #include <map>
... ...
libqpdf/qpdf/QPDF_private.hh 0 โ†’ 100644
  1 +#ifndef QPDF_PRIVATE_HH
  2 +#define QPDF_PRIVATE_HH
  3 +
  4 +#include <qpdf/QPDF.hh>
  5 +
  6 +// Writer class is restricted to QPDFWriter so that only it can call certain methods.
  7 +class QPDF::Writer
  8 +{
  9 + friend class QPDFWriter;
  10 +
  11 + private:
  12 + static void
  13 + optimize(
  14 + QPDF& qpdf,
  15 + QPDFWriter::ObjTable const& obj,
  16 + std::function<int(QPDFObjectHandle&)> skip_stream_parameters)
  17 + {
  18 + return qpdf.optimize(obj, skip_stream_parameters);
  19 + }
  20 +
  21 + static void
  22 + getLinearizedParts(
  23 + QPDF& qpdf,
  24 + QPDFWriter::ObjTable const& obj,
  25 + std::vector<QPDFObjectHandle>& part4,
  26 + std::vector<QPDFObjectHandle>& part6,
  27 + std::vector<QPDFObjectHandle>& part7,
  28 + std::vector<QPDFObjectHandle>& part8,
  29 + std::vector<QPDFObjectHandle>& part9)
  30 + {
  31 + qpdf.getLinearizedParts(obj, part4, part6, part7, part8, part9);
  32 + }
  33 +
  34 + static void
  35 + generateHintStream(
  36 + QPDF& qpdf,
  37 + QPDFWriter::NewObjTable const& new_obj,
  38 + QPDFWriter::ObjTable const& obj,
  39 + std::shared_ptr<Buffer>& hint_stream,
  40 + int& S,
  41 + int& O,
  42 + bool compressed)
  43 + {
  44 + return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed);
  45 + }
  46 +
  47 + static std::vector<QPDFObjGen>
  48 + getCompressibleObjGens(QPDF& qpdf)
  49 + {
  50 + return qpdf.getCompressibleObjVector();
  51 + }
  52 +
  53 + static std::vector<bool>
  54 + getCompressibleObjSet(QPDF& qpdf)
  55 + {
  56 + return qpdf.getCompressibleObjSet();
  57 + }
  58 +
  59 + static std::map<QPDFObjGen, QPDFXRefEntry> const&
  60 + getXRefTable(QPDF& qpdf)
  61 + {
  62 + return qpdf.getXRefTableInternal();
  63 + }
  64 +
  65 + static size_t
  66 + tableSize(QPDF& qpdf)
  67 + {
  68 + return qpdf.tableSize();
  69 + }
  70 +};
  71 +
  72 +// The Resolver class is restricted to QPDFObject so that only it can resolve indirect
  73 +// references.
  74 +class QPDF::Resolver
  75 +{
  76 + friend class QPDFObject;
  77 + friend class qpdf::BaseHandle;
  78 +
  79 + private:
  80 + static std::shared_ptr<QPDFObject> const&
  81 + resolved(QPDF* qpdf, QPDFObjGen og)
  82 + {
  83 + return qpdf->resolve(og);
  84 + }
  85 +};
  86 +
  87 +// StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data.
  88 +class QPDF::StreamCopier
  89 +{
  90 + friend class QPDFObjectHandle;
  91 +
  92 + private:
  93 + static void
  94 + copyStreamData(QPDF* qpdf, QPDFObjectHandle const& dest, QPDFObjectHandle const& src)
  95 + {
  96 + qpdf->copyStreamData(dest, src);
  97 + }
  98 +};
  99 +
  100 +// The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides
  101 +// special access to allow the parser to create unresolved objects and dangling references.
  102 +class QPDF::ParseGuard
  103 +{
  104 + friend class QPDFParser;
  105 +
  106 + private:
  107 + ParseGuard(QPDF* qpdf) :
  108 + qpdf(qpdf)
  109 + {
  110 + if (qpdf) {
  111 + qpdf->inParse(true);
  112 + }
  113 + }
  114 +
  115 + static std::shared_ptr<QPDFObject>
  116 + getObject(QPDF* qpdf, int id, int gen, bool parse_pdf)
  117 + {
  118 + return qpdf->getObjectForParser(id, gen, parse_pdf);
  119 + }
  120 +
  121 + ~ParseGuard()
  122 + {
  123 + if (qpdf) {
  124 + qpdf->inParse(false);
  125 + }
  126 + }
  127 + QPDF* qpdf;
  128 +};
  129 +
  130 +// Pipe class is restricted to QPDF_Stream.
  131 +class QPDF::Pipe
  132 +{
  133 + friend class qpdf::Stream;
  134 +
  135 + private:
  136 + static bool
  137 + pipeStreamData(
  138 + QPDF* qpdf,
  139 + QPDFObjGen og,
  140 + qpdf_offset_t offset,
  141 + size_t length,
  142 + QPDFObjectHandle dict,
  143 + Pipeline* pipeline,
  144 + bool suppress_warnings,
  145 + bool will_retry)
  146 + {
  147 + return qpdf->pipeStreamData(
  148 + og, offset, length, dict, pipeline, suppress_warnings, will_retry);
  149 + }
  150 +};
  151 +
  152 +class QPDF::ObjCache
  153 +{
  154 + public:
  155 + ObjCache() :
  156 + end_before_space(0),
  157 + end_after_space(0)
  158 + {
  159 + }
  160 + ObjCache(
  161 + std::shared_ptr<QPDFObject> object,
  162 + qpdf_offset_t end_before_space = 0,
  163 + qpdf_offset_t end_after_space = 0) :
  164 + object(object),
  165 + end_before_space(end_before_space),
  166 + end_after_space(end_after_space)
  167 + {
  168 + }
  169 +
  170 + std::shared_ptr<QPDFObject> object;
  171 + qpdf_offset_t end_before_space;
  172 + qpdf_offset_t end_after_space;
  173 +};
  174 +
  175 +class QPDF::ObjCopier
  176 +{
  177 + public:
  178 + std::map<QPDFObjGen, QPDFObjectHandle> object_map;
  179 + std::vector<QPDFObjectHandle> to_copy;
  180 + QPDFObjGen::set visiting;
  181 +};
  182 +
  183 +class QPDF::EncryptionParameters
  184 +{
  185 + friend class QPDF;
  186 +
  187 + public:
  188 + EncryptionParameters();
  189 +
  190 + private:
  191 + bool encrypted;
  192 + bool encryption_initialized;
  193 + int encryption_V;
  194 + int encryption_R;
  195 + bool encrypt_metadata;
  196 + std::map<std::string, encryption_method_e> crypt_filters;
  197 + encryption_method_e cf_stream;
  198 + encryption_method_e cf_string;
  199 + encryption_method_e cf_file;
  200 + std::string provided_password;
  201 + std::string user_password;
  202 + std::string encryption_key;
  203 + std::string cached_object_encryption_key;
  204 + QPDFObjGen cached_key_og;
  205 + bool user_password_matched;
  206 + bool owner_password_matched;
  207 +};
  208 +
  209 +class QPDF::ForeignStreamData
  210 +{
  211 + friend class QPDF;
  212 +
  213 + public:
  214 + ForeignStreamData(
  215 + std::shared_ptr<EncryptionParameters> encp,
  216 + std::shared_ptr<InputSource> file,
  217 + QPDFObjGen foreign_og,
  218 + qpdf_offset_t offset,
  219 + size_t length,
  220 + QPDFObjectHandle local_dict);
  221 +
  222 + private:
  223 + std::shared_ptr<EncryptionParameters> encp;
  224 + std::shared_ptr<InputSource> file;
  225 + QPDFObjGen foreign_og;
  226 + qpdf_offset_t offset;
  227 + size_t length;
  228 + QPDFObjectHandle local_dict;
  229 +};
  230 +
  231 +class QPDF::CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider
  232 +{
  233 + public:
  234 + CopiedStreamDataProvider(QPDF& destination_qpdf);
  235 + ~CopiedStreamDataProvider() override = default;
  236 + bool provideStreamData(
  237 + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) override;
  238 + void registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
  239 + void registerForeignStream(QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData>);
  240 +
  241 + private:
  242 + QPDF& destination_qpdf;
  243 + std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
  244 + std::map<QPDFObjGen, std::shared_ptr<ForeignStreamData>> foreign_stream_data;
  245 +};
  246 +
  247 +class QPDF::StringDecrypter: public QPDFObjectHandle::StringDecrypter
  248 +{
  249 + friend class QPDF;
  250 +
  251 + public:
  252 + StringDecrypter(QPDF* qpdf, QPDFObjGen og);
  253 + ~StringDecrypter() override = default;
  254 + void decryptString(std::string& val) override;
  255 +
  256 + private:
  257 + QPDF* qpdf;
  258 + QPDFObjGen og;
  259 +};
  260 +
  261 +// PDF 1.4: Table F.4
  262 +struct QPDF::HPageOffsetEntry
  263 +{
  264 + int delta_nobjects{0}; // 1
  265 + qpdf_offset_t delta_page_length{0}; // 2
  266 + // vectors' sizes = nshared_objects
  267 + int nshared_objects{0}; // 3
  268 + std::vector<int> shared_identifiers; // 4
  269 + std::vector<int> shared_numerators; // 5
  270 + qpdf_offset_t delta_content_offset{0}; // 6
  271 + qpdf_offset_t delta_content_length{0}; // 7
  272 +};
  273 +
  274 +// PDF 1.4: Table F.3
  275 +struct QPDF::HPageOffset
  276 +{
  277 + int min_nobjects{0}; // 1
  278 + qpdf_offset_t first_page_offset{0}; // 2
  279 + int nbits_delta_nobjects{0}; // 3
  280 + int min_page_length{0}; // 4
  281 + int nbits_delta_page_length{0}; // 5
  282 + int min_content_offset{0}; // 6
  283 + int nbits_delta_content_offset{0}; // 7
  284 + int min_content_length{0}; // 8
  285 + int nbits_delta_content_length{0}; // 9
  286 + int nbits_nshared_objects{0}; // 10
  287 + int nbits_shared_identifier{0}; // 11
  288 + int nbits_shared_numerator{0}; // 12
  289 + int shared_denominator{0}; // 13
  290 + // vector size is npages
  291 + std::vector<HPageOffsetEntry> entries;
  292 +};
  293 +
  294 +// PDF 1.4: Table F.6
  295 +struct QPDF::HSharedObjectEntry
  296 +{
  297 + // Item 3 is a 128-bit signature (unsupported by Acrobat)
  298 + int delta_group_length{0}; // 1
  299 + int signature_present{0}; // 2 -- always 0
  300 + int nobjects_minus_one{0}; // 4 -- always 0
  301 +};
  302 +
  303 +// PDF 1.4: Table F.5
  304 +struct QPDF::HSharedObject
  305 +{
  306 + int first_shared_obj{0}; // 1
  307 + qpdf_offset_t first_shared_offset{0}; // 2
  308 + int nshared_first_page{0}; // 3
  309 + int nshared_total{0}; // 4
  310 + int nbits_nobjects{0}; // 5
  311 + int min_group_length{0}; // 6
  312 + int nbits_delta_group_length{0}; // 7
  313 + // vector size is nshared_total
  314 + std::vector<HSharedObjectEntry> entries;
  315 +};
  316 +
  317 +// PDF 1.4: Table F.9
  318 +struct QPDF::HGeneric
  319 +{
  320 + int first_object{0}; // 1
  321 + qpdf_offset_t first_object_offset{0}; // 2
  322 + int nobjects{0}; // 3
  323 + int group_length{0}; // 4
  324 +};
  325 +
  326 +// Other linearization data structures
  327 +
  328 +// Initialized from Linearization Parameter dictionary
  329 +struct QPDF::LinParameters
  330 +{
  331 + qpdf_offset_t file_size{0}; // /L
  332 + int first_page_object{0}; // /O
  333 + qpdf_offset_t first_page_end{0}; // /E
  334 + int npages{0}; // /N
  335 + qpdf_offset_t xref_zero_offset{0}; // /T
  336 + int first_page{0}; // /P
  337 + qpdf_offset_t H_offset{0}; // offset of primary hint stream
  338 + qpdf_offset_t H_length{0}; // length of primary hint stream
  339 +};
  340 +
  341 +// Computed hint table value data structures. These tables contain the computed values on which
  342 +// the hint table values are based. They exclude things like number of bits and store actual
  343 +// values instead of mins and deltas. File offsets are also absolute rather than being offset
  344 +// by the size of the primary hint table. We populate the hint table structures from these
  345 +// during writing and compare the hint table values with these during validation. We ignore
  346 +// some values for various reasons described in the code. Those values are omitted from these
  347 +// structures. Note also that object numbers are object numbers from the input file, not the
  348 +// output file.
  349 +
  350 +// Naming convention: CHSomething is analogous to HSomething above. "CH" is computed hint.
  351 +
  352 +struct QPDF::CHPageOffsetEntry
  353 +{
  354 + int nobjects{0};
  355 + int nshared_objects{0};
  356 + // vectors' sizes = nshared_objects
  357 + std::vector<int> shared_identifiers;
  358 +};
  359 +
  360 +struct QPDF::CHPageOffset
  361 +{
  362 + // vector size is npages
  363 + std::vector<CHPageOffsetEntry> entries;
  364 +};
  365 +
  366 +struct QPDF::CHSharedObjectEntry
  367 +{
  368 + CHSharedObjectEntry(int object) :
  369 + object(object)
  370 + {
  371 + }
  372 +
  373 + int object;
  374 +};
  375 +
  376 +// PDF 1.4: Table F.5
  377 +struct QPDF::CHSharedObject
  378 +{
  379 + int first_shared_obj{0};
  380 + int nshared_first_page{0};
  381 + int nshared_total{0};
  382 + // vector size is nshared_total
  383 + std::vector<CHSharedObjectEntry> entries;
  384 +};
  385 +
  386 +// No need for CHGeneric -- HGeneric is fine as is.
  387 +
  388 +// Data structures to support optimization -- implemented in QPDF_optimization.cc
  389 +
  390 +class QPDF::ObjUser
  391 +{
  392 + public:
  393 + enum user_e { ou_bad, ou_page, ou_thumb, ou_trailer_key, ou_root_key, ou_root };
  394 +
  395 + // type is set to ou_bad
  396 + ObjUser();
  397 +
  398 + // type must be ou_root
  399 + ObjUser(user_e type);
  400 +
  401 + // type must be one of ou_page or ou_thumb
  402 + ObjUser(user_e type, int pageno);
  403 +
  404 + // type must be one of ou_trailer_key or ou_root_key
  405 + ObjUser(user_e type, std::string const& key);
  406 +
  407 + bool operator<(ObjUser const&) const;
  408 +
  409 + user_e ou_type;
  410 + int pageno; // if ou_page;
  411 + std::string key; // if ou_trailer_key or ou_root_key
  412 +};
  413 +
  414 +struct QPDF::UpdateObjectMapsFrame
  415 +{
  416 + UpdateObjectMapsFrame(ObjUser const& ou, QPDFObjectHandle oh, bool top);
  417 +
  418 + ObjUser const& ou;
  419 + QPDFObjectHandle oh;
  420 + bool top;
  421 +};
  422 +
  423 +class QPDF::PatternFinder: public InputSource::Finder
  424 +{
  425 + public:
  426 + PatternFinder(QPDF& qpdf, bool (QPDF::*checker)()) :
  427 + qpdf(qpdf),
  428 + checker(checker)
  429 + {
  430 + }
  431 + ~PatternFinder() override = default;
  432 + bool
  433 + check() override
  434 + {
  435 + return (this->qpdf.*checker)();
  436 + }
  437 +
  438 + private:
  439 + QPDF& qpdf;
  440 + bool (QPDF::*checker)();
  441 +};
  442 +
  443 +class QPDF::Members
  444 +{
  445 + friend class QPDF;
  446 + friend class ResolveRecorder;
  447 +
  448 + public:
  449 + Members();
  450 + Members(Members const&) = delete;
  451 + ~Members() = default;
  452 +
  453 + private:
  454 + std::shared_ptr<QPDFLogger> log;
  455 + unsigned long long unique_id{0};
  456 + QPDFTokenizer tokenizer;
  457 + std::shared_ptr<InputSource> file;
  458 + std::string last_object_description;
  459 + bool provided_password_is_hex_key{false};
  460 + bool ignore_xref_streams{false};
  461 + bool suppress_warnings{false};
  462 + size_t max_warnings{0};
  463 + bool attempt_recovery{true};
  464 + bool check_mode{false};
  465 + std::shared_ptr<EncryptionParameters> encp;
  466 + std::string pdf_version;
  467 + std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
  468 + // Various tables are indexed by object id, with potential size id + 1
  469 + int xref_table_max_id{std::numeric_limits<int>::max() - 1};
  470 + qpdf_offset_t xref_table_max_offset{0};
  471 + std::set<int> deleted_objects;
  472 + std::map<QPDFObjGen, ObjCache> obj_cache;
  473 + std::set<QPDFObjGen> resolving;
  474 + QPDFObjectHandle trailer;
  475 + std::vector<QPDFObjectHandle> all_pages;
  476 + bool invalid_page_found{false};
  477 + std::map<QPDFObjGen, int> pageobj_to_pages_pos;
  478 + bool pushed_inherited_attributes_to_pages{false};
  479 + bool ever_pushed_inherited_attributes_to_pages{false};
  480 + bool ever_called_get_all_pages{false};
  481 + std::vector<QPDFExc> warnings;
  482 + std::map<unsigned long long, ObjCopier> object_copiers;
  483 + std::shared_ptr<QPDFObjectHandle::StreamDataProvider> copied_streams;
  484 + // copied_stream_data_provider is owned by copied_streams
  485 + CopiedStreamDataProvider* copied_stream_data_provider{nullptr};
  486 + bool reconstructed_xref{false};
  487 + bool fixed_dangling_refs{false};
  488 + bool immediate_copy_from{false};
  489 + bool in_parse{false};
  490 + bool parsed{false};
  491 + std::set<int> resolved_object_streams;
  492 +
  493 + // Linearization data
  494 + qpdf_offset_t first_xref_item_offset{0}; // actual value from file
  495 + bool uncompressed_after_compressed{false};
  496 + bool linearization_warnings{false};
  497 +
  498 + // Linearization parameter dictionary and hint table data: may be read from file or computed
  499 + // prior to writing a linearized file
  500 + QPDFObjectHandle lindict;
  501 + LinParameters linp;
  502 + HPageOffset page_offset_hints;
  503 + HSharedObject shared_object_hints;
  504 + HGeneric outline_hints;
  505 +
  506 + // Computed linearization data: used to populate above tables during writing and to compare
  507 + // with them during validation. c_ means computed.
  508 + LinParameters c_linp;
  509 + CHPageOffset c_page_offset_data;
  510 + CHSharedObject c_shared_object_data;
  511 + HGeneric c_outline_data;
  512 +
  513 + // Object ordering data for linearized files: initialized by calculateLinearizationData().
  514 + // Part numbers refer to the PDF 1.4 specification.
  515 + std::vector<QPDFObjectHandle> part4;
  516 + std::vector<QPDFObjectHandle> part6;
  517 + std::vector<QPDFObjectHandle> part7;
  518 + std::vector<QPDFObjectHandle> part8;
  519 + std::vector<QPDFObjectHandle> part9;
  520 +
  521 + // Optimization data
  522 + std::map<ObjUser, std::set<QPDFObjGen>> obj_user_to_objects;
  523 + std::map<QPDFObjGen, std::set<ObjUser>> object_to_obj_users;
  524 +};
  525 +
  526 +// JobSetter class is restricted to QPDFJob.
  527 +class QPDF::JobSetter
  528 +{
  529 + friend class QPDFJob;
  530 +
  531 + private:
  532 + // Enable enhanced warnings for pdf file checking.
  533 + static void
  534 + setCheckMode(QPDF& qpdf, bool val)
  535 + {
  536 + qpdf.m->check_mode = val;
  537 + }
  538 +};
  539 +
  540 +class QPDF::ResolveRecorder
  541 +{
  542 + public:
  543 + ResolveRecorder(QPDF* qpdf, QPDFObjGen const& og) :
  544 + qpdf(qpdf),
  545 + iter(qpdf->m->resolving.insert(og).first)
  546 + {
  547 + }
  548 + virtual ~ResolveRecorder()
  549 + {
  550 + this->qpdf->m->resolving.erase(iter);
  551 + }
  552 +
  553 + private:
  554 + QPDF* qpdf;
  555 + std::set<QPDFObjGen>::const_iterator iter;
  556 +};
  557 +
  558 +#endif // QPDF_PRIVATE_HH
... ...