1 : //========================================================================
2 : //
3 : // XRef.h
4 : //
5 : // Copyright 1996-2003 Glyph & Cog, LLC
6 : //
7 : //========================================================================
8 :
9 : //========================================================================
10 : //
11 : // Modified under the Poppler project - http://poppler.freedesktop.org
12 : //
13 : // All changes made under the Poppler project to this file are licensed
14 : // under GPL version 2 or later
15 : //
16 : // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
17 : // Copyright (C) 2006, 2008, 2010-2013 Albert Astals Cid <aacid@kde.org>
18 : // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
19 : // Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
20 : // Copyright (C) 2010 Ilya Gorenbein <igorenbein@finjan.com>
21 : // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
22 : // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@kabelmail.de>
23 : // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
24 : // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
25 : //
26 : // To see a description of the changes please see the Changelog file that
27 : // came with your tarball or type make ChangeLog if you are building from git
28 : //
29 : //========================================================================
30 :
31 : #ifndef XREF_H
32 : #define XREF_H
33 :
34 : #ifdef USE_GCC_PRAGMAS
35 : #pragma interface
36 : #endif
37 :
38 : #include "poppler-config.h"
39 : #include "goo/gtypes.h"
40 : #include "goo/GooMutex.h"
41 : #include "Object.h"
42 : #include "Stream.h"
43 :
44 : #include <vector>
45 :
46 : class Dict;
47 : class Stream;
48 : class Parser;
49 : class PopplerCache;
50 :
51 : //------------------------------------------------------------------------
52 : // XRef
53 : //------------------------------------------------------------------------
54 :
55 : enum XRefEntryType {
56 : xrefEntryFree,
57 : xrefEntryUncompressed,
58 : xrefEntryCompressed,
59 : xrefEntryNone
60 : };
61 :
62 : struct XRefEntry {
63 : Goffset offset;
64 : int gen;
65 : XRefEntryType type;
66 : int flags;
67 : Object obj; //if this entry was updated, obj will contains the updated object
68 :
69 : enum Flag {
70 : // Regular flags
71 : Updated, // Entry was modified
72 :
73 : // Special flags -- available only after xref->scanSpecialFlags() is run
74 : Unencrypted, // Entry is stored in unencrypted form (meaningless in unencrypted documents)
75 : DontRewrite // Entry must not be written back in case of full rewrite
76 : };
77 :
78 : inline GBool getFlag(Flag flag) {
79 : const int mask = (1 << (int)flag);
80 : return (flags & mask) != 0;
81 : }
82 :
83 : inline void setFlag(Flag flag, GBool value) {
84 : const int mask = (1 << (int)flag);
85 : if (value) {
86 : flags |= mask;
87 : } else {
88 : flags &= ~mask;
89 : }
90 : }
91 : };
92 :
93 : class XRef {
94 : public:
95 :
96 : // Constructor, create an empty XRef, used for PDF writing
97 : XRef();
98 : // Constructor, create an empty XRef but with info dict, used for PDF writing
99 : XRef(Object *trailerDictA);
100 : // Constructor. Read xref table from stream.
101 : XRef(BaseStream *strA, Goffset pos, Goffset mainXRefEntriesOffsetA = 0, GBool *wasReconstructed = NULL, GBool reconstruct = false);
102 :
103 : // Destructor.
104 : ~XRef();
105 :
106 : // Copy xref but with new base stream!
107 : XRef *copy();
108 :
109 : // Is xref table valid?
110 149 : GBool isOk() { return ok; }
111 :
112 : // Is the last XRef section a stream or a table?
113 : GBool isXRefStream() { return xRefStream; }
114 :
115 : // Get the error code (if isOk() returns false).
116 : int getErrorCode() { return errCode; }
117 :
118 : // Set the encryption parameters.
119 : void setEncryption(int permFlagsA, GBool ownerPasswordOkA,
120 : Guchar *fileKeyA, int keyLengthA,
121 : int encVersionA, int encRevisionA,
122 : CryptAlgorithm encAlgorithmA);
123 : // Mark Encrypt entry as Unencrypted
124 : void markUnencrypted();
125 :
126 : void getEncryptionParameters(Guchar **fileKeyA, CryptAlgorithm *encAlgorithmA, int *keyLengthA);
127 :
128 : // Is the file encrypted?
129 : GBool isEncrypted() { return encrypted; }
130 :
131 : // Check various permissions.
132 : GBool okToPrint(GBool ignoreOwnerPW = gFalse);
133 : GBool okToPrintHighRes(GBool ignoreOwnerPW = gFalse);
134 : GBool okToChange(GBool ignoreOwnerPW = gFalse);
135 : GBool okToCopy(GBool ignoreOwnerPW = gFalse);
136 : GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
137 : GBool okToFillForm(GBool ignoreOwnerPW = gFalse);
138 : GBool okToAccessibility(GBool ignoreOwnerPW = gFalse);
139 : GBool okToAssemble(GBool ignoreOwnerPW = gFalse);
140 : int getPermFlags() { return permFlags; }
141 :
142 : // Get catalog object.
143 : Object *getCatalog(Object *obj);
144 :
145 : // Fetch an indirect reference.
146 : Object *fetch(int num, int gen, Object *obj, int recursion = 0);
147 :
148 : // Return the document's Info dictionary (if any).
149 : Object *getDocInfo(Object *obj);
150 : Object *getDocInfoNF(Object *obj);
151 :
152 : // Return the number of objects in the xref table.
153 : int getNumObjects() { return size; }
154 :
155 : // Return the catalog object reference.
156 : int getRootNum() { return rootNum; }
157 : int getRootGen() { return rootGen; }
158 :
159 : // Get end position for a stream in a damaged file.
160 : // Returns false if unknown or file is not damaged.
161 : GBool getStreamEnd(Goffset streamStart, Goffset *streamEnd);
162 :
163 : // Retuns the entry that belongs to the offset
164 : int getNumEntry(Goffset offset);
165 :
166 : // Scans the document and sets special flags in all xref entries. One of those
167 : // flags is Unencrypted, which affects how the object is fetched. Therefore,
168 : // this function must be called before fetching unencrypted objects (e.g.
169 : // Encrypt dictionary, XRef streams). Note that the code that initializes
170 : // decryption doesn't need to call this function, because it runs before
171 : // decryption is enabled, and therefore the Unencrypted flag is ignored.
172 : void scanSpecialFlags();
173 :
174 : // Direct access.
175 : XRefEntry *getEntry(int i, GBool complainIfMissing = gTrue);
176 : Object *getTrailerDict() { return &trailerDict; }
177 :
178 : // Write access
179 : void setModifiedObject(Object* o, Ref r);
180 : Ref addIndirectObject (Object* o);
181 : void removeIndirectObject(Ref r);
182 : void add(int num, int gen, Goffset offs, GBool used);
183 :
184 : // Output XRef table to stream
185 : void writeTableToFile(OutStream* outStr, GBool writeAllEntries);
186 : // Output XRef stream contents to GooString and fill trailerDict fields accordingly
187 : void writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref);
188 :
189 : // to be thread safe during write where changes are not allowed
190 : void lock();
191 : void unlock();
192 :
193 : private:
194 :
195 : BaseStream *str; // input stream
196 : Goffset start; // offset in file (to allow for garbage
197 : // at beginning of file)
198 : XRefEntry *entries; // xref entries
199 : int capacity; // size of <entries> array
200 : int size; // number of entries
201 : int rootNum, rootGen; // catalog dict
202 : GBool ok; // true if xref table is valid
203 : int errCode; // error code (if <ok> is false)
204 : Object trailerDict; // trailer dictionary
205 : Goffset *streamEnds; // 'endstream' positions - only used in
206 : // damaged files
207 : int streamEndsLen; // number of valid entries in streamEnds
208 : PopplerCache *objStrs; // cached object streams
209 : GBool encrypted; // true if file is encrypted
210 : int encRevision;
211 : int encVersion; // encryption algorithm
212 : CryptAlgorithm encAlgorithm; // encryption algorithm
213 : int keyLength; // length of key, in bytes
214 : int permFlags; // permission bits
215 : Guchar fileKey[32]; // file decryption key
216 : GBool ownerPasswordOk; // true if owner password is correct
217 : Goffset prevXRefOffset; // position of prev XRef section (= next to read)
218 : Goffset mainXRefEntriesOffset; // offset of entries in main XRef table
219 : GBool xRefStream; // true if last XRef section is a stream
220 : Goffset mainXRefOffset; // position of the main XRef table/stream
221 : GBool scannedSpecialFlags; // true if scanSpecialFlags has been called
222 : GBool strOwner; // true if str is owned by the instance
223 : #if MULTITHREADED
224 : GooMutex mutex;
225 : #endif
226 :
227 : void init();
228 : int reserve(int newSize);
229 : int resize(int newSize);
230 : GBool readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
231 : GBool readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum);
232 : GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n);
233 : GBool readXRefStream(Stream *xrefStr, Goffset *pos);
234 : GBool constructXRef(GBool *wasReconstructed, GBool needCatalogDict = gFalse);
235 : GBool parseEntry(Goffset offset, XRefEntry *entry);
236 : void readXRefUntil(int untilEntryNum, std::vector<int> *xrefStreamObjsNum = NULL);
237 : void markUnencrypted(Object *obj);
238 :
239 : class XRefWriter {
240 : public:
241 : virtual void startSection(int first, int count) = 0;
242 : virtual void writeEntry(Goffset offset, int gen, XRefEntryType type) = 0;
243 : virtual ~XRefWriter() {};
244 : };
245 :
246 : class XRefTableWriter: public XRefWriter {
247 : public:
248 : XRefTableWriter(OutStream* outStrA);
249 : void startSection(int first, int count);
250 : void writeEntry(Goffset offset, int gen, XRefEntryType type);
251 : private:
252 : OutStream* outStr;
253 : };
254 :
255 : class XRefStreamWriter: public XRefWriter {
256 : public:
257 : XRefStreamWriter(Object *index, GooString *stmBuf);
258 : void startSection(int first, int count);
259 : void writeEntry(Goffset offset, int gen, XRefEntryType type);
260 : private:
261 : Object *index;
262 : GooString *stmBuf;
263 : };
264 :
265 : void writeXRef(XRefWriter *writer, GBool writeAllEntries);
266 : };
267 :
268 : #endif
|