#include "stdafx.h" #include #include "Object.h" #include "Array.h" #include "Dict.h" #include "Decrypt.h" #include "Parser.h" #include "XRef.h" Parser::Parser(XRef *pXref, Lexer *pLexer, BOOL bAllowStreams) { m_pXref = pXref; m_pLexer = pLexer; m_nInlineImage = 0; m_bAllowStreams = bAllowStreams; m_pLexer->GetObject( &m_oBuffer1 ); m_pLexer->GetObject( &m_oBuffer2 ); } Parser::~Parser() { m_oBuffer1.Free(); m_oBuffer2.Free(); delete m_pLexer; } Object *Parser::GetObject(Object *pObject, unsigned char *sDecryptKey, CryptAlgorithm eEncryptAlgorithm, int nKeyLength, int nObjectNum, int nObjectGen) { Stream *pStream = NULL; Object oTemp; int nNum = 0; // Обновляем буффер после Inline image data if ( m_nInlineImage == 2 ) { m_oBuffer1.Free(); m_oBuffer2.Free(); m_pLexer->GetObject( &m_oBuffer1 ); m_pLexer->GetObject( &m_oBuffer2 ); m_nInlineImage = 0; } // Массив if ( m_oBuffer1.IsCommand("[") ) { Shift(); pObject->InitArray(m_pXref); while ( !m_oBuffer1.IsCommand("]" ) && !m_oBuffer1.IsEOF() ) pObject->ArrayAdd( GetObject( &oTemp, sDecryptKey, eEncryptAlgorithm, nKeyLength, nObjectNum, nObjectGen) ); if ( m_oBuffer1.IsEOF() ) { // TO DO: Error "End of file inside array" } Shift(); } else if ( m_oBuffer1.IsCommand("<<") ) // Dictionary или Stream { Shift(); pObject->InitDict(m_pXref); while ( !m_oBuffer1.IsCommand(">>") && !m_oBuffer1.IsEOF() ) { if ( !m_oBuffer1.IsName() ) { // TO DO: Error "Dictionary key must be a name object" Shift(); } else { char *sKey = CopyString( m_oBuffer1.GetName() ); Shift(); if ( m_oBuffer1.IsEOF() || m_oBuffer1.IsError() ) { MemUtilsFree( sKey ); break; } pObject->DictAdd( sKey, GetObject( &oTemp, sDecryptKey, eEncryptAlgorithm, nKeyLength, nObjectNum, nObjectGen)); } } if ( m_oBuffer1.IsEOF() ) { // TO DO: Error "End of file inside dictionary" } // Объекты Stream Objects не допустимы внутри потока или объекта типа Stream Objects if ( m_bAllowStreams && m_oBuffer2.IsCommand("stream") ) { if ( ( pStream = CreateStream(pObject, sDecryptKey, eEncryptAlgorithm, nKeyLength, nObjectNum, nObjectGen) ) ) { pObject->InitStream( pStream ); } else { pObject->Free(); pObject->InitError(); } } else { Shift(); } } else if ( m_oBuffer1.IsInt() ) // Либо ссылка, либо число { nNum = m_oBuffer1.GetInt(); Shift(); if ( m_oBuffer1.IsInt() && m_oBuffer2.IsCommand("R") ) { pObject->InitRef( nNum, m_oBuffer1.GetInt()); Shift(); Shift(); } else { pObject->InitInt(nNum); } } else if ( m_oBuffer1.IsString() && sDecryptKey ) // строка { StringExt *seTemp = m_oBuffer1.GetString(); StringExt *seRes = new StringExt(); oTemp.InitNull(); DecryptStream *pDecrypt = new DecryptStream(new MemoryStream( seTemp->GetBuffer(), 0, seTemp->GetLength(), &oTemp), sDecryptKey, eEncryptAlgorithm, nKeyLength, nObjectNum, nObjectGen); pDecrypt->Reset(); int nChar = 0; while ( ( nChar = pDecrypt->GetChar() ) != EOF ) { seRes->Append((char)nChar); } delete pDecrypt; pObject->InitString(seRes); Shift(); } else // простой объект { m_oBuffer1.Copy(pObject); Shift(); } return pObject; } Stream *Parser::CreateStream(Object *pDict, unsigned char *sDecryptKey, CryptAlgorithm eEncryptAlgorithm, int nKeyLength, int nObjectNum, int nObjectGen) { Object oTemp; unsigned int nLength, unEndPos; m_pLexer->SkipToNextLine(); unsigned int unPos = m_pLexer->GetPos(); // Считываем длину pDict->DictLookup("Length", &oTemp); if ( oTemp.IsInt() ) { nLength = (unsigned int)oTemp.GetInt(); oTemp.Free(); } else { oTemp.Free(); unsigned int unEndPos = unPos; while ( !m_oBuffer2.IsCommand("endstream") && !m_oBuffer2.IsEOF() ) { unEndPos = m_pLexer->GetPos(); Shift(); } nLength = unEndPos - unPos; m_pLexer->SetPos( unPos ); // Оставим на всякий случай заглушку if ( nLength <= 0 ) nLength = 5000; } // Меняем длину, если файл поврежден if ( m_pXref && m_pXref->GetStreamEnd( unPos, &unEndPos) ) { nLength = unEndPos - unPos; } // В сильно повержденных файлах PDF, выставляем конец потока сразу // после его начала if ( !m_pLexer->GetStream() ) { return NULL; } BaseStream *pBaseStream = m_pLexer->GetStream()->GetBaseStream(); // Пропускаем данный потока m_pLexer->SetPos( unPos + nLength ); // Проверяем 'endstream' Shift(); // '>>' Shift(); // 'endstream' if ( m_oBuffer1.IsCommand("endstream") ) { Shift(); } else { // TO DO : Error "Missing 'endstream'" // Заплатка для поврежденных файлов: nLength += 5000; } Stream *pStream = pBaseStream->MakeSubStream( unPos, TRUE, nLength, pDict ); // Decryption if ( sDecryptKey ) { pStream = new DecryptStream( pStream, sDecryptKey, eEncryptAlgorithm, nKeyLength, nObjectNum, nObjectGen); } // Filters pStream = pStream->AddFilters( pDict ); return pStream; } void Parser::Shift() { if ( m_nInlineImage > 0 ) { if ( m_nInlineImage < 2 ) { ++m_nInlineImage; } else { // В поврежденном потоке, если 'ID' появляется в середине потока, // нужно сбросить параметры m_nInlineImage = 0; } } else if ( m_oBuffer2.IsCommand("ID") ) { m_pLexer->SkipChar(); // пропускаем символ после команды 'ID' m_nInlineImage = 1; } m_oBuffer1.Free(); m_oBuffer1 = m_oBuffer2; if ( m_nInlineImage > 0 ) // не буфферизируем данные Inline Image m_oBuffer2.InitNull(); else m_pLexer->GetObject( &m_oBuffer2 ); }