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" 10 CXFA_SAXReaderHandler::CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext) 11 : m_pContext(pContext) { 12 FXSYS_assert(m_pContext); 13 } 14 CXFA_SAXReaderHandler::~CXFA_SAXReaderHandler() {} 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 125 IXFA_ChecksumContext* XFA_Checksum_Create() { 126 return new CXFA_ChecksumContext; 127 } 128 CXFA_ChecksumContext::CXFA_ChecksumContext() 129 : m_pSAXReader(NULL), m_pByteContext(NULL) {} 130 CXFA_ChecksumContext::~CXFA_ChecksumContext() { 131 FinishChecksum(); 132 } 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 } 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 } 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 } 181 void CXFA_ChecksumContext::GetChecksum(CFX_ByteString& bsChecksum) { 182 bsChecksum = m_bsChecksum; 183 } 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