1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
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, 2016 Thomas Freitag <Thomas.Freitag@kabelmail.de>
23 // Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso@hotmail.it>
24 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
25 // Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
27 // To see a description of the changes please see the Changelog file that
28 // came with your tarball or type make ChangeLog if you are building from git
30 //========================================================================
35 #ifdef USE_GCC_PRAGMAS
39 #include "poppler-config.h"
40 #include "goo/gtypes.h"
41 #include "goo/GooMutex.h"
52 //------------------------------------------------------------------------
54 //------------------------------------------------------------------------
58 xrefEntryUncompressed
,
68 Object obj
; //if this entry was updated, obj will contains the updated object
72 Updated
, // Entry was modified
74 // Special flags -- available only after xref->scanSpecialFlags() is run
75 Unencrypted
, // Entry is stored in unencrypted form (meaningless in unencrypted documents)
76 DontRewrite
// Entry must not be written back in case of full rewrite
79 inline GBool
getFlag(Flag flag
) {
80 const int mask
= (1 << (int)flag
);
81 return (flags
& mask
) != 0;
84 inline void setFlag(Flag flag
, GBool value
) {
85 const int mask
= (1 << (int)flag
);
97 // Constructor, create an empty XRef, used for PDF writing
99 // Constructor, create an empty XRef but with info dict, used for PDF writing
100 XRef(Object
*trailerDictA
);
101 // Constructor. Read xref table from stream.
102 XRef(BaseStream
*strA
, Goffset pos
, Goffset mainXRefEntriesOffsetA
= 0, GBool
*wasReconstructed
= NULL
, GBool reconstruct
= false);
107 // Copy xref but with new base stream!
110 // Is xref table valid?
111 GBool
isOk() { return ok
; }
113 // Is the last XRef section a stream or a table?
114 GBool
isXRefStream() { return xRefStream
; }
116 // Get the error code (if isOk() returns false).
117 int getErrorCode() { return errCode
; }
119 // Set the encryption parameters.
120 void setEncryption(int permFlagsA
, GBool ownerPasswordOkA
,
121 Guchar
*fileKeyA
, int keyLengthA
,
122 int encVersionA
, int encRevisionA
,
123 CryptAlgorithm encAlgorithmA
);
124 // Mark Encrypt entry as Unencrypted
125 void markUnencrypted();
127 void getEncryptionParameters(Guchar
**fileKeyA
, CryptAlgorithm
*encAlgorithmA
, int *keyLengthA
);
129 // Is the file encrypted?
130 GBool
isEncrypted() { return encrypted
; }
132 // Check various permissions.
133 GBool
okToPrint(GBool ignoreOwnerPW
= gFalse
);
134 GBool
okToPrintHighRes(GBool ignoreOwnerPW
= gFalse
);
135 GBool
okToChange(GBool ignoreOwnerPW
= gFalse
);
136 GBool
okToCopy(GBool ignoreOwnerPW
= gFalse
);
137 GBool
okToAddNotes(GBool ignoreOwnerPW
= gFalse
);
138 GBool
okToFillForm(GBool ignoreOwnerPW
= gFalse
);
139 GBool
okToAccessibility(GBool ignoreOwnerPW
= gFalse
);
140 GBool
okToAssemble(GBool ignoreOwnerPW
= gFalse
);
141 int getPermFlags() { return permFlags
; }
143 // Get catalog object.
144 Object
*getCatalog(Object
*obj
);
146 // Fetch an indirect reference.
147 Object
*fetch(int num
, int gen
, Object
*obj
, int recursion
= 0);
149 // Return the document's Info dictionary (if any).
150 Object
*getDocInfo(Object
*obj
);
151 Object
*getDocInfoNF(Object
*obj
);
153 // Create and return the document's Info dictionary if none exists.
154 // Otherwise return the existing one.
155 Object
*createDocInfoIfNoneExists(Object
*obj
);
157 // Remove the document's Info dictionary and update the trailer dictionary.
158 void removeDocInfo();
160 // Return the number of objects in the xref table.
161 int getNumObjects() { return size
; }
163 // Return the catalog object reference.
164 int getRootNum() { return rootNum
; }
165 int getRootGen() { return rootGen
; }
167 // Get end position for a stream in a damaged file.
168 // Returns false if unknown or file is not damaged.
169 GBool
getStreamEnd(Goffset streamStart
, Goffset
*streamEnd
);
171 // Retuns the entry that belongs to the offset
172 int getNumEntry(Goffset offset
);
174 // Scans the document and sets special flags in all xref entries. One of those
175 // flags is Unencrypted, which affects how the object is fetched. Therefore,
176 // this function must be called before fetching unencrypted objects (e.g.
177 // Encrypt dictionary, XRef streams). Note that the code that initializes
178 // decryption doesn't need to call this function, because it runs before
179 // decryption is enabled, and therefore the Unencrypted flag is ignored.
180 void scanSpecialFlags();
183 XRefEntry
*getEntry(int i
, GBool complainIfMissing
= gTrue
);
184 Object
*getTrailerDict() { return &trailerDict
; }
186 // Was the XRef modified?
187 GBool
isModified() { return modified
; }
188 // Set the modification flag for XRef to true.
189 void setModified() { modified
= gTrue
; }
192 void setModifiedObject(Object
* o
, Ref r
);
193 Ref
addIndirectObject (Object
* o
);
194 void removeIndirectObject(Ref r
);
195 void add(int num
, int gen
, Goffset offs
, GBool used
);
197 // Output XRef table to stream
198 void writeTableToFile(OutStream
* outStr
, GBool writeAllEntries
);
199 // Output XRef stream contents to GooString and fill trailerDict fields accordingly
200 void writeStreamToBuffer(GooString
*stmBuf
, Dict
*xrefDict
, XRef
*xref
);
202 // to be thread safe during write where changes are not allowed
208 BaseStream
*str
; // input stream
209 Goffset start
; // offset in file (to allow for garbage
210 // at beginning of file)
211 XRefEntry
*entries
; // xref entries
212 int capacity
; // size of <entries> array
213 int size
; // number of entries
214 int rootNum
, rootGen
; // catalog dict
215 GBool ok
; // true if xref table is valid
216 int errCode
; // error code (if <ok> is false)
217 GBool xrefReconstructed
; // marker, true if xref was already reconstructed
218 Object trailerDict
; // trailer dictionary
220 Goffset
*streamEnds
; // 'endstream' positions - only used in
222 int streamEndsLen
; // number of valid entries in streamEnds
223 PopplerCache
*objStrs
; // cached object streams
224 GBool encrypted
; // true if file is encrypted
226 int encVersion
; // encryption algorithm
227 CryptAlgorithm encAlgorithm
; // encryption algorithm
228 int keyLength
; // length of key, in bytes
229 int permFlags
; // permission bits
230 Guchar fileKey
[32]; // file decryption key
231 GBool ownerPasswordOk
; // true if owner password is correct
232 Goffset prevXRefOffset
; // position of prev XRef section (= next to read)
233 Goffset mainXRefEntriesOffset
; // offset of entries in main XRef table
234 GBool xRefStream
; // true if last XRef section is a stream
235 Goffset mainXRefOffset
; // position of the main XRef table/stream
236 GBool scannedSpecialFlags
; // true if scanSpecialFlags has been called
237 GBool strOwner
; // true if str is owned by the instance
243 int reserve(int newSize
);
244 int resize(int newSize
);
245 GBool
readXRef(Goffset
*pos
, std::vector
<Goffset
> *followedXRefStm
, std::vector
<int> *xrefStreamObjsNum
);
246 GBool
readXRefTable(Parser
*parser
, Goffset
*pos
, std::vector
<Goffset
> *followedXRefStm
, std::vector
<int> *xrefStreamObjsNum
);
247 GBool
readXRefStreamSection(Stream
*xrefStr
, int *w
, int first
, int n
);
248 GBool
readXRefStream(Stream
*xrefStr
, Goffset
*pos
);
249 GBool
constructXRef(GBool
*wasReconstructed
, GBool needCatalogDict
= gFalse
);
250 GBool
parseEntry(Goffset offset
, XRefEntry
*entry
);
251 void readXRefUntil(int untilEntryNum
, std::vector
<int> *xrefStreamObjsNum
= NULL
);
252 void markUnencrypted(Object
*obj
);
256 virtual void startSection(int first
, int count
) = 0;
257 virtual void writeEntry(Goffset offset
, int gen
, XRefEntryType type
) = 0;
258 virtual ~XRefWriter() {};
261 // XRefWriter subclass that writes a XRef table
262 class XRefTableWriter
: public XRefWriter
{
264 XRefTableWriter(OutStream
* outStrA
);
265 void startSection(int first
, int count
);
266 void writeEntry(Goffset offset
, int gen
, XRefEntryType type
);
271 // XRefWriter subclass that writes a XRef stream
272 class XRefStreamWriter
: public XRefWriter
{
274 XRefStreamWriter(Object
*index
, GooString
*stmBuf
, int offsetSize
);
275 void startSection(int first
, int count
);
276 void writeEntry(Goffset offset
, int gen
, XRefEntryType type
);
283 // Dummy XRefWriter subclass that only checks if all offsets fit in 4 bytes
284 class XRefPreScanWriter
: public XRefWriter
{
287 void startSection(int first
, int count
);
288 void writeEntry(Goffset offset
, int gen
, XRefEntryType type
);
290 GBool hasOffsetsBeyond4GB
;
293 void writeXRef(XRefWriter
*writer
, GBool writeAllEntries
);