Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-10 10:23:54

0001 //========================================================================
0002 //
0003 // XRef.h
0004 //
0005 // Copyright 1996-2003 Glyph & Cog, LLC
0006 //
0007 //========================================================================
0008 
0009 //========================================================================
0010 //
0011 // Modified under the Poppler project - http://poppler.freedesktop.org
0012 //
0013 // All changes made under the Poppler project to this file are licensed
0014 // under GPL version 2 or later
0015 //
0016 // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
0017 // Copyright (C) 2006, 2008, 2010-2013, 2017-2022 Albert Astals Cid <aacid@kde.org>
0018 // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
0019 // Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
0020 // Copyright (C) 2010 Ilya Gorenbein <igorenbein@finjan.com>
0021 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
0022 // Copyright (C) 2012, 2013, 2016 Thomas Freitag <Thomas.Freitag@kabelmail.de>
0023 // Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso@hotmail.it>
0024 // Copyright (C) 2013, 2017, 2019 Adrian Johnson <ajohnson@redneon.com>
0025 // Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
0026 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
0027 // Copyright (C) 2018 Marek Kasik <mkasik@redhat.com>
0028 // Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com>
0029 // Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
0030 //
0031 // To see a description of the changes please see the Changelog file that
0032 // came with your tarball or type make ChangeLog if you are building from git
0033 //
0034 //========================================================================
0035 
0036 #ifndef XREF_H
0037 #define XREF_H
0038 
0039 #include <functional>
0040 
0041 #include "poppler-config.h"
0042 #include "poppler_private_export.h"
0043 #include "Object.h"
0044 #include "Stream.h"
0045 #include "PopplerCache.h"
0046 
0047 class Dict;
0048 class Stream;
0049 class Parser;
0050 class ObjectStream;
0051 
0052 //------------------------------------------------------------------------
0053 // XRef
0054 //------------------------------------------------------------------------
0055 
0056 enum XRefEntryType
0057 {
0058     xrefEntryFree,
0059     xrefEntryUncompressed,
0060     xrefEntryCompressed,
0061     xrefEntryNone
0062 };
0063 
0064 struct XRefEntry
0065 {
0066     Goffset offset;
0067     int gen;
0068     XRefEntryType type;
0069     int flags;
0070     Object obj; // if this entry was updated, obj will contains the updated object
0071 
0072     enum Flag
0073     {
0074         // Regular flags
0075         Updated, // Entry was modified
0076         Parsing, // Entry is currently being parsed
0077 
0078         // Special flags -- available only after xref->scanSpecialFlags() is run
0079         Unencrypted, // Entry is stored in unencrypted form (meaningless in unencrypted documents)
0080         DontRewrite // Entry must not be written back in case of full rewrite
0081     };
0082 
0083     inline bool getFlag(Flag flag) const
0084     {
0085         const int mask = (1 << (int)flag);
0086         return (flags & mask) != 0;
0087     }
0088 
0089     inline void setFlag(Flag flag, bool value)
0090     {
0091         const int mask = (1 << (int)flag);
0092         if (value) {
0093             flags |= mask;
0094         } else {
0095             flags &= ~mask;
0096         }
0097     }
0098 };
0099 
0100 class POPPLER_PRIVATE_EXPORT XRef
0101 {
0102 public:
0103     // Constructor, create an empty XRef, used for PDF writing
0104     XRef();
0105     // Constructor, create an empty XRef but with info dict, used for PDF writing
0106     explicit XRef(const Object *trailerDictA);
0107     // Constructor.  Read xref table from stream.
0108     XRef(BaseStream *strA, Goffset pos, Goffset mainXRefEntriesOffsetA = 0, bool *wasReconstructed = nullptr, bool reconstruct = false, const std::function<void()> &xrefReconstructedCallback = {});
0109 
0110     // Destructor.
0111     ~XRef();
0112 
0113     XRef(const XRef &) = delete;
0114     XRef &operator=(const XRef &) = delete;
0115 
0116     // Copy xref but with new base stream!
0117     XRef *copy() const;
0118 
0119     // Is xref table valid?
0120     bool isOk() const { return ok; }
0121 
0122     // Is the last XRef section a stream or a table?
0123     bool isXRefStream() const { return xRefStream; }
0124 
0125     // Get the error code (if isOk() returns false).
0126     int getErrorCode() const { return errCode; }
0127 
0128     // Set the encryption parameters.
0129     void setEncryption(int permFlagsA, bool ownerPasswordOkA, const unsigned char *fileKeyA, int keyLengthA, int encVersionA, int encRevisionA, CryptAlgorithm encAlgorithmA);
0130     // Mark Encrypt entry as Unencrypted
0131     void markUnencrypted();
0132 
0133     void getEncryptionParameters(unsigned char **fileKeyA, CryptAlgorithm *encAlgorithmA, int *keyLengthA);
0134 
0135     // Is the file encrypted?
0136     bool isEncrypted() const { return encrypted; }
0137 
0138     // Is the given Ref encrypted?
0139     bool isRefEncrypted(Ref r);
0140 
0141     // Check various permissions.
0142     bool okToPrint(bool ignoreOwnerPW = false) const;
0143     bool okToPrintHighRes(bool ignoreOwnerPW = false) const;
0144     bool okToChange(bool ignoreOwnerPW = false) const;
0145     bool okToCopy(bool ignoreOwnerPW = false) const;
0146     bool okToAddNotes(bool ignoreOwnerPW = false) const;
0147     bool okToFillForm(bool ignoreOwnerPW = false) const;
0148     bool okToAccessibility(bool ignoreOwnerPW = false) const;
0149     bool okToAssemble(bool ignoreOwnerPW = false) const;
0150     int getPermFlags() const { return permFlags; }
0151 
0152     // Get catalog object.
0153     Object getCatalog();
0154 
0155     // Fetch an indirect reference.
0156     Object fetch(const Ref ref, int recursion = 0);
0157     // If endPos is not null, returns file position after parsing the object. This will
0158     // be a few bytes after the end of the object due to the parser reading ahead.
0159     // Returns -1 if object is in compressed stream.
0160     Object fetch(int num, int gen, int recursion = 0, Goffset *endPos = nullptr);
0161 
0162     // Return the document's Info dictionary (if any).
0163     Object getDocInfo();
0164     Object getDocInfoNF();
0165 
0166     // Create and return the document's Info dictionary if needed.
0167     // Otherwise return the existing one.
0168     // Returns in the given parameter the Ref the Info is in
0169     Object createDocInfoIfNeeded(Ref *ref);
0170 
0171     // Remove the document's Info dictionary and update the trailer dictionary.
0172     void removeDocInfo();
0173 
0174     // Return the number of objects in the xref table.
0175     int getNumObjects() const { return size; }
0176 
0177     // Return the catalog object reference.
0178     int getRootNum() const { return rootNum; }
0179     int getRootGen() const { return rootGen; }
0180     Ref getRoot() const { return { rootNum, rootGen }; }
0181 
0182     // Get end position for a stream in a damaged file.
0183     // Returns false if unknown or file is not damaged.
0184     bool getStreamEnd(Goffset streamStart, Goffset *streamEnd);
0185 
0186     // Retuns the entry that belongs to the offset
0187     int getNumEntry(Goffset offset);
0188 
0189     // Scans the document and sets special flags in all xref entries. One of those
0190     // flags is Unencrypted, which affects how the object is fetched. Therefore,
0191     // this function must be called before fetching unencrypted objects (e.g.
0192     // Encrypt dictionary, XRef streams). Note that the code that initializes
0193     // decryption doesn't need to call this function, because it runs before
0194     // decryption is enabled, and therefore the Unencrypted flag is ignored.
0195     void scanSpecialFlags();
0196 
0197     // Direct access.
0198     XRefEntry *getEntry(int i, bool complainIfMissing = true);
0199     Object *getTrailerDict() { return &trailerDict; }
0200 
0201     // Was the XRef modified?
0202     bool isModified() const { return modified; }
0203     // Set the modification flag for XRef to true.
0204     void setModified() { modified = true; }
0205 
0206     // Write access
0207     void setModifiedObject(const Object *o, Ref r);
0208     Ref addIndirectObject(const Object &o);
0209     void removeIndirectObject(Ref r);
0210     bool add(int num, int gen, Goffset offs, bool used);
0211     void add(Ref ref, Goffset offs, bool used);
0212     // Adds a stream object using AutoFreeMemStream.
0213     // The function takes ownership over dict and buffer.
0214     // The buffer should be created using gmalloc().
0215     // Returns ref to a new object.
0216     Ref addStreamObject(Dict *dict, char *buffer, const Goffset bufferSize);
0217     Ref addStreamObject(Dict *dict, uint8_t *buffer, const Goffset bufferSize);
0218 
0219     // Output XRef table to stream
0220     void writeTableToFile(OutStream *outStr, bool writeAllEntries);
0221     // Output XRef stream contents to GooString and fill trailerDict fields accordingly
0222     void writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref);
0223 
0224     // to be thread safe during write where changes are not allowed
0225     void lock();
0226     void unlock();
0227 
0228 private:
0229     BaseStream *str; // input stream
0230     Goffset start; // offset in file (to allow for garbage
0231                    //   at beginning of file)
0232     XRefEntry *entries; // xref entries
0233     int capacity; // size of <entries> array
0234     int size; // number of entries
0235     int rootNum, rootGen; // catalog dict
0236     bool ok; // true if xref table is valid
0237     int errCode; // error code (if <ok> is false)
0238     bool xrefReconstructed; // marker, true if xref was already reconstructed
0239     Object trailerDict; // trailer dictionary
0240     bool modified;
0241     Goffset *streamEnds; // 'endstream' positions - only used in
0242                          //   damaged files
0243     int streamEndsLen; // number of valid entries in streamEnds
0244     PopplerCache<Goffset, ObjectStream> objStrs; // cached object streams
0245     bool encrypted; // true if file is encrypted
0246     int encRevision;
0247     int encVersion; // encryption algorithm
0248     CryptAlgorithm encAlgorithm; // encryption algorithm
0249     int keyLength; // length of key, in bytes
0250     int permFlags; // permission bits
0251     unsigned char fileKey[32]; // file decryption key
0252     bool ownerPasswordOk; // true if owner password is correct
0253     Goffset prevXRefOffset; // position of prev XRef section (= next to read)
0254     Goffset mainXRefEntriesOffset; // offset of entries in main XRef table
0255     bool xRefStream; // true if last XRef section is a stream
0256     Goffset mainXRefOffset; // position of the main XRef table/stream
0257     bool scannedSpecialFlags; // true if scanSpecialFlags has been called
0258     bool strOwner; // true if str is owned by the instance
0259     mutable std::recursive_mutex mutex;
0260     std::function<void()> xrefReconstructedCb;
0261 
0262     int reserve(int newSize);
0263     int resize(int newSize);
0264     bool readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
0265     bool readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
0266     bool readXRefStreamSection(Stream *xrefStr, const int *w, int first, int n);
0267     bool readXRefStream(Stream *xrefStr, Goffset *pos);
0268     bool constructXRef(bool *wasReconstructed, bool needCatalogDict = false);
0269     bool parseEntry(Goffset offset, XRefEntry *entry);
0270     void readXRefUntil(int untilEntryNum, std::vector<int> *xrefStreamObjsNum = nullptr);
0271     void markUnencrypted(Object *obj);
0272 
0273     class XRefWriter
0274     {
0275     public:
0276         XRefWriter() = default;
0277         virtual void startSection(int first, int count) = 0;
0278         virtual void writeEntry(Goffset offset, int gen, XRefEntryType type) = 0;
0279         virtual ~XRefWriter();
0280 
0281         XRefWriter(const XRefWriter &) = delete;
0282         XRefWriter &operator=(const XRefWriter &other) = delete;
0283     };
0284 
0285     // XRefWriter subclass that writes a XRef table
0286     class XRefTableWriter : public XRefWriter
0287     {
0288     public:
0289         explicit XRefTableWriter(OutStream *outStrA);
0290         void startSection(int first, int count) override;
0291         void writeEntry(Goffset offset, int gen, XRefEntryType type) override;
0292 
0293     private:
0294         OutStream *outStr;
0295     };
0296 
0297     // XRefWriter subclass that writes a XRef stream
0298     class XRefStreamWriter : public XRefWriter
0299     {
0300     public:
0301         XRefStreamWriter(Array *index, GooString *stmBuf, int offsetSize);
0302         void startSection(int first, int count) override;
0303         void writeEntry(Goffset offset, int gen, XRefEntryType type) override;
0304 
0305     private:
0306         Array *index;
0307         GooString *stmBuf;
0308         int offsetSize;
0309     };
0310 
0311     // Dummy XRefWriter subclass that only checks if all offsets fit in 4 bytes
0312     class XRefPreScanWriter : public XRefWriter
0313     {
0314     public:
0315         XRefPreScanWriter();
0316         void startSection(int first, int count) override;
0317         void writeEntry(Goffset offset, int gen, XRefEntryType type) override;
0318 
0319         bool hasOffsetsBeyond4GB;
0320     };
0321 
0322     void writeXRef(XRefWriter *writer, bool writeAllEntries);
0323 };
0324 
0325 #endif