Files
core/ASCOfficePDFReader/Parser.cpp

250 lines
5.5 KiB
C++

#include "stdafx.h"
#include <stddef.h>
#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 );
}