home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / pdf / Parser.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  8.2 KB  |  351 lines

  1. //========================================================================
  2. //
  3. // Parser.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8. //
  9. // Ported to EPOC by Sander van der Wal
  10. //
  11. // $Log: Parser.cpp $
  12. // Revision 1.2  2000-09-17 13:38:21+02  svdwal
  13. // Ported
  14. //
  15.  
  16. #ifdef __GNUC__
  17. #pragma implementation
  18. #endif
  19.  
  20. #ifndef __E32DEF_H__
  21. #include <e32def.h> // remove warning about NULL redefinition
  22. #endif
  23.  
  24. #include <stddef.h>
  25.  
  26. #include "Object.h"
  27. #include "Array.h"
  28. #include "Dict.h"
  29. #include "Parser.h"
  30. #include "Error.h"
  31. #include "md5.h"
  32. #include "XRef.h"
  33.  
  34. #include "PDFGlobal.h"
  35. #include "Pdf.rsg"
  36. #include "PROFILE.h"
  37.  
  38. void Parser::ConstructL() {
  39.   lexer->getObjL(&buf1);
  40.   lexer->getObjL(&buf2);
  41. }
  42.  
  43. Parser::~Parser() {
  44.   buf1.free();
  45.   buf2.free();
  46.   delete lexer;
  47. }
  48.  
  49. Object *Parser::getObjL(Object *obj) {
  50.  
  51.   PROFILE_START(PARSER__GETOBJ);
  52.  
  53.   char *key;
  54.   Stream *str;
  55.   //Object obj2;
  56.   int num;
  57.  
  58.   // refill buffer after inline image data
  59.   if (inlineImg == 2) {
  60.     buf1.free();
  61.     buf2.free();
  62.     lexer->getObjL(&buf1);
  63.     lexer->getObjL(&buf2);
  64.     inlineImg = 0;
  65.   }
  66.  
  67.   // indirect reference or integer
  68.   if (buf1.isInt()) {
  69.     num = buf1.getInt();
  70.     shiftL();
  71.     if (buf1.isInt() && buf2.isCmd("R")) {
  72.       obj->initRef(num, buf1.getInt());
  73.       shiftL();
  74.       shiftL();
  75.     } else {
  76.       obj->initInt(num);
  77.     }
  78.   }
  79.   // array
  80.   else if (buf1.isCmd("[")) {
  81.     shiftL();
  82.     RAutoObject obj2;
  83.     obj->initArrayL();
  84.     while (!buf1.isCmd("]") && !buf1.isEOF()) {
  85.       obj->arrayAddL(getObjL(&obj2));
  86.       obj2.initNull();
  87.     }
  88.     if (buf1.isEOF())
  89.       error(getPos(), R_END_OF_FILE_INSIDE_ARRAY);
  90.     shiftL();
  91.  
  92.   // dictionary or stream
  93.   } else if (buf1.isCmd("<<")) {
  94.     shiftL();
  95.     obj->initDictL();
  96.     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
  97.       if (!buf1.isName()) {
  98.         error(getPos(), R_DICTIONARY_KEY_MUST_BE_A_NAME_OBJECT);
  99.         shiftL();
  100.       } 
  101.       else {
  102.         RAutoObject obj2;
  103.         key = copyStringL(buf1.getName());
  104.         CleanupStack::PushL(key);
  105.         shiftL();
  106.         if (buf1.isEOF() || buf1.isError())
  107.           break;
  108.         obj->dictAddL(key, getObjL(&obj2));
  109.         obj2.initNull();
  110.         CleanupStack::Pop(); // key
  111.       }
  112.     }
  113.     if (buf1.isEOF())
  114.       error(getPos(), R_END_OF_FILE_INSIDE_DICTIONARY);
  115.     if (buf2.isCmd("stream")) {
  116.       //Object dict;
  117.       //dict->copyL(obj);
  118.       str = makeStreamL(obj);
  119.       if (str) {
  120.         //obj->free();
  121.         obj->initStream(str);
  122.       } 
  123.       else {
  124.         obj->free();
  125.         obj->initError();
  126.       }
  127.     } 
  128.     else {
  129.       shiftL();
  130.     }
  131.  
  132.   // simple object
  133.   } else {
  134.     buf1.copyL(obj);
  135.     shiftL();
  136.   }
  137.   
  138.   PROFILE_STOP(PARSER__GETOBJ);
  139.   
  140.   return obj;
  141. }
  142.  
  143. Stream *Parser::makeStreamL(Object *dict) {
  144.   Object obj;
  145.   Stream *str;
  146.   int pos, length;
  147.  
  148.   // get stream start position
  149.   lexer->skipToNextLine();
  150.   pos = lexer->getPos();
  151.  
  152.   // get length
  153.   dict->dictLookupL("Length", &obj);
  154.   if (obj.isInt()) {
  155.     length = obj.getInt();
  156.     obj.free();
  157.   } else {
  158.     error(getPos(), R_BAD__LENGTH__ATTRIBUTE_IN_STREAM);
  159.     obj.free();
  160.     return NULL;
  161.   }
  162.  
  163.   // make base stream
  164.   str = new(ELeave) FileStream(lexer->getStream()->getFile(), pos, length, dict);
  165.   CleanupStack::PushL(str);
  166.  
  167.   // get filters
  168.   str = str->addFiltersL(dict);
  169.   // str is possibly changed, repush it
  170.   CleanupStack::Pop(); // str
  171.   CleanupStack::PushL(str);
  172.  
  173.   // skip over stream data
  174.   lexer->setPos(pos + length);
  175.  
  176.   // refill token buffers and check for 'endstream'
  177.   shiftL();  // kill '>>'
  178.   shiftL();  // kill 'stream'
  179.   if (buf1.isCmd("endstream"))
  180.     shiftL();
  181.   else
  182.     error(getPos(), R_MISSING__ENDSTREAM_);
  183.  
  184.   CleanupStack::Pop(); // str
  185.   return str;
  186. }
  187.  
  188. void Parser::shiftL() {
  189.  
  190.   PROFILE_START(PARSER__SHIFT);
  191.  
  192.   if (inlineImg > 0) {
  193.     ++inlineImg;
  194.   } else if (buf2.isCmd("ID")) {
  195.     lexer->skipChar();        // skip char after 'ID' command
  196.     inlineImg = 1;
  197.   }
  198.   buf1.free();
  199.   buf1 = buf2;
  200.   buf2.initNull();
  201.   if (inlineImg > 0)        // don't buffer inline image data
  202.     //buf2.initNull()
  203.     ;
  204.   else
  205.     lexer->getObjL(&buf2);
  206.  
  207.   PROFILE_STOP(PARSER__SHIFT);
  208. }
  209.  
  210.  
  211. Object *Parser::getEncryptedObjL(Object *obj, int num, int gen) {
  212.  
  213.   PROFILE_START(PARSER__GETOBJ);
  214.  
  215.   char *key;
  216.   Stream *str;
  217.   //Object obj2;
  218.  
  219.   MD5 context;
  220.   RC4KEY rc4Key;
  221.   GString* MD5Key;
  222.   GString* Key;
  223.  
  224.   // refill buffer after inline image data
  225.   if (inlineImg == 2) {
  226.     buf1.free();
  227.     buf2.free();
  228.     lexer->getObjL(&buf1);
  229.     lexer->getObjL(&buf2);
  230.     inlineImg = 0;
  231.   }
  232.  
  233.   // array
  234.   if (buf1.isCmd("[")) {
  235.     shiftL();
  236.     RAutoObject obj2;
  237.     obj->initArrayL();
  238.     while (!buf1.isCmd("]") && !buf1.isEOF()) {
  239.       obj->arrayAddL(getEncryptedObjL(&obj2, num, gen));
  240.       obj2.initNull();
  241.     }
  242.     if (buf1.isEOF())
  243.       error(getPos(), R_END_OF_FILE_INSIDE_ARRAY);
  244.     shiftL();
  245.  
  246.   // dictionary or stream
  247.   } else if (buf1.isCmd("<<")) {
  248.     shiftL();
  249.     obj->initDictL();
  250.     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
  251.       if (!buf1.isName()) {
  252.      error(getPos(), R_DICTIONARY_KEY_MUST_BE_A_NAME_OBJECT);
  253.     shiftL();
  254.       } else {
  255.         RAutoObject obj2;
  256.     key = copyStringL(buf1.getName());
  257.         CleanupStack::PushL(key);
  258.     shiftL();
  259.     if (buf1.isEOF() || buf1.isError())
  260.       break;
  261.     obj->dictAddL(key, getEncryptedObjL(&obj2, num, gen));
  262.         obj2.initNull();
  263.         CleanupStack::Pop(); // key
  264.       }
  265.     }
  266.     if (buf1.isEOF())
  267.       error(getPos(),  R_END_OF_FILE_INSIDE_DICTIONARY);
  268.     if (buf2.isCmd("stream")) {
  269.       str = makeStreamL(obj);
  270.       if (str) {
  271.     obj->initStream(str);
  272.         // enable Decryption on base File Stream
  273.         str = obj->getStream()->getBaseStream();
  274.         MD5Key = GString::NewLC();
  275.         Key = GString::NewLC();
  276.         Key->appendL(Global().XRef.xref->getEncryptionKey());
  277.         Key->appendL((char)( num       & 0xff));
  278.         Key->appendL((char)((num >> 8) & 0xff));
  279.         Key->appendL((char)((num >>16) & 0xff));
  280.         Key->appendL((char)( gen       & 0xff));
  281.         Key->appendL((char)((gen >> 8) & 0xff));
  282.         context.update((unsigned char *)Key->getCString(), 10);
  283.         context.finalize();
  284.         // MD5Key->clearL();
  285.         char *p = (char *)context.raw_digestL();
  286.         CleanupStack::PushL(p);
  287.         MD5Key->appendL(p,10);
  288.         // delete p;
  289.         CleanupStack::PopAndDestroy(2); // p, Key
  290.         // determine rc4Key
  291.         rc4ExpandKey(&rc4Key, (unsigned char *)MD5Key->getCString(), 10);
  292.         str->enableEncryption(&rc4Key);
  293.         CleanupStack::PopAndDestroy(); // MD5Key
  294.       } else {
  295.     obj->free();
  296.     obj->initError();
  297.       }
  298.     } else {
  299.       shiftL();
  300.     }
  301.  
  302.   // indirect reference or integer
  303.   } else if (buf1.isInt()) {
  304.     num = buf1.getInt();
  305.     shiftL();
  306.     if (buf1.isInt() && buf2.isCmd("R")) {
  307.       obj->initRef(num, buf1.getInt());
  308.       shiftL();
  309.       shiftL();
  310.     } else {
  311.       obj->initInt(num);
  312.     }
  313.  
  314.     // decrypt strings
  315.   } else if (buf1.isString()) {
  316.     buf1.copyL(obj);
  317.     GString *s;
  318.     s = obj->getString();
  319.     MD5Key = GString::NewLC();
  320.     Key = GString::NewLC();
  321.     Key->appendL(Global().XRef.xref->getEncryptionKey());
  322.     Key->appendL((char)( num       & 0xff));
  323.     Key->appendL((char)((num >> 8) & 0xff));
  324.     Key->appendL((char)((num >>16) & 0xff));
  325.     Key->appendL((char)( gen       & 0xff));
  326.     Key->appendL((char)((gen >> 8) & 0xff));
  327.     context.update((unsigned char *)Key->getCString(),10);
  328.     context.finalize();
  329.     // MD5Key->clearL();
  330.     char *p = (char *)context.raw_digestL();
  331.     CleanupStack::PushL(p);
  332.     MD5Key->appendL(p,10);
  333.     CleanupStack::PopAndDestroy(2); // delete p; Key
  334.     // determine rc4Key
  335.     rc4ExpandKey(&rc4Key, (unsigned char *)MD5Key->getCString(),10);
  336.     rc4Crypt (&rc4Key,
  337.       (unsigned char *) obj->getString()->getCString(),
  338.       obj->getString()->getLength());
  339.     CleanupStack::PopAndDestroy(); // MD5Key
  340.     shiftL();
  341.  
  342.   } else {
  343.     buf1.copyL(obj);
  344.     shiftL();
  345.   }
  346.  
  347.   PROFILE_STOP(PARSER__GETOBJ);
  348.   
  349.   return obj;
  350. }
  351.