? 01-xpdf-3.00pl1.patch ? 02-xpdf-3.00pl2.patch ? 03-xpdf-3.00pl3.patch ? 10-xpdf-3.01-docs.patch ? 11-xpdf-3.01-fixedpoint.patch ? 12-xpdf-3.01-no-no-decryption.patch ? 13-xpdf-3.01-goo-allocn.patch ? 14-xpdf-3.01-copyright-etc-updates.patch ? 15-xpdf-3.01-new-freetype.patch ? 16-xpdf-3.01-plugins.patch ? poppler/SecurityHandler.cc ? poppler/SecurityHandler.h ? poppler/XpdfPluginAPI.cc ? poppler/XpdfPluginAPI.h ? poppler/patches Index: poppler/DCTStream.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/DCTStream.h,v retrieving revision 1.4 diff -u -r1.4 DCTStream.h --- poppler/DCTStream.h 1 Aug 2005 19:15:40 -0000 1.4 +++ poppler/DCTStream.h 15 Sep 2005 12:59:51 -0000 @@ -32,9 +32,7 @@ #include "poppler-config.h" #include "Error.h" #include "Object.h" -#ifndef NO_DECRYPTION #include "Decrypt.h" -#endif #include "Stream.h" extern "C" { Index: poppler/Decrypt.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Decrypt.cc,v retrieving revision 1.2 diff -u -r1.2 Decrypt.cc --- poppler/Decrypt.cc 28 Aug 2005 09:43:18 -0000 1.2 +++ poppler/Decrypt.cc 15 Sep 2005 12:59:52 -0000 @@ -66,7 +66,8 @@ GooString *ownerKey, GooString *userKey, int permissions, GooString *fileID, GooString *ownerPassword, GooString *userPassword, - Guchar *fileKey, GBool *ownerPasswordOk) { + Guchar *fileKey, GBool encryptMetadata, + GBool *ownerPasswordOk) { Guchar test[32], test2[32]; GooString *userPassword2; Guchar fState[256]; @@ -111,7 +112,8 @@ } userPassword2 = new GooString((char *)test2, 32); if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, - permissions, fileID, userPassword2, fileKey)) { + permissions, fileID, userPassword2, fileKey, + encryptMetadata)) { *ownerPasswordOk = gTrue; delete userPassword2; return gTrue; @@ -121,13 +123,15 @@ // try using the supplied user password return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, - permissions, fileID, userPassword, fileKey); + permissions, fileID, userPassword, fileKey, + encryptMetadata); } GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, GooString *ownerKey, GooString *userKey, int permissions, GooString *fileID, - GooString *userPassword, Guchar *fileKey) { + GooString *userPassword, Guchar *fileKey, + GBool encryptMetadata) { Guchar *buf; Guchar test[32]; Guchar fState[256]; @@ -137,7 +141,7 @@ GBool ok; // generate file key - buf = (Guchar *)gmalloc(68 + fileID->getLength()); + buf = (Guchar *)gmalloc(72 + fileID->getLength()); if (userPassword) { len = userPassword->getLength(); if (len < 32) { @@ -155,7 +159,14 @@ buf[66] = (permissions >> 16) & 0xff; buf[67] = (permissions >> 24) & 0xff; memcpy(buf + 68, fileID->getCString(), fileID->getLength()); - md5(buf, 68 + fileID->getLength(), fileKey); + len = 68 + fileID->getLength(); + if (!encryptMetadata) { + buf[len++] = 0xff; + buf[len++] = 0xff; + buf[len++] = 0xff; + buf[len++] = 0xff; + } + md5(buf, len, fileKey); if (encRevision == 3) { for (i = 0; i < 50; ++i) { md5(fileKey, keyLength, fileKey); Index: poppler/Decrypt.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Decrypt.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 Decrypt.h --- poppler/Decrypt.h 3 Mar 2005 19:46:00 -0000 1.1.1.1 +++ poppler/Decrypt.h 15 Sep 2005 12:59:53 -0000 @@ -41,14 +41,16 @@ GooString *ownerKey, GooString *userKey, int permissions, GooString *fileID, GooString *ownerPassword, GooString *userPassword, - Guchar *fileKey, GBool *ownerPasswordOk); + Guchar *fileKey, GBool encryptMetadata, + GBool *ownerPasswordOk); private: static GBool makeFileKey2(int encVersion, int encRevision, int keyLength, GooString *ownerKey, GooString *userKey, int permissions, GooString *fileID, - GooString *userPassword, Guchar *fileKey); + GooString *userPassword, Guchar *fileKey, + GBool encryptMetadata); int objKeyLength; Guchar objKey[21]; Index: poppler/FlateStream.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/FlateStream.h,v retrieving revision 1.1 diff -u -r1.1 FlateStream.h --- poppler/FlateStream.h 27 Apr 2005 20:56:18 -0000 1.1 +++ poppler/FlateStream.h 15 Sep 2005 12:59:53 -0000 @@ -32,9 +32,7 @@ #include "poppler-config.h" #include "Error.h" #include "Object.h" -#ifndef NO_DECRYPTION #include "Decrypt.h" -#endif #include "Stream.h" extern "C" { Index: poppler/GlobalParams.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/GlobalParams.cc,v retrieving revision 1.8 diff -u -r1.8 GlobalParams.cc --- poppler/GlobalParams.cc 23 Aug 2005 18:20:45 -0000 1.8 +++ poppler/GlobalParams.cc 15 Sep 2005 13:00:03 -0000 @@ -15,6 +15,14 @@ #include #include #include +#ifdef ENABLE_PLUGINS +# ifndef WIN32 +# include +# endif +#endif +#ifdef WIN32 +# include +#endif #if HAVE_PAPER_H #include #endif @@ -31,6 +39,9 @@ #include "CMap.h" #include "BuiltinFontTables.h" #include "FontEncodingTables.h" +#ifdef ENABLE_PLUGINS +# include "XpdfPluginAPI.h" +#endif #include "GlobalParams.h" #include "GfxFont.h" @@ -58,6 +69,12 @@ #include "UnicodeMapTables.h" #include "UTF8.h" +#ifdef ENABLE_PLUGINS +# ifdef WIN32 +extern XpdfPluginVecTable xpdfPluginVecTable; +# endif +#endif + //------------------------------------------------------------------------ #define cidToUnicodeCacheSize 4 @@ -121,6 +138,148 @@ } } +#ifdef ENABLE_PLUGINS +//------------------------------------------------------------------------ +// Plugin +//------------------------------------------------------------------------ + +class Plugin { +public: + + static Plugin *load(char *type, char *name); + ~Plugin(); + +private: + +#ifdef WIN32 + Plugin(HMODULE libA); + HMODULE lib; +#else + Plugin(void *dlA); + void *dl; +#endif +}; + +Plugin *Plugin::load(char *type, char *name) { + GString *path; + Plugin *plugin; + XpdfPluginVecTable *vt; + XpdfBool (*xpdfInitPlugin)(void); +#ifdef WIN32 + HMODULE libA; +#else + void *dlA; +#endif + + path = globalParams->getBaseDir(); + appendToPath(path, "plugins"); + appendToPath(path, type); + appendToPath(path, name); + +#ifdef WIN32 + path->append(".dll"); + if (!(libA = LoadLibrary(path->getCString()))) { + error(-1, "Failed to load plugin '%s'", + path->getCString()); + goto err1; + } + if (!(vt = (XpdfPluginVecTable *) + GetProcAddress(libA, "xpdfPluginVecTable"))) { + error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", + path->getCString()); + goto err2; + } +#else + //~ need to deal with other extensions here + path->append(".so"); + if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) { + error(-1, "Failed to load plugin '%s': %s", + path->getCString(), dlerror()); + goto err1; + } + if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) { + error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", + path->getCString()); + goto err2; + } +#endif + + if (vt->version != xpdfPluginVecTable.version) { + error(-1, "Plugin '%s' is wrong version", path->getCString()); + goto err2; + } + memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable)); + +#ifdef WIN32 + if (!(xpdfInitPlugin = (XpdfBool (*)(void)) + GetProcAddress(libA, "xpdfInitPlugin"))) { + error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", + path->getCString()); + goto err2; + } +#else + if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) { + error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", + path->getCString()); + goto err2; + } +#endif + + if (!(*xpdfInitPlugin)()) { + error(-1, "Initialization of plugin '%s' failed", + path->getCString()); + goto err2; + } + +#ifdef WIN32 + plugin = new Plugin(libA); +#else + plugin = new Plugin(dlA); +#endif + + delete path; + return plugin; + + err2: +#ifdef WIN32 + FreeLibrary(libA); +#else + dlclose(dlA); +#endif + err1: + delete path; + return NULL; +} + +#ifdef WIN32 +Plugin::Plugin(HMODULE libA) { + lib = libA; +} +#else +Plugin::Plugin(void *dlA) { + dl = dlA; +} +#endif + +Plugin::~Plugin() { + void (*xpdfFreePlugin)(void); + +#ifdef WIN32 + if ((xpdfFreePlugin = (void (*)(void)) + GetProcAddress(lib, "xpdfFreePlugin"))) { + (*xpdfFreePlugin)(); + } + FreeLibrary(lib); +#else + if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) { + (*xpdfFreePlugin)(); + } + dlclose(dl); +#endif +} + +#endif // ENABLE_PLUGINS + //------------------------------------------------------------------------ // parsing //------------------------------------------------------------------------ @@ -224,6 +383,11 @@ unicodeMapCache = new UnicodeMapCache(); cMapCache = new CMapCache(); +#ifdef ENABLE_PLUGINS + plugins = new GList(); + securityHandlers = new GList(); +#endif + // set up the initial nameToUnicode table for (i = 0; nameToUnicodeTab[i].name; ++i) { nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u); @@ -816,6 +980,11 @@ delete unicodeMapCache; delete cMapCache; +#ifdef ENABLE_PLUGINS + delete securityHandlers; + deleteGList(plugins, Plugin); +#endif + #if MULTITHREADED gDestroyMutex(&mutex); gDestroyMutex(&unicodeMapCacheMutex); @@ -1741,3 +1910,63 @@ errQuiet = errQuietA; unlockGlobalParams; } + +void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) { +#ifdef ENABLE_PLUGINS + lockGlobalParams; + securityHandlers->append(handler); + unlockGlobalParams; +#endif +} + +XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) { +#ifdef ENABLE_PLUGINS + XpdfSecurityHandler *hdlr; + int i; + + lockGlobalParams; + for (i = 0; i < securityHandlers->getLength(); ++i) { + hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); + if (!stricmp(hdlr->name, name)) { + unlockGlobalParams; + return hdlr; + } + } + unlockGlobalParams; + + if (!loadPlugin("security", name)) { + return NULL; + } + + lockGlobalParams; + for (i = 0; i < securityHandlers->getLength(); ++i) { + hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); + if (!strcmp(hdlr->name, name)) { + unlockGlobalParams; + return hdlr; + } + } + unlockGlobalParams; +#endif + + return NULL; +} + +#ifdef ENABLE_PLUGINS +//------------------------------------------------------------------------ +// plugins +//------------------------------------------------------------------------ + +GBool GlobalParams::loadPlugin(char *type, char *name) { + Plugin *plugin; + + if (!(plugin = Plugin::load(type, name))) { + return gFalse; + } + lockGlobalParams; + plugins->append(plugin); + unlockGlobalParams; + return gTrue; +} + +#endif // ENABLE_PLUGINS Index: poppler/GlobalParams.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/GlobalParams.h,v retrieving revision 1.3 diff -u -r1.3 GlobalParams.h --- poppler/GlobalParams.h 23 Aug 2005 18:20:45 -0000 1.3 +++ poppler/GlobalParams.h 15 Sep 2005 13:00:05 -0000 @@ -33,6 +33,7 @@ class UnicodeMapCache; class CMap; class CMapCache; +struct XpdfSecurityHandler; class GlobalParams; class GfxFont; @@ -165,6 +166,9 @@ UnicodeMap *getUnicodeMap(GooString *encodingName); CMap *getCMap(GooString *collection, GooString *cMapName); UnicodeMap *getTextEncoding(); +#ifdef ENABLE_PLUGINS + GBool loadPlugin(char *type, char *name); +#endif //----- functions to set parameters @@ -198,6 +202,11 @@ void setProfileCommands(GBool profileCommandsA); void setErrQuiet(GBool errQuietA); + //----- security handlers + + void addSecurityHandler(XpdfSecurityHandler *handler); + XpdfSecurityHandler *getSecurityHandler(char *name); + private: void parseFile(GooString *fileName, FILE *f); @@ -232,6 +241,7 @@ //----- user-modifiable settings + GooString *baseDir; // base directory - for plugins, etc. NameToCharCode * // mapping from char name to Unicode nameToUnicode; GooHash *cidToUnicodes; // files for mappings from char collections @@ -296,6 +306,12 @@ FcConfig *FCcfg; +#ifdef ENABLE_PLUGINS + GList *plugins; // list of plugins [Plugin] + GList *securityHandlers; // list of loaded security handlers + // [XpdfSecurityHandler] +#endif + #if MULTITHREADED GooMutex mutex; GooMutex unicodeMapCacheMutex; Index: poppler/Makefile.am =================================================================== RCS file: /cvs/poppler/poppler/poppler/Makefile.am,v retrieving revision 1.11 diff -u -r1.11 Makefile.am --- poppler/Makefile.am 23 Aug 2005 18:20:45 -0000 1.11 +++ poppler/Makefile.am 15 Sep 2005 13:00:05 -0000 @@ -74,6 +74,7 @@ INCLUDES = \ -I$(top_srcdir) \ + -I$(top_srcdir)/goo \ $(splash_includes) \ $(cairo_includes) \ $(arthur_includes) \ @@ -142,6 +143,7 @@ NameToUnicodeTable.h \ PSOutputDev.h \ TextOutputDev.h \ + SecurityHandler.h \ UTF8.h \ poppler-config.h @@ -190,4 +192,5 @@ PSOutputDev.cc \ TextOutputDev.cc \ PageLabelInfo.h \ - PageLabelInfo.cc + PageLabelInfo.cc \ + SecurityHandler.cc Index: poppler/PDFDoc.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.cc,v retrieving revision 1.5 diff -u -r1.5 PDFDoc.cc --- poppler/PDFDoc.cc 7 Aug 2005 23:58:12 -0000 1.5 +++ poppler/PDFDoc.cc 15 Sep 2005 13:00:05 -0000 @@ -30,6 +30,7 @@ #include "ErrorCodes.h" #include "Lexer.h" #include "Parser.h" +#include "SecurityHandler.h" #ifndef DISABLE_OUTLINE #include "Outline.h" #endif @@ -244,6 +245,41 @@ } } +GBool PDFDoc::checkEncryption(GooString *ownerPassword, GooString *userPassword) { + Object encrypt; + GBool encrypted; + SecurityHandler *secHdlr; + GBool ret; + + xref->getTrailerDict()->dictLookup("Encrypt", &encrypt); + if ((encrypted = encrypt.isDict())) { + if ((secHdlr = SecurityHandler::make(this, &encrypt))) { + if (secHdlr->checkEncryption(ownerPassword, userPassword)) { + // authorization succeeded + xref->setEncryption(secHdlr->getPermissionFlags(), + secHdlr->getOwnerPasswordOk(), + secHdlr->getFileKey(), + secHdlr->getFileKeyLength(), + secHdlr->getEncVersion(), + secHdlr->getEncRevision()); + ret = gTrue; + } else { + // authorization failed + ret = gFalse; + } + delete secHdlr; + } else { + // couldn't find the matching security handler + ret = gFalse; + } + } else { + // document is not encrypted + ret = gTrue; + } + encrypt.free(); + return ret; +} + void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI, int rotate, GBool crop, GBool doLinks, GBool (*abortCheckCbk)(void *data), Index: poppler/PDFDoc.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/PDFDoc.h,v retrieving revision 1.3 diff -u -r1.3 PDFDoc.h --- poppler/PDFDoc.h 6 Jul 2005 13:29:00 -0000 1.3 +++ poppler/PDFDoc.h 15 Sep 2005 13:00:06 -0000 @@ -166,6 +166,7 @@ GBool setup(GooString *ownerPassword, GooString *userPassword); GBool checkFooter(); void checkHeader(); + GBool checkEncryption(GooString *ownerPassword, GooString *userPassword); void getLinks(Page *page); GooString *fileName; Index: poppler/Parser.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Parser.cc,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 Parser.cc --- poppler/Parser.cc 3 Mar 2005 19:46:03 -0000 1.1.1.1 +++ poppler/Parser.cc 15 Sep 2005 13:00:06 -0000 @@ -19,9 +19,7 @@ #include "Parser.h" #include "XRef.h" #include "Error.h" -#ifndef NO_DECRYPTION #include "Decrypt.h" -#endif Parser::Parser(XRef *xrefA, Lexer *lexerA) { xref = xrefA; @@ -37,23 +35,17 @@ delete lexer; } -#ifndef NO_DECRYPTION Object *Parser::getObj(Object *obj, Guchar *fileKey, int keyLength, int objNum, int objGen) { -#else -Object *Parser::getObj(Object *obj) { -#endif char *key; Stream *str; Object obj2; int num; -#ifndef NO_DECRYPTION Decrypt *decrypt; GooString *s; char *p; int i; -#endif // refill buffer after inline image data if (inlineImg == 2) { @@ -69,11 +61,7 @@ shift(); obj->initArray(xref); while (!buf1.isCmd("]") && !buf1.isEOF()) -#ifndef NO_DECRYPTION obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen)); -#else - obj->arrayAdd(getObj(&obj2)); -#endif if (buf1.isEOF()) error(getPos(), "End of file inside array"); shift(); @@ -93,11 +81,7 @@ gfree(key); break; } -#ifndef NO_DECRYPTION obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen)); -#else - obj->dictAdd(key, getObj(&obj2)); -#endif } } if (buf1.isEOF()) @@ -105,12 +89,10 @@ if (buf2.isCmd("stream")) { if ((str = makeStream(obj))) { obj->initStream(str); -#ifndef NO_DECRYPTION if (fileKey) { str->getBaseStream()->doDecryption(fileKey, keyLength, objNum, objGen); } -#endif } else { obj->free(); obj->initError(); @@ -131,7 +113,6 @@ obj->initInt(num); } -#ifndef NO_DECRYPTION // string } else if (buf1.isString() && fileKey) { buf1.copy(obj); @@ -144,7 +125,6 @@ } delete decrypt; shift(); -#endif // simple object } else { Index: poppler/Parser.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Parser.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 Parser.h --- poppler/Parser.h 3 Mar 2005 19:46:01 -0000 1.1.1.1 +++ poppler/Parser.h 15 Sep 2005 13:00:06 -0000 @@ -29,13 +29,9 @@ ~Parser(); // Get the next object from the input stream. -#ifndef NO_DECRYPTION Object *getObj(Object *obj, Guchar *fileKey = NULL, int keyLength = 0, int objNum = 0, int objGen = 0); -#else - Object *getObj(Object *obj); -#endif // Get stream. Stream *getStream() { return lexer->getStream(); } Index: poppler/Stream.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/Stream.cc,v retrieving revision 1.4 diff -u -r1.4 Stream.cc --- poppler/Stream.cc 27 Aug 2005 08:43:43 -0000 1.4 +++ poppler/Stream.cc 15 Sep 2005 13:00:19 -0000 @@ -25,9 +25,7 @@ #include "poppler-config.h" #include "Error.h" #include "Object.h" -#ifndef NO_DECRYPTION #include "Decrypt.h" -#endif #include "Stream.h" #include "JBIG2Stream.h" #include "JPXStream.h" @@ -280,25 +278,19 @@ BaseStream::BaseStream(Object *dictA) { dict = *dictA; -#ifndef NO_DECRYPTION decrypt = NULL; -#endif } BaseStream::~BaseStream() { dict.free(); -#ifndef NO_DECRYPTION if (decrypt) delete decrypt; -#endif } -#ifndef NO_DECRYPTION void BaseStream::doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen) { decrypt = new Decrypt(fileKey, keyLength, objNum, objGen); } -#endif //------------------------------------------------------------------------ // FilterStream @@ -604,10 +596,8 @@ saved = gTrue; bufPtr = bufEnd = buf; bufPos = start; -#ifndef NO_DECRYPTION if (decrypt) decrypt->reset(); -#endif } void FileStream::close() { @@ -625,9 +615,7 @@ GBool FileStream::fillBuf() { int n; -#ifndef NO_DECRYPTION char *p; -#endif bufPos += bufEnd - buf; bufPtr = bufEnd = buf; @@ -644,13 +632,11 @@ if (bufPtr >= bufEnd) { return gFalse; } -#ifndef NO_DECRYPTION if (decrypt) { for (p = buf; p < bufEnd; ++p) { *p = (char)decrypt->decryptByte((Guchar)*p); } } -#endif return gTrue; } @@ -739,11 +725,9 @@ void MemStream::reset() { bufPtr = buf + start; -#ifndef NO_DECRYPTION if (decrypt) { decrypt->reset(); } -#endif } void MemStream::close() { @@ -770,7 +754,6 @@ bufPtr = buf + start; } -#ifndef NO_DECRYPTION void MemStream::doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen) { char *newBuf; @@ -789,7 +772,6 @@ needFree = gTrue; } } -#endif //------------------------------------------------------------------------ // EmbedStream Index: poppler/Stream.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/Stream.h,v retrieving revision 1.4 diff -u -r1.4 Stream.h --- poppler/Stream.h 31 Aug 2005 15:28:46 -0000 1.4 +++ poppler/Stream.h 15 Sep 2005 13:00:21 -0000 @@ -17,9 +17,7 @@ #include "goo/gtypes.h" #include "Object.h" -#ifndef NO_DECRYPTION class Decrypt; -#endif class BaseStream; //------------------------------------------------------------------------ @@ -145,17 +143,13 @@ virtual Guint getStart() = 0; virtual void moveStart(int delta) = 0; -#ifndef NO_DECRYPTION // Set decryption for this stream. virtual void doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen); -#endif -#ifndef NO_DECRYPTION protected: Decrypt *decrypt; -#endif private: @@ -322,10 +316,8 @@ virtual void setPos(Guint pos, int dir = 0); virtual Guint getStart() { return start; } virtual void moveStart(int delta); -#ifndef NO_DECRYPTION virtual void doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen); -#endif private: Index: poppler/XRef.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/XRef.cc,v retrieving revision 1.4 diff -u -r1.4 XRef.cc --- poppler/XRef.cc 27 Aug 2005 08:43:43 -0000 1.4 +++ poppler/XRef.cc 15 Sep 2005 13:00:22 -0000 @@ -22,9 +22,7 @@ #include "Lexer.h" #include "Parser.h" #include "Dict.h" -#ifndef NO_DECRYPTION #include "Decrypt.h" -#endif #include "Error.h" #include "ErrorCodes.h" #include "XRef.h" @@ -34,7 +32,6 @@ #define xrefSearchSize 1024 // read this many bytes at end of file // to look for 'startxref' -#ifndef NO_DECRYPTION //------------------------------------------------------------------------ // Permission bits // Note that the PDF spec uses 1 base (eg bit 3 is 1<<2) @@ -49,7 +46,6 @@ #define permAssemble (1<<10) // bit 11 #define permHighResPrint (1<<11) // bit 12 #define defPermFlags 0xfffc -#endif //------------------------------------------------------------------------ // ObjectStream @@ -263,9 +259,7 @@ trailerDict.getDict()->setXRef(this); // check for encryption -#ifndef NO_DECRYPTION encrypted = gFalse; -#endif if (checkEncrypted(ownerPassword, userPassword)) { ok = gFalse; errCode = errEncrypted; @@ -786,129 +780,34 @@ return gFalse; } -#ifndef NO_DECRYPTION -GBool XRef::checkEncrypted(GooString *ownerPassword, GooString *userPassword) { - Object encrypt, filterObj, versionObj, revisionObj, lengthObj; - Object ownerKey, userKey, permissions, fileID, fileID1; - GBool encrypted1; - GBool ret; - - keyLength = 0; - encVersion = encRevision = 0; - ret = gFalse; - - permFlags = defPermFlags; - ownerPasswordOk = gFalse; - trailerDict.dictLookup("Encrypt", &encrypt); - if ((encrypted1 = encrypt.isDict())) { - ret = gTrue; - encrypt.dictLookup("Filter", &filterObj); - if (filterObj.isName("Standard")) { - encrypt.dictLookup("V", &versionObj); - encrypt.dictLookup("R", &revisionObj); - encrypt.dictLookup("Length", &lengthObj); - encrypt.dictLookup("O", &ownerKey); - encrypt.dictLookup("U", &userKey); - encrypt.dictLookup("P", &permissions); - trailerDict.dictLookup("ID", &fileID); - if (versionObj.isInt() && - revisionObj.isInt() && - ownerKey.isString() && ownerKey.getString()->getLength() == 32 && - userKey.isString() && userKey.getString()->getLength() == 32 && - permissions.isInt() && - fileID.isArray()) { - encVersion = versionObj.getInt(); - encRevision = revisionObj.getInt(); - if (lengthObj.isInt()) { - keyLength = lengthObj.getInt() / 8; - } else { - keyLength = 5; - } - if (keyLength > 16) { - keyLength = 16; - } - /* special case for revision 2. - * See Algorithm 3.2 step 9 from PDF Reference, fifth edition.*/ - if (encRevision == 2) { - keyLength = 5; - } +void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA, + Guchar *fileKeyA, int keyLengthA, + int encVersionA, int encRevisionA) { + int i; - permFlags = permissions.getInt(); - if (encVersion >= 1 && encVersion <= 2 && - encRevision >= 2 && encRevision <= 3) { - fileID.arrayGet(0, &fileID1); - if (fileID1.isString()) { - if (Decrypt::makeFileKey(encVersion, encRevision, keyLength, - ownerKey.getString(), userKey.getString(), - permFlags, fileID1.getString(), - ownerPassword, userPassword, fileKey, - &ownerPasswordOk)) { - if (ownerPassword && !ownerPasswordOk) { - error(-1, "Incorrect owner password"); - } - ret = gFalse; - } else { - error(-1, "Incorrect password"); - } - } else { - error(-1, "Weird encryption info"); - } - fileID1.free(); - } else { - error(-1, "Unsupported version/revision (%d/%d) of Standard security handler", - encVersion, encRevision); - } - } else { - error(-1, "Weird encryption info"); - } - fileID.free(); - permissions.free(); - userKey.free(); - ownerKey.free(); - lengthObj.free(); - revisionObj.free(); - versionObj.free(); - } else { - error(-1, "Unknown security handler '%s'", - filterObj.isName() ? filterObj.getName() : "???"); - } - filterObj.free(); + encrypted = gTrue; + permFlags = permFlagsA; + ownerPasswordOk = ownerPasswordOkA; + if (keyLengthA <= 16) { + keyLength = keyLengthA; + } else { + keyLength = 16; } - encrypt.free(); - - // this flag has to be set *after* we read the O/U/P strings - encrypted = encrypted1; - - return ret; -} -#else -GBool XRef::checkEncrypted(GooString *ownerPassword, GooString *userPassword) { - Object obj; - GBool encrypted; - - trailerDict.dictLookup("Encrypt", &obj); - if ((encrypted = !obj.isNull())) { - error(-1, "PDF file is encrypted and this version of the Xpdf tools"); - error(-1, "was built without decryption support."); + for (i = 0; i < keyLength; ++i) { + fileKey[i] = fileKeyA[i]; } - obj.free(); - return encrypted; + encVersion = encVersionA; + encRevision = encRevisionA; } -#endif GBool XRef::okToPrint(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint); -#else - return gTrue; -#endif } // we can print at high res if we are only doing security handler revision // 2 (and we are allowed to print at all), or with security handler rev // 3 and we are allowed to print, and bit 12 is set. GBool XRef::okToPrintHighRes(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION if (2 == encRevision) { return (okToPrint(ignoreOwnerPW)); } else if (encRevision >= 3) { @@ -917,57 +816,30 @@ // something weird - unknown security handler version return gFalse; } -#else - return gTrue; -#endif } GBool XRef::okToChange(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange); -#else - return gTrue; -#endif } GBool XRef::okToCopy(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy); -#else - return gTrue; -#endif } GBool XRef::okToAddNotes(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes); -#else - return gTrue; -#endif } GBool XRef::okToFillForm(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permFillForm); -#else - return gTrue; -#endif } GBool XRef::okToAccessibility(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permAccessibility); -#else - return gTrue; -#endif } GBool XRef::okToAssemble(GBool ignoreOwnerPW) { -#ifndef NO_DECRYPTION return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permAssemble); -#else - return gTrue; -#endif } Object *XRef::fetch(int num, int gen, Object *obj) { @@ -999,12 +871,8 @@ !obj3.isCmd("obj")) { goto err; } -#ifndef NO_DECRYPTION parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength, num, gen); -#else - parser->getObj(obj); -#endif obj1.free(); obj2.free(); obj3.free(); Index: poppler/XRef.h =================================================================== RCS file: /cvs/poppler/poppler/poppler/XRef.h,v retrieving revision 1.2 diff -u -r1.2 XRef.h --- poppler/XRef.h 5 Jul 2005 12:15:04 -0000 1.2 +++ poppler/XRef.h 15 Sep 2005 13:00:23 -0000 @@ -52,12 +52,13 @@ // Get the error code (if isOk() returns false). int getErrorCode() { return errCode; } + // Set the encryption parameters. + void setEncryption(int permFlagsA, GBool ownerPasswordOkA, + Guchar *fileKeyA, int keyLengthA, + int encVersionA, int encRevisionA); + // Is the file encrypted? -#ifndef NO_DECRYPTION GBool isEncrypted() { return encrypted; } -#else - GBool isEncrypted() { return gFalse; } -#endif // Check various permissions. GBool okToPrint(GBool ignoreOwnerPW = gFalse); @@ -114,15 +115,13 @@ // damaged files int streamEndsLen; // number of valid entries in streamEnds ObjectStream *objStr; // cached object stream -#ifndef NO_DECRYPTION GBool encrypted; // true if file is encrypted + int encRevision; int encVersion; // encryption algorithm - int encRevision; // security handler revision int keyLength; // length of key, in bytes int permFlags; // permission bits Guchar fileKey[16]; // file decryption key GBool ownerPasswordOk; // true if owner password is correct -#endif Guint getStartXref(); GBool readXRef(Guint *pos); Index: poppler/poppler-config.h.in =================================================================== RCS file: /cvs/poppler/poppler/poppler/poppler-config.h.in,v retrieving revision 1.2 diff -u -r1.2 poppler-config.h.in --- poppler/poppler-config.h.in 28 Jul 2005 06:31:57 -0000 1.2 +++ poppler/poppler-config.h.in 15 Sep 2005 13:00:23 -0000 @@ -41,8 +41,6 @@ // Also, there's a couple of preprocessor symbols in the header files // that are used but never defined: DISABLE_OUTLINE, DEBUG_MEM and -// NO_DECRYPTION. We might want to explicitly #undef these to make -// sure we don't get spurious API or ABI incompatibilities. //------------------------------------------------------------------------ // version --- /dev/null 2005-09-15 11:24:01.334625920 +0200 +++ poppler/SecurityHandler.h 2005-09-15 13:11:56.000000000 +0200 @@ -0,0 +1,157 @@ +//======================================================================== +// +// SecurityHandler.h +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SECURITYHANDLER_H +#define SECURITYHANDLER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class GooString; +class PDFDoc; +struct XpdfSecurityHandler; + +//------------------------------------------------------------------------ +// SecurityHandler +//------------------------------------------------------------------------ + +class SecurityHandler { +public: + + static SecurityHandler *make(PDFDoc *docA, Object *encryptDictA); + + SecurityHandler(PDFDoc *docA); + virtual ~SecurityHandler(); + + // Check the document's encryption. If the document is encrypted, + // this will first try and (in + // "batch" mode), and if those fail, it will attempt to request a + // password from the user. This is the high-level function that + // calls the lower level functions for the specific security handler + // (requesting a password three times, etc.). Returns true if the + // document can be opened (if it's unencrypted, or if a correct + // password is obtained); false otherwise (encrypted and no correct + // password). + GBool checkEncryption(GooString *ownerPassword, + GooString *userPassword); + + // Create authorization data for the specified owner and user + // passwords. If the security handler doesn't support "batch" mode, + // this function should return NULL. + virtual void *makeAuthData(GooString *ownerPassword, + GooString *userPassword) = 0; + + // Construct authorization data, typically by prompting the user for + // a password. Returns an authorization data object, or NULL to + // cancel. + virtual void *getAuthData() = 0; + + // Free the authorization data returned by makeAuthData or + // getAuthData. + virtual void freeAuthData(void *authData) = 0; + + // Attempt to authorize the document, using the supplied + // authorization data (which may be NULL). Returns true if + // successful (i.e., if at least the right to open the document was + // granted). + virtual GBool authorize(void *authData) = 0; + + // Return the various authorization parameters. These are only + // valid after authorize has returned true. + virtual int getPermissionFlags() = 0; + virtual GBool getOwnerPasswordOk() = 0; + virtual Guchar *getFileKey() = 0; + virtual int getFileKeyLength() = 0; + virtual int getEncVersion() = 0; + virtual int getEncRevision() = 0; + +protected: + + PDFDoc *doc; +}; + +//------------------------------------------------------------------------ +// StandardSecurityHandler +//------------------------------------------------------------------------ + +class StandardSecurityHandler: public SecurityHandler { +public: + + StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA); + virtual ~StandardSecurityHandler(); + + virtual void *makeAuthData(GooString *ownerPassword, + GooString *userPassword); + virtual void *getAuthData(); + virtual void freeAuthData(void *authData); + virtual GBool authorize(void *authData); + virtual int getPermissionFlags() { return permFlags; } + virtual GBool getOwnerPasswordOk() { return ownerPasswordOk; } + virtual Guchar *getFileKey() { return fileKey; } + virtual int getFileKeyLength() { return fileKeyLength; } + virtual int getEncVersion() { return encVersion; } + virtual int getEncRevision() { return encRevision; } + +private: + + int permFlags; + GBool ownerPasswordOk; + Guchar fileKey[16]; + int fileKeyLength; + int encVersion; + int encRevision; + GBool encryptMetadata; + + GooString *ownerKey, *userKey; + GooString *fileID; + GBool ok; +}; + +#ifdef ENABLE_PLUGINS +//------------------------------------------------------------------------ +// ExternalSecurityHandler +//------------------------------------------------------------------------ + +class ExternalSecurityHandler: public SecurityHandler { +public: + + ExternalSecurityHandler(PDFDoc *docA, Object *encryptDictA, + XpdfSecurityHandler *xshA); + virtual ~ExternalSecurityHandler(); + + virtual void *makeAuthData(GooString *ownerPassword, + GooString *userPassword); + virtual void *getAuthData(); + virtual void freeAuthData(void *authData); + virtual GBool authorize(void *authData); + virtual int getPermissionFlags() { return permFlags; } + virtual GBool getOwnerPasswordOk() { return gFalse; } + virtual Guchar *getFileKey() { return fileKey; } + virtual int getFileKeyLength() { return fileKeyLength; } + virtual int getEncVersion() { return encVersion; } + +private: + + Object encryptDict; + XpdfSecurityHandler *xsh; + void *docData; + int permFlags; + Guchar fileKey[16]; + int fileKeyLength; + int encVersion; + GBool ok; +}; +#endif // ENABLE_PLUGINS + +#endif --- /dev/null 2005-09-15 11:24:01.334625920 +0200 +++ poppler/SecurityHandler.cc 2005-09-15 12:58:30.000000000 +0200 @@ -0,0 +1,376 @@ +//======================================================================== +// +// SecurityHandler.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "GooString.h" +#include "PDFDoc.h" +#include "Decrypt.h" +#include "Error.h" +#include "GlobalParams.h" +#if HAVE_XPDFCORE +# include "XPDFCore.h" +#elif HAVE_WINPDFCORE +# include "WinPDFCore.h" +#endif +#ifdef ENABLE_PLUGINS +# include "XpdfPluginAPI.h" +#endif +#include "SecurityHandler.h" + +//------------------------------------------------------------------------ +// SecurityHandler +//------------------------------------------------------------------------ + +SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) { + Object filterObj; + SecurityHandler *secHdlr; + XpdfSecurityHandler *xsh; + + encryptDictA->dictLookup("Filter", &filterObj); + if (filterObj.isName("Standard")) { + secHdlr = new StandardSecurityHandler(docA, encryptDictA); + } else if (filterObj.isName()) { +#ifdef ENABLE_PLUGINS + if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) { + secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh); + } else { +#endif + error(-1, "Couldn't find the '%s' security handler", + filterObj.getName()); + secHdlr = NULL; +#ifdef ENABLE_PLUGINS + } +#endif + } else { + error(-1, "Missing or invalid 'Filter' entry in encryption dictionary"); + secHdlr = NULL; + } + filterObj.free(); + return secHdlr; +} + +SecurityHandler::SecurityHandler(PDFDoc *docA) { + doc = docA; +} + +SecurityHandler::~SecurityHandler() { +} + +GBool SecurityHandler::checkEncryption(GooString *ownerPassword, + GooString *userPassword) { + void *authData; + GBool ok; + int i; + + if (ownerPassword || userPassword) { + authData = makeAuthData(ownerPassword, userPassword); + } else { + authData = NULL; + } + ok = authorize(authData); + if (authData) { + freeAuthData(authData); + } + for (i = 0; !ok && i < 3; ++i) { + if (!(authData = getAuthData())) { + break; + } + ok = authorize(authData); + if (authData) { + freeAuthData(authData); + } + } + if (!ok) { + error(-1, "Incorrect password"); + } + return ok; +} + +//------------------------------------------------------------------------ +// StandardSecurityHandler +//------------------------------------------------------------------------ + +class StandardAuthData { +public: + + StandardAuthData(GooString *ownerPasswordA, GooString *userPasswordA) { + ownerPassword = ownerPasswordA; + userPassword = userPasswordA; + } + + ~StandardAuthData() { + if (ownerPassword) { + delete ownerPassword; + } + if (userPassword) { + delete userPassword; + } + } + + GooString *ownerPassword; + GooString *userPassword; +}; + +StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, + Object *encryptDictA): + SecurityHandler(docA) +{ + Object versionObj, revisionObj, lengthObj; + Object ownerKeyObj, userKeyObj, permObj, fileIDObj; + Object fileIDObj1; + Object cryptFiltersObj, streamFilterObj, stringFilterObj; + Object cryptFilterObj, cfmObj, cfLengthObj; + Object encryptMetadataObj; + + ok = gFalse; + fileID = NULL; + ownerKey = NULL; + userKey = NULL; + + encryptDictA->dictLookup("V", &versionObj); + encryptDictA->dictLookup("R", &revisionObj); + encryptDictA->dictLookup("Length", &lengthObj); + encryptDictA->dictLookup("O", &ownerKeyObj); + encryptDictA->dictLookup("U", &userKeyObj); + encryptDictA->dictLookup("P", &permObj); + doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj); + if (versionObj.isInt() && + revisionObj.isInt() && + ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 && + userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 && + permObj.isInt()) { + encVersion = versionObj.getInt(); + encRevision = revisionObj.getInt(); + // revision 2 forces a 40-bit key - some buggy PDF generators + // set the Length value incorrectly + if (encRevision == 2 || !lengthObj.isInt()) { + fileKeyLength = 5; + } else { + fileKeyLength = lengthObj.getInt() / 8; + } + encryptMetadata = gTrue; + //~ this currently only handles a subset of crypt filter functionality + if (encVersion == 4 && encRevision == 4) { + encryptDictA->dictLookup("CF", &cryptFiltersObj); + encryptDictA->dictLookup("StmF", &streamFilterObj); + encryptDictA->dictLookup("StrF", &stringFilterObj); + if (cryptFiltersObj.isDict() && + streamFilterObj.isName() && + stringFilterObj.isName() && + !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) { + if (cryptFiltersObj.dictLookup(streamFilterObj.getName(), + &cryptFilterObj)->isDict()) { + if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) { + encVersion = 2; + encRevision = 3; + if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) { + //~ according to the spec, this should be cfLengthObj / 8 + fileKeyLength = cfLengthObj.getInt(); + } + cfLengthObj.free(); + } + cfmObj.free(); + } + cryptFilterObj.free(); + } + stringFilterObj.free(); + streamFilterObj.free(); + cryptFiltersObj.free(); + if (encryptDictA->dictLookup("EncryptMetadata", + &encryptMetadataObj)->isBool()) { + encryptMetadata = encryptMetadataObj.getBool(); + } + encryptMetadataObj.free(); + } + permFlags = permObj.getInt(); + ownerKey = ownerKeyObj.getString()->copy(); + userKey = userKeyObj.getString()->copy(); + if (encVersion >= 1 && encVersion <= 2 && + encRevision >= 2 && encRevision <= 3) { + if (fileIDObj.isArray()) { + if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) { + fileID = fileIDObj1.getString()->copy(); + } else { + fileID = new GooString(); + } + fileIDObj1.free(); + } else { + fileID = new GooString(); + } + ok = gTrue; + } else { + error(-1, "Unsupported version/revision (%d/%d) of Standard security handler", + encVersion, encRevision); + } + } else { + error(-1, "Weird encryption info"); + } + if (fileKeyLength > 16) { + fileKeyLength = 16; + } + fileIDObj.free(); + permObj.free(); + userKeyObj.free(); + ownerKeyObj.free(); + lengthObj.free(); + revisionObj.free(); + versionObj.free(); +} + +StandardSecurityHandler::~StandardSecurityHandler() { + if (fileID) { + delete fileID; + } + if (ownerKey) { + delete ownerKey; + } + if (userKey) { + delete userKey; + } +} + +void *StandardSecurityHandler::makeAuthData(GooString *ownerPassword, + GooString *userPassword) { + return new StandardAuthData(ownerPassword ? ownerPassword->copy() + : (GooString *)NULL, + userPassword ? userPassword->copy() + : (GooString *)NULL); +} + +void *StandardSecurityHandler::getAuthData() { +#if HAVE_XPDFCORE + XPDFCore *core; + GooString *password; + + if (!(core = (XPDFCore *)doc->getGUIData()) || + !(password = core->getPassword())) { + return NULL; + } + return new StandardAuthData(password, password->copy()); +#elif HAVE_WINPDFCORE + WinPDFCore *core; + GooString *password; + + if (!(core = (WinPDFCore *)doc->getGUIData()) || + !(password = core->getPassword())) { + return NULL; + } + return new StandardAuthData(password, password->copy()); +#else + return NULL; +#endif +} + +void StandardSecurityHandler::freeAuthData(void *authData) { + delete (StandardAuthData *)authData; +} + +GBool StandardSecurityHandler::authorize(void *authData) { + GooString *ownerPassword, *userPassword; + + if (!ok) { + return gFalse; + } + if (authData) { + ownerPassword = ((StandardAuthData *)authData)->ownerPassword; + userPassword = ((StandardAuthData *)authData)->userPassword; + } else { + ownerPassword = NULL; + userPassword = NULL; + } + if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength, + ownerKey, userKey, permFlags, fileID, + ownerPassword, userPassword, fileKey, + encryptMetadata, &ownerPasswordOk)) { + return gFalse; + } + return gTrue; +} + +#ifdef ENABLE_PLUGINS + +//------------------------------------------------------------------------ +// ExternalSecurityHandler +//------------------------------------------------------------------------ + +ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA, + Object *encryptDictA, + XpdfSecurityHandler *xshA): + SecurityHandler(docA) +{ + encryptDictA->copy(&encryptDict); + xsh = xshA; + ok = gFalse; + + if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA, + (XpdfObject)encryptDictA, &docData)) { + return; + } + + ok = gTrue; +} + +ExternalSecurityHandler::~ExternalSecurityHandler() { + (*xsh->freeDoc)(xsh->handlerData, docData); + encryptDict.free(); +} + +void *ExternalSecurityHandler::makeAuthData(GooString *ownerPassword, + GooString *userPassword) { + char *opw, *upw; + void *authData; + + opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL; + upw = userPassword ? userPassword->getCString() : (char *)NULL; + if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) { + return NULL; + } + return authData; +} + +void *ExternalSecurityHandler::getAuthData() { + void *authData; + + if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) { + return NULL; + } + return authData; +} + +void ExternalSecurityHandler::freeAuthData(void *authData) { + (*xsh->freeAuthData)(xsh->handlerData, docData, authData); +} + +GBool ExternalSecurityHandler::authorize(void *authData) { + char *key; + int length; + + if (!ok) { + return gFalse; + } + permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData); + if (!(permFlags & xpdfPermissionOpen)) { + return gFalse; + } + if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) { + return gFalse; + } + if ((fileKeyLength = length) > 16) { + fileKeyLength = 16; + } + memcpy(fileKey, key, fileKeyLength); + (*xsh->freeKey)(xsh->handlerData, docData, key, length); + return gTrue; +} + +#endif // ENABLE_PLUGINS --- /dev/null 2005-09-15 11:24:01.334625920 +0200 +++ poppler/XpdfPluginAPI.cc 2005-09-15 12:43:52.000000000 +0200 @@ -0,0 +1,262 @@ +//======================================================================== +// +// XpdfPluginAPI.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include "aconf.h" + +#ifdef ENABLE_PLUGINS + +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "PDFDoc.h" +#ifdef WIN32 +#include "WinPDFCore.h" +#else +#include "XPDFCore.h" +#endif +#include "XpdfPluginAPI.h" + +//------------------------------------------------------------------------ + +//~ This should use a pool of Objects; change xpdfFreeObj to match. +static Object *allocObj() { + return (Object *)gmalloc(sizeof(Object)); +} + +//------------------------------------------------------------------------ +// Document access functions +//------------------------------------------------------------------------ + +XpdfObject _xpdfGetInfoDict(XpdfDoc doc) { + Object *obj; + + obj = allocObj(); + return (XpdfObject)((PDFDoc *)doc)->getDocInfo(obj); +} + +XpdfObject _xpdfGetCatalog(XpdfDoc doc) { + Object *obj; + + obj = allocObj(); + return (XpdfObject)((PDFDoc *)doc)->getXRef()->getCatalog(obj); +} + +#ifdef _WIN32 + +HWND _xpdfWin32GetWindow(XpdfDoc doc) { + WinPDFCore *core; + + if (!(core = (WinPDFCore *)((PDFDoc *)doc)->getGUIData())) { + return NULL; + } + return core->getDrawFrame(); +} + +#else + +Widget _xpdfXGetWindow(XpdfDoc doc) { + XPDFCore *core; + + if (!(core = (XPDFCore *)((PDFDoc *)doc)->getGUIData())) { + return NULL; + } + return core->getWidget(); +} + +#endif + +//------------------------------------------------------------------------ +// Object access functions. +//------------------------------------------------------------------------ + +XpdfBool _xpdfObjIsBool(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isBool(); +} + +XpdfBool _xpdfObjIsInt(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isInt(); +} + +XpdfBool _xpdfObjIsReal(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isReal(); +} + +XpdfBool _xpdfObjIsNumber(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isNum(); +} + +XpdfBool _xpdfObjIsString(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isString(); +} + +XpdfBool _xpdfObjIsName(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isName(); +} + +XpdfBool _xpdfObjIsNull(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isNull(); +} + +XpdfBool _xpdfObjIsArray(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isArray(); +} + +XpdfBool _xpdfObjIsDict(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isDict(); +} + +XpdfBool _xpdfObjIsStream(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isStream(); +} + +XpdfBool _xpdfObjIsRef(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isRef(); +} + +XpdfBool _xpdfBoolValue(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->getBool(); +} + +int _xpdfIntValue(XpdfObject obj) { + if (!((Object *)obj)->isInt()) { + return 0; + } + return ((Object *)obj)->getInt(); +} + +double _xpdfRealValue(XpdfObject obj) { + if (!((Object *)obj)->isReal()) { + return 0; + } + return ((Object *)obj)->getReal(); +} + +double _xpdfNumberValue(XpdfObject obj) { + if (!((Object *)obj)->isNum()) { + return 0; + } + return ((Object *)obj)->getNum(); +} + +int _xpdfStringLength(XpdfObject obj) { + if (!((Object *)obj)->isString()) { + return 0; + } + return ((Object *)obj)->getString()->getLength(); +} + +char *_xpdfStringValue(XpdfObject obj) { + if (!((Object *)obj)->isString()) { + return 0; + } + return ((Object *)obj)->getString()->getCString(); +} + +char *_xpdfNameValue(XpdfObject obj) { + if (!((Object *)obj)->isName()) { + return NULL; + } + return ((Object *)obj)->getName(); +} + +int _xpdfArrayLength(XpdfObject obj) { + if (!((Object *)obj)->isArray()) { + return 0; + } + return ((Object *)obj)->arrayGetLength(); +} + +XpdfObject _xpdfArrayGet(XpdfObject obj, int idx) { + Object *elem; + + elem = allocObj(); + if (!((Object *)obj)->isArray()) { + return (XpdfObject)elem->initNull(); + } + return (XpdfObject)((Object *)obj)->arrayGet(idx, elem); +} + +XpdfObject _xpdfDictGet(XpdfObject obj, char *key) { + Object *elem; + + elem = allocObj(); + if (!((Object *)obj)->isDict()) { + return (XpdfObject)elem->initNull(); + } + return (XpdfObject)((Object *)obj)->dictLookup(key, elem); +} + +void _xpdfFreeObj(XpdfObject obj) { + ((Object *)obj)->free(); + gfree(obj); +} + +//------------------------------------------------------------------------ +// Memory allocation functions +//------------------------------------------------------------------------ + +void *_xpdfMalloc(int size) { + return gmalloc(size); +} + +void *_xpdfRealloc(void *p, int size) { + return grealloc(p, size); +} + +void _xpdfFree(void *p) { + gfree(p); +} + +//------------------------------------------------------------------------ +// Security handlers +//------------------------------------------------------------------------ + +void _xpdfRegisterSecurityHandler(XpdfSecurityHandler *handler) { + if (handler->version <= xpdfPluginAPIVersion) { + globalParams->addSecurityHandler(handler); + } +} + +//------------------------------------------------------------------------ + +XpdfPluginVecTable xpdfPluginVecTable = { + xpdfPluginAPIVersion, + &_xpdfGetInfoDict, + &_xpdfGetCatalog, +#ifdef _WIN32 + &_xpdfWin32GetWindow, +#else + &_xpdfXGetWindow, +#endif + &_xpdfObjIsBool, + &_xpdfObjIsInt, + &_xpdfObjIsReal, + &_xpdfObjIsString, + &_xpdfObjIsName, + &_xpdfObjIsNull, + &_xpdfObjIsArray, + &_xpdfObjIsDict, + &_xpdfObjIsStream, + &_xpdfObjIsRef, + &_xpdfBoolValue, + &_xpdfIntValue, + &_xpdfRealValue, + &_xpdfStringLength, + &_xpdfStringValue, + &_xpdfNameValue, + &_xpdfArrayLength, + &_xpdfArrayGet, + &_xpdfDictGet, + &_xpdfFreeObj, + &_xpdfMalloc, + &_xpdfRealloc, + &_xpdfFree, + &_xpdfRegisterSecurityHandler, +}; + +#endif // ENABLE_PLUGINS --- /dev/null 2005-09-15 11:24:01.334625920 +0200 +++ poppler/XpdfPluginAPI.h 2005-09-15 12:43:52.000000000 +0200 @@ -0,0 +1,341 @@ +/* + * XpdfPluginAPI.h + * + * Copyright 2004 Glyph & Cog, LLC + */ + +#ifndef XPDFPLUGINAPI_H +#define XPDFPLUGINAPI_H + +#ifdef _WIN32 +#include +#else +#define Object XtObject +#include +#undef Object +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------------------ + * Macros + *------------------------------------------------------------------------*/ + +/* + * The current API version. + */ +#define xpdfPluginAPIVersion 1 + +#ifdef _WIN32 +# ifdef __cplusplus +# define PLUGINFUNC(retType) extern "C" __declspec(dllexport) retType +# else +# define PLUGINFUNC(retType) extern __declspec(dllexport) retType +# endif +#else +# ifdef __cplusplus +# define PLUGINFUNC(retType) extern "C" retType +# else +# define PLUGINFUNC(retType) extern retType +# endif +#endif + +/*------------------------------------------------------------------------ + * Plugin setup/cleanup + *------------------------------------------------------------------------*/ + +/* + * All plugins are required to implement two functions: + * + * -- Initialize the plugin. Returns non-zero if successful. + * PLUGINFUNC(XpdfBool) xpdfInitPlugin(void); + * + * -- Free the plugin. + * PLUGINFUNC(void) xpdfFreePlugin(void); + */ + +/*------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------*/ + +/* + * Standard C boolean -- zero = false, non-zero = true. + */ +typedef int XpdfBool; +#define xpdfTrue 1 +#define xpdfFalse 0 + +/* + * PDF document handle. + */ +typedef struct _XpdfDoc *XpdfDoc; + +/* + * PDF object handle. + */ +typedef struct _XpdfObject *XpdfObject; + +/* + * Document access permissions. Any of these can be bitwise 'or'ed + * together. If xpdfPermissionOpen is not included, the document + * cannot be opened at all, and the other bits are ignored. + */ +typedef unsigned int XpdfPermission; +#define xpdfPermissionOpen (1 << 0) +#define xpdfPermissionPrint (1 << 2) +#define xpdfPermissionChange (1 << 3) +#define xpdfPermissionCopy (1 << 4) +#define xpdfPermissionNotes (1 << 5) + +/*------------------------------------------------------------------------ + * Security handler + *------------------------------------------------------------------------*/ + +/* + * XpdfSecurityHandler - a security handler plugin should create one + * of these and pass it to xpdfRegisterSecurityHandler. + */ +#ifdef __cplusplus +struct XpdfSecurityHandler { +#else +typedef struct { +#endif + + /* + * Version of the security handler spec (this document) -- use + * xpdfPluginAPIVersion. + */ + int version; + + /* + * Security handler name. + */ + char *name; + + /* + * Any global data the security handler needs. XpdfViewer will pass + * this pointer to all handler functions as the + * argument. + */ + void *handlerData; + + /* + * Allocate and initialize data for a new document. XpdfViewer will + * pass the returned pointer to all other handler functions as the + * argument. Returns non-zero if successful. + */ + XpdfBool (*newDoc)(void *handlerData, XpdfDoc doc, + XpdfObject encryptDict, void **docData); + + /* + * Free the data allocated by newDoc. + */ + void (*freeDoc)(void *handlerData, void *docData); + + /* + * Construct authorization data based on the supplied owner and user + * passwords (either or both of which may be NULL). This function + * is called in "batch" mode, i.e., if the password was supplied on + * the command line or via an Xpdf library API. It should not + * generate any user interaction (e.g., a password dialog). It is + * not required to support this function: the makeAuthData function + * pointer can be set to NULL. Returns non-zero if successful. + */ + XpdfBool (*makeAuthData)(void *handlerData, void *docData, + char *ownerPassword, char *userPassword, + void **authData); + + /* + * Request any needed information (e.g., a password) from the user, + * and construct an authorization data object. Returns non-zero if + * successful. + */ + XpdfBool (*getAuthData)(void *handlerData, void *docData, + void **authData); + + /* + * Free the data allocated by getAuthData. + */ + void (*freeAuthData)(void *handlerData, void *docData, + void *authData); + + /* + * Request permission to access the document. This returns all + * permissions granted by authData. + */ + XpdfPermission (*authorize)(void *handlerData, void *docData, + void *authData); + + /* + * Get the decryption key and algorithm version associated with the + * document. Returns non-zero if successful. + */ + XpdfBool (*getKey)(void *handlerData, void *docData, + char **key, int *keyLen, int *cryptVersion); + + /* + * Free the data allocated by getKey. + */ + void (*freeKey)(void *handlerData, void *docData, + char *key, int keyLen); + +#ifdef __cplusplus +}; +#else +} XpdfSecurityHandler; +#endif + +/*------------------------------------------------------------------------*/ + +typedef struct { + int version; + +/*------------------------------------------------------------------------ + * Document access functions + *------------------------------------------------------------------------*/ + +/* + * Get a document's info dictionary. (The returned object must be + * freed with xpdfFreeObj.) + */ +XpdfObject (*_xpdfGetInfoDict)(XpdfDoc doc); + +/* + * Get a document's catalog ("root") dictionary. (The returned object + * must be freed with xpdfFreeObj.) + */ +XpdfObject (*_xpdfGetCatalog)(XpdfDoc doc); + +#ifdef _WIN32 + +/* + * Get the handle for the viewer window associated with the specified + * document. [Win32 only] + */ +HWND (*_xpdfWin32GetWindow)(XpdfDoc doc); + +#else + +/* + * Get the Motif widget for the viewer window associated with the + * specified document. [X only] + */ +Widget (*_xpdfXGetWindow)(XpdfDoc doc); + +#endif + +/*------------------------------------------------------------------------ + * Object access functions + *------------------------------------------------------------------------*/ + +/* + * Check an object's type. + */ +XpdfBool (*_xpdfObjIsBool)(XpdfObject obj); +XpdfBool (*_xpdfObjIsInt)(XpdfObject obj); +XpdfBool (*_xpdfObjIsReal)(XpdfObject obj); +XpdfBool (*_xpdfObjIsString)(XpdfObject obj); +XpdfBool (*_xpdfObjIsName)(XpdfObject obj); +XpdfBool (*_xpdfObjIsNull)(XpdfObject obj); +XpdfBool (*_xpdfObjIsArray)(XpdfObject obj); +XpdfBool (*_xpdfObjIsDict)(XpdfObject obj); +XpdfBool (*_xpdfObjIsStream)(XpdfObject obj); +XpdfBool (*_xpdfObjIsRef)(XpdfObject obj); + +/* + * Value access. + * (Objects returned by xpdfArrayGet and xpdfDictGet must be freed + * with xpdfFreeObj.) + */ +XpdfBool (*_xpdfBoolValue)(XpdfObject obj); +int (*_xpdfIntValue)(XpdfObject obj); +double (*_xpdfRealValue)(XpdfObject obj); +int (*_xpdfStringLength)(XpdfObject obj); +char *(*_xpdfStringValue)(XpdfObject obj); +char *(*_xpdfNameValue)(XpdfObject obj); +int (*_xpdfArrayLength)(XpdfObject obj); +XpdfObject (*_xpdfArrayGet)(XpdfObject obj, int idx); +XpdfObject (*_xpdfDictGet)(XpdfObject obj, char *key); + +/* + * Object destruction. NB: *all* objects must be freed after use. + */ +void (*_xpdfFreeObj)(XpdfObject obj); + +/*------------------------------------------------------------------------ + * Memory allocation functions + *------------------------------------------------------------------------*/ + +void *(*_xpdfMalloc)(int size); +void *(*_xpdfRealloc)(void *p, int size); +void (*_xpdfFree)(void *p); + +/*------------------------------------------------------------------------ + * Security handler functions + *------------------------------------------------------------------------*/ + +/* + * Register a new security handler. + */ +void (*_xpdfRegisterSecurityHandler)(XpdfSecurityHandler *handler); + +/*------------------------------------------------------------------------*/ + +} XpdfPluginVecTable; + +#ifdef _WIN32 + +extern __declspec(dllexport) XpdfPluginVecTable xpdfPluginVecTable; + +#define xpdfPluginSetup \ + extern __declspec(dllexport) \ + XpdfPluginVecTable xpdfPluginVecTable = {xpdfPluginAPIVersion}; + +#else + +extern XpdfPluginVecTable xpdfPluginVecTable; + +#define xpdfPluginSetup \ + XpdfPluginVecTable xpdfPluginVecTable = {xpdfPluginAPIVersion}; + +#endif + +#define xpdfGetInfoDict (*xpdfPluginVecTable._xpdfGetInfoDict) +#define xpdfGetCatalog (*xpdfPluginVecTable._xpdfGetCatalog) +#ifdef _WIN32 +#define xpdfWin32GetWindow (*xpdfPluginVecTable._xpdfWin32GetWindow) +#else +#define xpdfXGetWindow (*xpdfPluginVecTable._xpdfXGetWindow) +#endif +#define xpdfObjIsBool (*xpdfPluginVecTable._xpdfObjIsBool) +#define xpdfObjIsInt (*xpdfPluginVecTable._xpdfObjIsInt) +#define xpdfObjIsReal (*xpdfPluginVecTable._xpdfObjIsReal) +#define xpdfObjIsString (*xpdfPluginVecTable._xpdfObjIsString) +#define xpdfObjIsName (*xpdfPluginVecTable._xpdfObjIsName) +#define xpdfObjIsNull (*xpdfPluginVecTable._xpdfObjIsNull) +#define xpdfObjIsArray (*xpdfPluginVecTable._xpdfObjIsArray) +#define xpdfObjIsDict (*xpdfPluginVecTable._xpdfObjIsDict) +#define xpdfObjIsStream (*xpdfPluginVecTable._xpdfObjIsStream) +#define xpdfObjIsRef (*xpdfPluginVecTable._xpdfObjIsRef) +#define xpdfBoolValue (*xpdfPluginVecTable._xpdfBoolValue) +#define xpdfIntValue (*xpdfPluginVecTable._xpdfIntValue) +#define xpdfRealValue (*xpdfPluginVecTable._xpdfRealValue) +#define xpdfStringLength (*xpdfPluginVecTable._xpdfStringLength) +#define xpdfStringValue (*xpdfPluginVecTable._xpdfStringValue) +#define xpdfNameValue (*xpdfPluginVecTable._xpdfNameValue) +#define xpdfArrayLength (*xpdfPluginVecTable._xpdfArrayLength) +#define xpdfArrayGet (*xpdfPluginVecTable._xpdfArrayGet) +#define xpdfDictGet (*xpdfPluginVecTable._xpdfDictGet) +#define xpdfFreeObj (*xpdfPluginVecTable._xpdfFreeObj) +#define xpdfMalloc (*xpdfPluginVecTable._xpdfMalloc) +#define xpdfRealloc (*xpdfPluginVecTable._xpdfRealloc) +#define xpdfFree (*xpdfPluginVecTable._xpdfFree) +#define xpdfRegisterSecurityHandler (*xpdfPluginVecTable._xpdfRegisterSecurityHandler) + +#ifdef __cplusplus +} +#endif + +#endif