00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <aconf.h>
00010
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <string.h>
00019 #include "GString.h"
00020 #include "xpdf_config.h"
00021 #include "GlobalParams.h"
00022 #include "Page.h"
00023 #include "Catalog.h"
00024 #include "Stream.h"
00025 #include "XRef.h"
00026 #include "Link.h"
00027 #include "OutputDev.h"
00028 #include "Error.h"
00029 #include "ErrorCodes.h"
00030 #include "Lexer.h"
00031 #include "Parser.h"
00032 #ifndef DISABLE_OUTLINE
00033 #include "Outline.h"
00034 #endif
00035 #include "PDFDoc.h"
00036
00037
00038
00039 #define headerSearchSize 1024 // read this many bytes at beginning of
00040
00041
00042
00043
00044
00045
00046 PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
00047 GString *userPassword) {
00048 Object obj;
00049 GString *fileName1, *fileName2;
00050
00051 ok = gFalse;
00052 errCode = errNone;
00053
00054 file = NULL;
00055 str = NULL;
00056 xref = NULL;
00057 catalog = NULL;
00058 links = NULL;
00059 #ifndef DISABLE_OUTLINE
00060 outline = NULL;
00061 #endif
00062
00063 fileName = fileNameA;
00064 fileName1 = fileName;
00065
00066
00067
00068 fileName2 = NULL;
00069 #ifdef VMS
00070 if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
00071 error(-1, "Couldn't open file '%s'", fileName1->getCString());
00072 errCode = errOpenFile;
00073 return;
00074 }
00075 #else
00076 if (!(file = fopen(fileName1->getCString(), "rb"))) {
00077 fileName2 = fileName->copy();
00078 fileName2->lowerCase();
00079 if (!(file = fopen(fileName2->getCString(), "rb"))) {
00080 fileName2->upperCase();
00081 if (!(file = fopen(fileName2->getCString(), "rb"))) {
00082 error(-1, "Couldn't open file '%s'", fileName->getCString());
00083 delete fileName2;
00084 errCode = errOpenFile;
00085 return;
00086 }
00087 }
00088 delete fileName2;
00089 }
00090 #endif
00091
00092
00093 obj.initNull();
00094 str = new FileStream(file, 0, gFalse, 0, &obj);
00095
00096 ok = setup(ownerPassword, userPassword);
00097 }
00098
00099 PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
00100 GString *userPassword) {
00101 ok = gFalse;
00102 errCode = errNone;
00103 fileName = NULL;
00104 file = NULL;
00105 str = strA;
00106 xref = NULL;
00107 catalog = NULL;
00108 links = NULL;
00109 #ifndef DISABLE_OUTLINE
00110 outline = NULL;
00111 #endif
00112 ok = setup(ownerPassword, userPassword);
00113 }
00114
00115 GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
00116
00117 checkHeader();
00118
00119
00120 xref = new XRef(str, ownerPassword, userPassword);
00121 if (!xref->isOk()) {
00122 error(-1, "Couldn't read xref table");
00123 errCode = xref->getErrorCode();
00124 return gFalse;
00125 }
00126
00127
00128 catalog = new Catalog(xref);
00129 if (!catalog->isOk()) {
00130 error(-1, "Couldn't read page catalog");
00131 errCode = errBadCatalog;
00132 return gFalse;
00133 }
00134
00135 #ifndef DISABLE_OUTLINE
00136
00137 outline = new Outline(catalog->getOutline(), xref);
00138 #endif
00139
00140
00141 return gTrue;
00142 }
00143
00144 PDFDoc::~PDFDoc() {
00145 #ifndef DISABLE_OUTLINE
00146 delete outline;
00147 #endif
00148 delete catalog;
00149 delete xref;
00150 delete str;
00151 if (file) {
00152 fclose(file);
00153 }
00154 delete fileName;
00155 delete links;
00156 }
00157
00158
00159
00160 void PDFDoc::checkHeader() {
00161 char hdrBuf[headerSearchSize+1];
00162 char *p;
00163 int i;
00164
00165 pdfVersion = 0;
00166 for (i = 0; i < headerSearchSize; ++i) {
00167 hdrBuf[i] = str->getChar();
00168 }
00169 hdrBuf[headerSearchSize] = '\0';
00170 for (i = 0; i < headerSearchSize - 5; ++i) {
00171 if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
00172 break;
00173 }
00174 }
00175 if (i >= headerSearchSize - 5) {
00176 error(-1, "May not be a PDF file (continuing anyway)");
00177 return;
00178 }
00179 str->moveStart(i);
00180 p = strtok(&hdrBuf[i+5], " \t\n\r");
00181 pdfVersion = atof(p);
00182 if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
00183 pdfVersion > supportedPDFVersionNum + 0.0001) {
00184 error(-1, "PDF version %s -- xpdf supports version %s"
00185 " (continuing anyway)", p, supportedPDFVersionStr);
00186 }
00187 }
00188
00189 void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
00190 int rotate, GBool doLinks,
00191 GBool (*abortCheckCbk)(void *data),
00192 void *abortCheckCbkData) {
00193 Page *p;
00194
00195 if (globalParams->getPrintCommands()) {
00196 printf("***** page %d *****\n", page);
00197 }
00198 p = catalog->getPage(page);
00199 if (doLinks) {
00200 if (links) {
00201 delete links;
00202 }
00203 getLinks(p);
00204 p->display(out, zoom, rotate, links, catalog,
00205 abortCheckCbk, abortCheckCbkData);
00206 } else {
00207 p->display(out, zoom, rotate, NULL, catalog,
00208 abortCheckCbk, abortCheckCbkData);
00209 }
00210 }
00211
00212 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
00213 int zoom, int rotate, GBool doLinks,
00214 GBool (*abortCheckCbk)(void *data),
00215 void *abortCheckCbkData) {
00216 int page;
00217
00218 for (page = firstPage; page <= lastPage; ++page) {
00219 displayPage(out, page, zoom, rotate, doLinks,
00220 abortCheckCbk, abortCheckCbkData);
00221 }
00222 }
00223
00224 void PDFDoc::displayPageSlice(OutputDev *out, int page, double zoom,
00225 int rotate, int sliceX, int sliceY,
00226 int sliceW, int sliceH,
00227 GBool (*abortCheckCbk)(void *data),
00228 void *abortCheckCbkData) {
00229 Page *p;
00230
00231 p = catalog->getPage(page);
00232 p->displaySlice(out, zoom, rotate, sliceX, sliceY, sliceW, sliceH,
00233 NULL, catalog, abortCheckCbk, abortCheckCbkData);
00234 }
00235
00236 GBool PDFDoc::isLinearized() {
00237 Parser *parser;
00238 Object obj1, obj2, obj3, obj4, obj5;
00239 GBool lin;
00240
00241 lin = gFalse;
00242 obj1.initNull();
00243 parser = new Parser(xref,
00244 new Lexer(xref,
00245 str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
00246 parser->getObj(&obj1);
00247 parser->getObj(&obj2);
00248 parser->getObj(&obj3);
00249 parser->getObj(&obj4);
00250 if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
00251 obj4.isDict()) {
00252 obj4.dictLookup("Linearized", &obj5);
00253 if (obj5.isNum() && obj5.getNum() > 0) {
00254 lin = gTrue;
00255 }
00256 obj5.free();
00257 }
00258 obj4.free();
00259 obj3.free();
00260 obj2.free();
00261 obj1.free();
00262 delete parser;
00263 return lin;
00264 }
00265
00266 GBool PDFDoc::saveAs(GString *name) {
00267 FILE *f;
00268 int c;
00269
00270 if (!(f = fopen(name->getCString(), "wb"))) {
00271 error(-1, "Couldn't open file '%s'", name->getCString());
00272 return gFalse;
00273 }
00274 str->reset();
00275 while ((c = str->getChar()) != EOF) {
00276 fputc(c, f);
00277 }
00278 str->close();
00279 fclose(f);
00280 return gTrue;
00281 }
00282
00283 void PDFDoc::getLinks(Page *page) {
00284 Object obj;
00285
00286 links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
00287 obj.free();
00288 }