[poppler] poppler/poppler: XpdfPluginAPI.cc, NONE,
1.1 XpdfPluginAPI.h, NONE, 1.1 SecurityHandler.cc, NONE,
1.1 SecurityHandler.h, NONE, 1.1 DCTStream.h, 1.4,
1.5 Decrypt.cc, 1.2, 1.3 Decrypt.h, 1.1.1.1, 1.2 FlateStream.h,
1.1, 1.2 GlobalParams.cc, 1.8, 1.9 GlobalParams.h, 1.3,
1.4 Makefile.am, 1.11, 1.12 PDFDoc.cc, 1.5, 1.6 PDFDoc.h, 1.3,
1.4 Parser.cc, 1.1.1.1, 1.2 Parser.h, 1.1.1.1, 1.2 Stream.cc,
1.4, 1.5 Stream.h, 1.4, 1.5 XRef.cc, 1.4, 1.5 XRef.h, 1.2,
1.3 poppler-config.h.in, 1.2, 1.3
Marco Pesenti Gritti
marco at freedesktop.org
Fri Sep 16 11:29:20 PDT 2005
Update of /cvs/poppler/poppler/poppler
In directory gabe:/tmp/cvs-serv4244/poppler
Modified Files:
DCTStream.h Decrypt.cc Decrypt.h FlateStream.h GlobalParams.cc
GlobalParams.h Makefile.am PDFDoc.cc PDFDoc.h Parser.cc
Parser.h Stream.cc Stream.h XRef.cc XRef.h poppler-config.h.in
Added Files:
XpdfPluginAPI.cc XpdfPluginAPI.h SecurityHandler.cc
SecurityHandler.h
Log Message:
2005-09-16 Marco Pesenti Gritti <mpg at redhat.com>
* goo/Makefile.am:
* poppler/DCTStream.h:
* poppler/Decrypt.cc:
* poppler/Decrypt.h:
* poppler/FlateStream.h:
* poppler/GlobalParams.cc:
* poppler/GlobalParams.h:
* poppler/Makefile.am:
* poppler/PDFDoc.cc:
* poppler/PDFDoc.h:
* poppler/Parser.cc:
* poppler/Parser.h:
* poppler/Stream.cc:
* poppler/Stream.h:
* poppler/XRef.cc:
* poppler/XRef.h:
* poppler/poppler-config.h.in:
Merge security plugins support from xpdf 3.01
--- NEW FILE: XpdfPluginAPI.cc ---
//========================================================================
//
// 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
--- NEW FILE: XpdfPluginAPI.h ---
/*
* XpdfPluginAPI.h
*
* Copyright 2004 Glyph & Cog, LLC
*/
#ifndef XPDFPLUGINAPI_H
#define XPDFPLUGINAPI_H
#ifdef _WIN32
#include <windows.h>
#else
#define Object XtObject
#include <X11/Intrinsic.h>
#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 <handlerData>
* argument.
*/
void *handlerData;
/*
* Allocate and initialize data for a new document. XpdfViewer will
* pass the returned pointer to all other handler functions as the
* <docData> 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
--- NEW FILE: SecurityHandler.cc ---
//========================================================================
//
// SecurityHandler.cc
//
// Copyright 2004 Glyph & Cog, LLC
//
//========================================================================
#include <config.h>
#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
--- NEW FILE: SecurityHandler.h ---
//========================================================================
//
// SecurityHandler.h
//
// Copyright 2004 Glyph & Cog, LLC
//
//========================================================================
#ifndef SECURITYHANDLER_H
#define SECURITYHANDLER_H
#include <config.h>
#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 <ownerPassword> and <userPassword> (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
Index: DCTStream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/DCTStream.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- DCTStream.h 1 Aug 2005 19:15:40 -0000 1.4
+++ DCTStream.h 16 Sep 2005 18:29:18 -0000 1.5
@@ -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: Decrypt.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Decrypt.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Decrypt.cc 28 Aug 2005 09:43:18 -0000 1.2
+++ Decrypt.cc 16 Sep 2005 18:29:18 -0000 1.3
@@ -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: Decrypt.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Decrypt.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- Decrypt.h 3 Mar 2005 19:46:00 -0000 1.1.1.1
+++ Decrypt.h 16 Sep 2005 18:29:18 -0000 1.2
@@ -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: FlateStream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/FlateStream.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- FlateStream.h 27 Apr 2005 20:56:18 -0000 1.1
+++ FlateStream.h 16 Sep 2005 18:29:18 -0000 1.2
@@ -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: GlobalParams.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GlobalParams.cc,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- GlobalParams.cc 23 Aug 2005 18:20:45 -0000 1.8
+++ GlobalParams.cc 16 Sep 2005 18:29:18 -0000 1.9
@@ -15,6 +15,14 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
+#ifdef ENABLE_PLUGINS
+# ifndef WIN32
+# include <dlfcn.h>
+# endif
+#endif
+#ifdef WIN32
+# include <shlobj.h>
+#endif
#if HAVE_PAPER_H
#include <paper.h>
#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: GlobalParams.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GlobalParams.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- GlobalParams.h 23 Aug 2005 18:20:45 -0000 1.3
+++ GlobalParams.h 16 Sep 2005 18:29:18 -0000 1.4
@@ -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: Makefile.am
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Makefile.am,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- Makefile.am 23 Aug 2005 18:20:45 -0000 1.11
+++ Makefile.am 16 Sep 2005 18:29:18 -0000 1.12
@@ -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: PDFDoc.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PDFDoc.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- PDFDoc.cc 7 Aug 2005 23:58:12 -0000 1.5
+++ PDFDoc.cc 16 Sep 2005 18:29:18 -0000 1.6
@@ -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: PDFDoc.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PDFDoc.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- PDFDoc.h 6 Jul 2005 13:29:00 -0000 1.3
+++ PDFDoc.h 16 Sep 2005 18:29:18 -0000 1.4
@@ -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: Parser.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Parser.cc,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- Parser.cc 3 Mar 2005 19:46:03 -0000 1.1.1.1
+++ Parser.cc 16 Sep 2005 18:29:18 -0000 1.2
@@ -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: Parser.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Parser.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- Parser.h 3 Mar 2005 19:46:01 -0000 1.1.1.1
+++ Parser.h 16 Sep 2005 18:29:18 -0000 1.2
@@ -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: Stream.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Stream.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Stream.cc 27 Aug 2005 08:43:43 -0000 1.4
+++ Stream.cc 16 Sep 2005 18:29:18 -0000 1.5
@@ -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: Stream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Stream.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Stream.h 31 Aug 2005 15:28:46 -0000 1.4
+++ Stream.h 16 Sep 2005 18:29:18 -0000 1.5
@@ -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: XRef.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/XRef.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- XRef.cc 27 Aug 2005 08:43:43 -0000 1.4
+++ XRef.cc 16 Sep 2005 18:29:18 -0000 1.5
@@ -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: XRef.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/XRef.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- XRef.h 5 Jul 2005 12:15:04 -0000 1.2
+++ XRef.h 16 Sep 2005 18:29:18 -0000 1.3
@@ -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-config.h.in
===================================================================
RCS file: /cvs/poppler/poppler/poppler/poppler-config.h.in,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- poppler-config.h.in 28 Jul 2005 06:31:57 -0000 1.2
+++ poppler-config.h.in 16 Sep 2005 18:29:18 -0000 1.3
@@ -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
More information about the poppler
mailing list