]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/PDFDoc.cxx
1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
24 #include "GlobalParams.h"
30 #include "OutputDev.h"
32 #include "ErrorCodes.h"
35 #include "SecurityHandler.h"
36 #ifndef DISABLE_OUTLINE
41 //------------------------------------------------------------------------
43 #define headerSearchSize 1024 // read this many bytes at beginning of
44 // file to look for '%PDF'
46 //------------------------------------------------------------------------
48 //------------------------------------------------------------------------
50 PDFDoc::PDFDoc(GString
*fileNameA
, GString
*ownerPassword
,
51 GString
*userPassword
, void *guiDataA
) {
53 GString
*fileName1
, *fileName2
;
65 #ifndef DISABLE_OUTLINE
76 if (!(file
= fopen(fileName1
->getCString(), "rb", "ctx=stm"))) {
77 error(-1, "Couldn't open file '%s'", fileName1
->getCString());
78 errCode
= errOpenFile
;
82 if (!(file
= fopen(fileName1
->getCString(), "rb"))) {
83 fileName2
= fileName
->copy();
84 fileName2
->lowerCase();
85 if (!(file
= fopen(fileName2
->getCString(), "rb"))) {
86 fileName2
->upperCase();
87 if (!(file
= fopen(fileName2
->getCString(), "rb"))) {
88 error(-1, "Couldn't open file '%s'", fileName
->getCString());
90 errCode
= errOpenFile
;
100 str
= new FileStream(file
, 0, gFalse
, 0, &obj
);
102 ok
= setup(ownerPassword
, userPassword
);
106 PDFDoc::PDFDoc(wchar_t *fileNameA
, int fileNameLen
, GString
*ownerPassword
,
107 GString
*userPassword
, void *guiDataA
) {
108 OSVERSIONINFO version
;
109 wchar_t fileName2
[_MAX_PATH
+ 1];
123 #ifndef DISABLE_OUTLINE
127 //~ file name should be stored in Unicode (?)
128 fileName
= new GString();
129 for (i
= 0; i
< fileNameLen
; ++i
) {
130 fileName
->append((char)fileNameA
[i
]);
133 // zero-terminate the file name string
134 for (i
= 0; i
< fileNameLen
&& i
< _MAX_PATH
; ++i
) {
135 fileName2
[i
] = fileNameA
[i
];
140 // NB: _wfopen is only available in NT
141 version
.dwOSVersionInfoSize
= sizeof(version
);
142 GetVersionEx(&version
);
143 if (version
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
144 file
= _wfopen(fileName2
, L
"rb");
146 file
= fopen(fileName
->getCString(), "rb");
149 error(-1, "Couldn't open file '%s'", fileName
->getCString());
150 errCode
= errOpenFile
;
156 str
= new FileStream(file
, 0, gFalse
, 0, &obj
);
158 ok
= setup(ownerPassword
, userPassword
);
162 PDFDoc::PDFDoc(BaseStream
*strA
, GString
*ownerPassword
,
163 GString
*userPassword
, void *guiDataA
) {
173 #ifndef DISABLE_OUTLINE
176 ok
= setup(ownerPassword
, userPassword
);
179 GBool
PDFDoc::setup(GString
*ownerPassword
, GString
*userPassword
) {
186 xref
= new XRef(str
);
188 error(-1, "Couldn't read xref table");
189 errCode
= xref
->getErrorCode();
193 // check for encryption
194 if (!checkEncryption(ownerPassword
, userPassword
)) {
195 errCode
= errEncrypted
;
200 catalog
= new Catalog(xref
);
201 if (!catalog
->isOk()) {
202 error(-1, "Couldn't read page catalog");
203 errCode
= errBadCatalog
;
207 #ifndef DISABLE_OUTLINE
209 outline
= new Outline(catalog
->getOutline(), xref
);
217 #ifndef DISABLE_OUTLINE
242 // Check for a PDF header on this stream. Skip past some garbage
244 void PDFDoc::checkHeader() {
245 char hdrBuf
[headerSearchSize
+1];
250 for (i
= 0; i
< headerSearchSize
; ++i
) {
251 hdrBuf
[i
] = str
->getChar();
253 hdrBuf
[headerSearchSize
] = '\0';
254 for (i
= 0; i
< headerSearchSize
- 5; ++i
) {
255 if (!strncmp(&hdrBuf
[i
], "%PDF-", 5)) {
259 if (i
>= headerSearchSize
- 5) {
260 error(-1, "May not be a PDF file (continuing anyway)");
264 if (!(p
= strtok(&hdrBuf
[i
+5], " \t\n\r"))) {
265 error(-1, "May not be a PDF file (continuing anyway)");
268 pdfVersion
= atof(p
);
269 if (!(hdrBuf
[i
+5] >= '0' && hdrBuf
[i
+5] <= '9') ||
270 pdfVersion
> supportedPDFVersionNum
+ 0.0001) {
271 error(-1, "PDF version %s -- xpdf supports version %s"
272 " (continuing anyway)", p
, supportedPDFVersionStr
);
276 GBool
PDFDoc::checkEncryption(GString
*ownerPassword
, GString
*userPassword
) {
279 SecurityHandler
*secHdlr
;
282 xref
->getTrailerDict()->dictLookup("Encrypt", &encrypt
);
283 if ((encrypted
= encrypt
.isDict())) {
284 if ((secHdlr
= SecurityHandler::make(this, &encrypt
))) {
285 if (secHdlr
->checkEncryption(ownerPassword
, userPassword
)) {
286 // authorization succeeded
287 xref
->setEncryption(secHdlr
->getPermissionFlags(),
288 secHdlr
->getOwnerPasswordOk(),
289 secHdlr
->getFileKey(),
290 secHdlr
->getFileKeyLength(),
291 secHdlr
->getEncVersion());
294 // authorization failed
299 // couldn't find the matching security handler
303 // document is not encrypted
310 void PDFDoc::displayPage(OutputDev
*out
, int page
, double hDPI
, double vDPI
,
311 int rotate
, GBool useMediaBox
, GBool crop
,
313 GBool (*abortCheckCbk
)(void *data
),
314 void *abortCheckCbkData
) {
317 if (globalParams
->getPrintCommands()) {
318 printf("***** page %d *****\n", page
);
320 p
= catalog
->getPage(page
);
326 p
->display(out
, hDPI
, vDPI
, rotate
, useMediaBox
, crop
, links
, catalog
,
327 abortCheckCbk
, abortCheckCbkData
);
329 p
->display(out
, hDPI
, vDPI
, rotate
, useMediaBox
, crop
, NULL
, catalog
,
330 abortCheckCbk
, abortCheckCbkData
);
334 void PDFDoc::displayPages(OutputDev
*out
, int firstPage
, int lastPage
,
335 double hDPI
, double vDPI
, int rotate
,
336 GBool useMediaBox
, GBool crop
, GBool doLinks
,
337 GBool (*abortCheckCbk
)(void *data
),
338 void *abortCheckCbkData
) {
341 for (page
= firstPage
; page
<= lastPage
; ++page
) {
342 displayPage(out
, page
, hDPI
, vDPI
, rotate
, useMediaBox
, crop
, doLinks
,
343 abortCheckCbk
, abortCheckCbkData
);
347 void PDFDoc::displayPageSlice(OutputDev
*out
, int page
,
348 double hDPI
, double vDPI
, int rotate
,
349 GBool useMediaBox
, GBool crop
, GBool doLinks
,
350 int sliceX
, int sliceY
, int sliceW
, int sliceH
,
351 GBool (*abortCheckCbk
)(void *data
),
352 void *abortCheckCbkData
) {
355 p
= catalog
->getPage(page
);
361 p
->displaySlice(out
, hDPI
, vDPI
, rotate
, useMediaBox
, crop
,
362 sliceX
, sliceY
, sliceW
, sliceH
,
363 links
, catalog
, abortCheckCbk
, abortCheckCbkData
);
365 p
->displaySlice(out
, hDPI
, vDPI
, rotate
, useMediaBox
, crop
,
366 sliceX
, sliceY
, sliceW
, sliceH
,
367 NULL
, catalog
, abortCheckCbk
, abortCheckCbkData
);
371 Links
*PDFDoc::takeLinks() {
379 GBool
PDFDoc::isLinearized() {
381 Object obj1
, obj2
, obj3
, obj4
, obj5
;
386 parser
= new Parser(xref
,
388 str
->makeSubStream(str
->getStart(), gFalse
, 0, &obj1
)));
389 parser
->getObj(&obj1
);
390 parser
->getObj(&obj2
);
391 parser
->getObj(&obj3
);
392 parser
->getObj(&obj4
);
393 if (obj1
.isInt() && obj2
.isInt() && obj3
.isCmd("obj") &&
395 obj4
.dictLookup("Linearized", &obj5
);
396 if (obj5
.isNum() && obj5
.getNum() > 0) {
409 GBool
PDFDoc::saveAs(GString
*name
) {
413 if (!(f
= fopen(name
->getCString(), "wb"))) {
414 error(-1, "Couldn't open file '%s'", name
->getCString());
418 while ((c
= str
->getChar()) != EOF
) {
426 void PDFDoc::getLinks(Page
*page
) {
429 links
= new Links(page
->getAnnots(&obj
), catalog
->getBaseURI());