Files
core/PdfReader/Src/Parser.cpp
Ilya.Kirillov eb965c1d6d Добавлен новый проект PdfReader для кроссплатформенного чтения Pdf.
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62480 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:01:53 +03:00

250 lines
5.6 KiB
C++

#include <stddef.h>
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Decrypt.h"
#include "Parser.h"
#include "XRef.h"
namespace PdfReader
{
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);
}
}