home *** CD-ROM | disk | FTP | other *** search
- //========================================================================
- //
- // Parser.cc
- //
- // Copyright 1996 Derek B. Noonburg
- //
- //========================================================================
- //
- // Ported to EPOC by Sander van der Wal
- //
- // $Log: Parser.cpp $
- // Revision 1.2 2000-09-17 13:38:21+02 svdwal
- // Ported
- //
-
- #ifdef __GNUC__
- #pragma implementation
- #endif
-
- #ifndef __E32DEF_H__
- #include <e32def.h> // remove warning about NULL redefinition
- #endif
-
- #include <stddef.h>
-
- #include "Object.h"
- #include "Array.h"
- #include "Dict.h"
- #include "Parser.h"
- #include "Error.h"
- #include "md5.h"
- #include "XRef.h"
-
- #include "PDFGlobal.h"
- #include "Pdf.rsg"
- #include "PROFILE.h"
-
- void Parser::ConstructL() {
- lexer->getObjL(&buf1);
- lexer->getObjL(&buf2);
- }
-
- Parser::~Parser() {
- buf1.free();
- buf2.free();
- delete lexer;
- }
-
- Object *Parser::getObjL(Object *obj) {
-
- PROFILE_START(PARSER__GETOBJ);
-
- char *key;
- Stream *str;
- //Object obj2;
- int num;
-
- // refill buffer after inline image data
- if (inlineImg == 2) {
- buf1.free();
- buf2.free();
- lexer->getObjL(&buf1);
- lexer->getObjL(&buf2);
- inlineImg = 0;
- }
-
- // indirect reference or integer
- if (buf1.isInt()) {
- num = buf1.getInt();
- shiftL();
- if (buf1.isInt() && buf2.isCmd("R")) {
- obj->initRef(num, buf1.getInt());
- shiftL();
- shiftL();
- } else {
- obj->initInt(num);
- }
- }
- // array
- else if (buf1.isCmd("[")) {
- shiftL();
- RAutoObject obj2;
- obj->initArrayL();
- while (!buf1.isCmd("]") && !buf1.isEOF()) {
- obj->arrayAddL(getObjL(&obj2));
- obj2.initNull();
- }
- if (buf1.isEOF())
- error(getPos(), R_END_OF_FILE_INSIDE_ARRAY);
- shiftL();
-
- // dictionary or stream
- } else if (buf1.isCmd("<<")) {
- shiftL();
- obj->initDictL();
- while (!buf1.isCmd(">>") && !buf1.isEOF()) {
- if (!buf1.isName()) {
- error(getPos(), R_DICTIONARY_KEY_MUST_BE_A_NAME_OBJECT);
- shiftL();
- }
- else {
- RAutoObject obj2;
- key = copyStringL(buf1.getName());
- CleanupStack::PushL(key);
- shiftL();
- if (buf1.isEOF() || buf1.isError())
- break;
- obj->dictAddL(key, getObjL(&obj2));
- obj2.initNull();
- CleanupStack::Pop(); // key
- }
- }
- if (buf1.isEOF())
- error(getPos(), R_END_OF_FILE_INSIDE_DICTIONARY);
- if (buf2.isCmd("stream")) {
- //Object dict;
- //dict->copyL(obj);
- str = makeStreamL(obj);
- if (str) {
- //obj->free();
- obj->initStream(str);
- }
- else {
- obj->free();
- obj->initError();
- }
- }
- else {
- shiftL();
- }
-
- // simple object
- } else {
- buf1.copyL(obj);
- shiftL();
- }
-
- PROFILE_STOP(PARSER__GETOBJ);
-
- return obj;
- }
-
- Stream *Parser::makeStreamL(Object *dict) {
- Object obj;
- Stream *str;
- int pos, length;
-
- // get stream start position
- lexer->skipToNextLine();
- pos = lexer->getPos();
-
- // get length
- dict->dictLookupL("Length", &obj);
- if (obj.isInt()) {
- length = obj.getInt();
- obj.free();
- } else {
- error(getPos(), R_BAD__LENGTH__ATTRIBUTE_IN_STREAM);
- obj.free();
- return NULL;
- }
-
- // make base stream
- str = new(ELeave) FileStream(lexer->getStream()->getFile(), pos, length, dict);
- CleanupStack::PushL(str);
-
- // get filters
- str = str->addFiltersL(dict);
- // str is possibly changed, repush it
- CleanupStack::Pop(); // str
- CleanupStack::PushL(str);
-
- // skip over stream data
- lexer->setPos(pos + length);
-
- // refill token buffers and check for 'endstream'
- shiftL(); // kill '>>'
- shiftL(); // kill 'stream'
- if (buf1.isCmd("endstream"))
- shiftL();
- else
- error(getPos(), R_MISSING__ENDSTREAM_);
-
- CleanupStack::Pop(); // str
- return str;
- }
-
- void Parser::shiftL() {
-
- PROFILE_START(PARSER__SHIFT);
-
- if (inlineImg > 0) {
- ++inlineImg;
- } else if (buf2.isCmd("ID")) {
- lexer->skipChar(); // skip char after 'ID' command
- inlineImg = 1;
- }
- buf1.free();
- buf1 = buf2;
- buf2.initNull();
- if (inlineImg > 0) // don't buffer inline image data
- //buf2.initNull()
- ;
- else
- lexer->getObjL(&buf2);
-
- PROFILE_STOP(PARSER__SHIFT);
- }
-
-
- Object *Parser::getEncryptedObjL(Object *obj, int num, int gen) {
-
- PROFILE_START(PARSER__GETOBJ);
-
- char *key;
- Stream *str;
- //Object obj2;
-
- MD5 context;
- RC4KEY rc4Key;
- GString* MD5Key;
- GString* Key;
-
- // refill buffer after inline image data
- if (inlineImg == 2) {
- buf1.free();
- buf2.free();
- lexer->getObjL(&buf1);
- lexer->getObjL(&buf2);
- inlineImg = 0;
- }
-
- // array
- if (buf1.isCmd("[")) {
- shiftL();
- RAutoObject obj2;
- obj->initArrayL();
- while (!buf1.isCmd("]") && !buf1.isEOF()) {
- obj->arrayAddL(getEncryptedObjL(&obj2, num, gen));
- obj2.initNull();
- }
- if (buf1.isEOF())
- error(getPos(), R_END_OF_FILE_INSIDE_ARRAY);
- shiftL();
-
- // dictionary or stream
- } else if (buf1.isCmd("<<")) {
- shiftL();
- obj->initDictL();
- while (!buf1.isCmd(">>") && !buf1.isEOF()) {
- if (!buf1.isName()) {
- error(getPos(), R_DICTIONARY_KEY_MUST_BE_A_NAME_OBJECT);
- shiftL();
- } else {
- RAutoObject obj2;
- key = copyStringL(buf1.getName());
- CleanupStack::PushL(key);
- shiftL();
- if (buf1.isEOF() || buf1.isError())
- break;
- obj->dictAddL(key, getEncryptedObjL(&obj2, num, gen));
- obj2.initNull();
- CleanupStack::Pop(); // key
- }
- }
- if (buf1.isEOF())
- error(getPos(), R_END_OF_FILE_INSIDE_DICTIONARY);
- if (buf2.isCmd("stream")) {
- str = makeStreamL(obj);
- if (str) {
- obj->initStream(str);
- // enable Decryption on base File Stream
- str = obj->getStream()->getBaseStream();
- MD5Key = GString::NewLC();
- Key = GString::NewLC();
- Key->appendL(Global().XRef.xref->getEncryptionKey());
- Key->appendL((char)( num & 0xff));
- Key->appendL((char)((num >> 8) & 0xff));
- Key->appendL((char)((num >>16) & 0xff));
- Key->appendL((char)( gen & 0xff));
- Key->appendL((char)((gen >> 8) & 0xff));
- context.update((unsigned char *)Key->getCString(), 10);
- context.finalize();
- // MD5Key->clearL();
- char *p = (char *)context.raw_digestL();
- CleanupStack::PushL(p);
- MD5Key->appendL(p,10);
- // delete p;
- CleanupStack::PopAndDestroy(2); // p, Key
- // determine rc4Key
- rc4ExpandKey(&rc4Key, (unsigned char *)MD5Key->getCString(), 10);
- str->enableEncryption(&rc4Key);
- CleanupStack::PopAndDestroy(); // MD5Key
- } else {
- obj->free();
- obj->initError();
- }
- } else {
- shiftL();
- }
-
- // indirect reference or integer
- } else if (buf1.isInt()) {
- num = buf1.getInt();
- shiftL();
- if (buf1.isInt() && buf2.isCmd("R")) {
- obj->initRef(num, buf1.getInt());
- shiftL();
- shiftL();
- } else {
- obj->initInt(num);
- }
-
- // decrypt strings
- } else if (buf1.isString()) {
- buf1.copyL(obj);
- GString *s;
- s = obj->getString();
- MD5Key = GString::NewLC();
- Key = GString::NewLC();
- Key->appendL(Global().XRef.xref->getEncryptionKey());
- Key->appendL((char)( num & 0xff));
- Key->appendL((char)((num >> 8) & 0xff));
- Key->appendL((char)((num >>16) & 0xff));
- Key->appendL((char)( gen & 0xff));
- Key->appendL((char)((gen >> 8) & 0xff));
- context.update((unsigned char *)Key->getCString(),10);
- context.finalize();
- // MD5Key->clearL();
- char *p = (char *)context.raw_digestL();
- CleanupStack::PushL(p);
- MD5Key->appendL(p,10);
- CleanupStack::PopAndDestroy(2); // delete p; Key
- // determine rc4Key
- rc4ExpandKey(&rc4Key, (unsigned char *)MD5Key->getCString(),10);
- rc4Crypt (&rc4Key,
- (unsigned char *) obj->getString()->getCString(),
- obj->getString()->getLength());
- CleanupStack::PopAndDestroy(); // MD5Key
- shiftL();
-
- } else {
- buf1.copyL(obj);
- shiftL();
- }
-
- PROFILE_STOP(PARSER__GETOBJ);
-
- return obj;
- }
-