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