1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/src/foxitlib.h"
8 #include "xfa/src/fxfa/src/common/xfa_common.h"
9 #include "xfa_checksum.h"
CXFA_SAXReaderHandler(CXFA_ChecksumContext * pContext)10 CXFA_SAXReaderHandler::CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext)
11 : m_pContext(pContext) {
12 FXSYS_assert(m_pContext);
13 }
~CXFA_SAXReaderHandler()14 CXFA_SAXReaderHandler::~CXFA_SAXReaderHandler() {}
OnTagEnter(const CFX_ByteStringC & bsTagName,FX_SAXNODE eType,FX_DWORD dwStartPos)15 void* CXFA_SAXReaderHandler::OnTagEnter(const CFX_ByteStringC& bsTagName,
16 FX_SAXNODE eType,
17 FX_DWORD dwStartPos) {
18 UpdateChecksum(TRUE);
19 if (eType != FX_SAXNODE_Tag && eType != FX_SAXNODE_Instruction) {
20 return NULL;
21 }
22 m_SAXContext.m_eNode = eType;
23 CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf;
24 textBuf << "<";
25 if (eType == FX_SAXNODE_Instruction) {
26 textBuf << "?";
27 }
28 textBuf << bsTagName;
29 m_SAXContext.m_bsTagName = bsTagName;
30 return &m_SAXContext;
31 }
OnTagAttribute(void * pTag,const CFX_ByteStringC & bsAttri,const CFX_ByteStringC & bsValue)32 void CXFA_SAXReaderHandler::OnTagAttribute(void* pTag,
33 const CFX_ByteStringC& bsAttri,
34 const CFX_ByteStringC& bsValue) {
35 if (pTag == NULL) {
36 return;
37 }
38 CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
39 textBuf << " " << bsAttri << "=\"" << bsValue << "\"";
40 }
OnTagBreak(void * pTag)41 void CXFA_SAXReaderHandler::OnTagBreak(void* pTag) {
42 if (pTag == NULL) {
43 return;
44 }
45 CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
46 textBuf << ">";
47 UpdateChecksum(FALSE);
48 }
OnTagData(void * pTag,FX_SAXNODE eType,const CFX_ByteStringC & bsData,FX_DWORD dwStartPos)49 void CXFA_SAXReaderHandler::OnTagData(void* pTag,
50 FX_SAXNODE eType,
51 const CFX_ByteStringC& bsData,
52 FX_DWORD dwStartPos) {
53 if (pTag == NULL) {
54 return;
55 }
56 CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
57 if (eType == FX_SAXNODE_CharData) {
58 textBuf << "<![CDATA[";
59 }
60 textBuf << bsData;
61 if (eType == FX_SAXNODE_CharData) {
62 textBuf << "]]>";
63 }
64 }
OnTagClose(void * pTag,FX_DWORD dwEndPos)65 void CXFA_SAXReaderHandler::OnTagClose(void* pTag, FX_DWORD dwEndPos) {
66 if (pTag == NULL) {
67 return;
68 }
69 CXFA_SAXContext* pSAXContext = (CXFA_SAXContext*)pTag;
70 CFX_ByteTextBuf& textBuf = pSAXContext->m_TextBuf;
71 if (pSAXContext->m_eNode == FX_SAXNODE_Instruction) {
72 textBuf << "?>";
73 } else if (pSAXContext->m_eNode == FX_SAXNODE_Tag) {
74 textBuf << "></" << pSAXContext->m_bsTagName << ">";
75 }
76 UpdateChecksum(FALSE);
77 }
OnTagEnd(void * pTag,const CFX_ByteStringC & bsTagName,FX_DWORD dwEndPos)78 void CXFA_SAXReaderHandler::OnTagEnd(void* pTag,
79 const CFX_ByteStringC& bsTagName,
80 FX_DWORD dwEndPos) {
81 if (pTag == NULL) {
82 return;
83 }
84 CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
85 textBuf << "</" << bsTagName << ">";
86 UpdateChecksum(FALSE);
87 }
OnTargetData(void * pTag,FX_SAXNODE eType,const CFX_ByteStringC & bsData,FX_DWORD dwStartPos)88 void CXFA_SAXReaderHandler::OnTargetData(void* pTag,
89 FX_SAXNODE eType,
90 const CFX_ByteStringC& bsData,
91 FX_DWORD dwStartPos) {
92 if (pTag == NULL && eType != FX_SAXNODE_Comment) {
93 return;
94 }
95 if (eType == FX_SAXNODE_Comment) {
96 CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf;
97 textBuf << "<!--" << bsData << "-->";
98 UpdateChecksum(FALSE);
99 } else {
100 CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
101 textBuf << " " << bsData;
102 }
103 }
UpdateChecksum(FX_BOOL bCheckSpace)104 void CXFA_SAXReaderHandler::UpdateChecksum(FX_BOOL bCheckSpace) {
105 int32_t iLength = m_SAXContext.m_TextBuf.GetLength();
106 if (iLength < 1) {
107 return;
108 }
109 uint8_t* pBuffer = m_SAXContext.m_TextBuf.GetBuffer();
110 FX_BOOL bUpdata = TRUE;
111 if (bCheckSpace) {
112 bUpdata = FALSE;
113 for (int32_t i = 0; i < iLength; i++) {
114 bUpdata = (pBuffer[i] > 0x20);
115 if (bUpdata) {
116 break;
117 }
118 }
119 }
120 if (bUpdata) {
121 m_pContext->Update(CFX_ByteStringC(pBuffer, iLength));
122 }
123 m_SAXContext.m_TextBuf.Clear();
124 }
XFA_Checksum_Create()125 IXFA_ChecksumContext* XFA_Checksum_Create() {
126 return new CXFA_ChecksumContext;
127 }
CXFA_ChecksumContext()128 CXFA_ChecksumContext::CXFA_ChecksumContext()
129 : m_pSAXReader(NULL), m_pByteContext(NULL) {}
~CXFA_ChecksumContext()130 CXFA_ChecksumContext::~CXFA_ChecksumContext() {
131 FinishChecksum();
132 }
StartChecksum()133 FX_BOOL CXFA_ChecksumContext::StartChecksum() {
134 FinishChecksum();
135 m_pByteContext = FX_Alloc(uint8_t, 128);
136 CRYPT_SHA1Start(m_pByteContext);
137 m_bsChecksum.Empty();
138 m_pSAXReader = FX_SAXReader_Create();
139 return m_pSAXReader != NULL;
140 }
UpdateChecksum(IFX_FileRead * pSrcFile,FX_FILESIZE offset,size_t size)141 FX_BOOL CXFA_ChecksumContext::UpdateChecksum(IFX_FileRead* pSrcFile,
142 FX_FILESIZE offset,
143 size_t size) {
144 if (m_pSAXReader == NULL) {
145 return FALSE;
146 }
147 if (pSrcFile == NULL) {
148 return FALSE;
149 }
150 if (size < 1) {
151 size = pSrcFile->GetSize();
152 }
153 CXFA_SAXReaderHandler handler(this);
154 m_pSAXReader->SetHandler(&handler);
155 if (m_pSAXReader->StartParse(
156 pSrcFile, (FX_DWORD)offset, (FX_DWORD)size,
157 FX_SAXPARSEMODE_NotSkipSpace | FX_SAXPARSEMODE_NotConvert_amp |
158 FX_SAXPARSEMODE_NotConvert_lt | FX_SAXPARSEMODE_NotConvert_gt |
159 FX_SAXPARSEMODE_NotConvert_sharp) < 0) {
160 return FALSE;
161 }
162 return m_pSAXReader->ContinueParse(NULL) > 99;
163 }
FinishChecksum()164 void CXFA_ChecksumContext::FinishChecksum() {
165 if (m_pSAXReader != NULL) {
166 m_pSAXReader->Release();
167 m_pSAXReader = NULL;
168 }
169 if (m_pByteContext) {
170 uint8_t digest[20];
171 FXSYS_memset(digest, 0, 20);
172 CRYPT_SHA1Finish(m_pByteContext, digest);
173 int32_t nLen = FX_Base64EncodeA(digest, 20, NULL);
174 FX_CHAR* pBuffer = m_bsChecksum.GetBuffer(nLen);
175 FX_Base64EncodeA(digest, 20, pBuffer);
176 m_bsChecksum.ReleaseBuffer(nLen);
177 FX_Free(m_pByteContext);
178 m_pByteContext = NULL;
179 }
180 }
GetChecksum(CFX_ByteString & bsChecksum)181 void CXFA_ChecksumContext::GetChecksum(CFX_ByteString& bsChecksum) {
182 bsChecksum = m_bsChecksum;
183 }
Update(const CFX_ByteStringC & bsText)184 void CXFA_ChecksumContext::Update(const CFX_ByteStringC& bsText) {
185 if (m_pByteContext != NULL) {
186 CRYPT_SHA1Update(m_pByteContext, bsText.GetPtr(), bsText.GetLength());
187 }
188 }
189