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