// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "xfa/fxfa/app/xfa_checksum.h"

#include "core/fdrm/crypto/include/fx_crypt.h"
#include "xfa/fgas/crt/fgas_algorithm.h"

CXFA_SAXReaderHandler::CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext)
    : m_pContext(pContext) {
  FXSYS_assert(m_pContext);
}
CXFA_SAXReaderHandler::~CXFA_SAXReaderHandler() {}
void* CXFA_SAXReaderHandler::OnTagEnter(const CFX_ByteStringC& bsTagName,
                                        FX_SAXNODE eType,
                                        FX_DWORD dwStartPos) {
  UpdateChecksum(TRUE);
  if (eType != FX_SAXNODE_Tag && eType != FX_SAXNODE_Instruction) {
    return NULL;
  }
  m_SAXContext.m_eNode = eType;
  CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf;
  textBuf << "<";
  if (eType == FX_SAXNODE_Instruction) {
    textBuf << "?";
  }
  textBuf << bsTagName;
  m_SAXContext.m_bsTagName = bsTagName;
  return &m_SAXContext;
}
void CXFA_SAXReaderHandler::OnTagAttribute(void* pTag,
                                           const CFX_ByteStringC& bsAttri,
                                           const CFX_ByteStringC& bsValue) {
  if (pTag == NULL) {
    return;
  }
  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
  textBuf << " " << bsAttri << "=\"" << bsValue << "\"";
}
void CXFA_SAXReaderHandler::OnTagBreak(void* pTag) {
  if (pTag == NULL) {
    return;
  }
  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
  textBuf << ">";
  UpdateChecksum(FALSE);
}
void CXFA_SAXReaderHandler::OnTagData(void* pTag,
                                      FX_SAXNODE eType,
                                      const CFX_ByteStringC& bsData,
                                      FX_DWORD dwStartPos) {
  if (pTag == NULL) {
    return;
  }
  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
  if (eType == FX_SAXNODE_CharData) {
    textBuf << "<![CDATA[";
  }
  textBuf << bsData;
  if (eType == FX_SAXNODE_CharData) {
    textBuf << "]]>";
  }
}
void CXFA_SAXReaderHandler::OnTagClose(void* pTag, FX_DWORD dwEndPos) {
  if (pTag == NULL) {
    return;
  }
  CXFA_SAXContext* pSAXContext = (CXFA_SAXContext*)pTag;
  CFX_ByteTextBuf& textBuf = pSAXContext->m_TextBuf;
  if (pSAXContext->m_eNode == FX_SAXNODE_Instruction) {
    textBuf << "?>";
  } else if (pSAXContext->m_eNode == FX_SAXNODE_Tag) {
    textBuf << "></" << pSAXContext->m_bsTagName << ">";
  }
  UpdateChecksum(FALSE);
}
void CXFA_SAXReaderHandler::OnTagEnd(void* pTag,
                                     const CFX_ByteStringC& bsTagName,
                                     FX_DWORD dwEndPos) {
  if (pTag == NULL) {
    return;
  }
  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
  textBuf << "</" << bsTagName << ">";
  UpdateChecksum(FALSE);
}
void CXFA_SAXReaderHandler::OnTargetData(void* pTag,
                                         FX_SAXNODE eType,
                                         const CFX_ByteStringC& bsData,
                                         FX_DWORD dwStartPos) {
  if (pTag == NULL && eType != FX_SAXNODE_Comment) {
    return;
  }
  if (eType == FX_SAXNODE_Comment) {
    CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf;
    textBuf << "<!--" << bsData << "-->";
    UpdateChecksum(FALSE);
  } else {
    CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
    textBuf << " " << bsData;
  }
}
void CXFA_SAXReaderHandler::UpdateChecksum(FX_BOOL bCheckSpace) {
  int32_t iLength = m_SAXContext.m_TextBuf.GetLength();
  if (iLength < 1) {
    return;
  }
  uint8_t* pBuffer = m_SAXContext.m_TextBuf.GetBuffer();
  FX_BOOL bUpdata = TRUE;
  if (bCheckSpace) {
    bUpdata = FALSE;
    for (int32_t i = 0; i < iLength; i++) {
      bUpdata = (pBuffer[i] > 0x20);
      if (bUpdata) {
        break;
      }
    }
  }
  if (bUpdata) {
    m_pContext->Update(CFX_ByteStringC(pBuffer, iLength));
  }
  m_SAXContext.m_TextBuf.Clear();
}
IXFA_ChecksumContext* XFA_Checksum_Create() {
  return new CXFA_ChecksumContext;
}
CXFA_ChecksumContext::CXFA_ChecksumContext()
    : m_pSAXReader(NULL), m_pByteContext(NULL) {}
CXFA_ChecksumContext::~CXFA_ChecksumContext() {
  FinishChecksum();
}
FX_BOOL CXFA_ChecksumContext::StartChecksum() {
  FinishChecksum();
  m_pByteContext = FX_Alloc(uint8_t, 128);
  CRYPT_SHA1Start(m_pByteContext);
  m_bsChecksum.Empty();
  m_pSAXReader = FX_SAXReader_Create();
  return m_pSAXReader != NULL;
}
FX_BOOL CXFA_ChecksumContext::UpdateChecksum(IFX_FileRead* pSrcFile,
                                             FX_FILESIZE offset,
                                             size_t size) {
  if (m_pSAXReader == NULL) {
    return FALSE;
  }
  if (pSrcFile == NULL) {
    return FALSE;
  }
  if (size < 1) {
    size = pSrcFile->GetSize();
  }
  CXFA_SAXReaderHandler handler(this);
  m_pSAXReader->SetHandler(&handler);
  if (m_pSAXReader->StartParse(
          pSrcFile, (FX_DWORD)offset, (FX_DWORD)size,
          FX_SAXPARSEMODE_NotSkipSpace | FX_SAXPARSEMODE_NotConvert_amp |
              FX_SAXPARSEMODE_NotConvert_lt | FX_SAXPARSEMODE_NotConvert_gt |
              FX_SAXPARSEMODE_NotConvert_sharp) < 0) {
    return FALSE;
  }
  return m_pSAXReader->ContinueParse(NULL) > 99;
}
void CXFA_ChecksumContext::FinishChecksum() {
  if (m_pSAXReader) {
    m_pSAXReader->Release();
    m_pSAXReader = NULL;
  }
  if (m_pByteContext) {
    uint8_t digest[20];
    FXSYS_memset(digest, 0, 20);
    CRYPT_SHA1Finish(m_pByteContext, digest);
    int32_t nLen = FX_Base64EncodeA(digest, 20, NULL);
    FX_CHAR* pBuffer = m_bsChecksum.GetBuffer(nLen);
    FX_Base64EncodeA(digest, 20, pBuffer);
    m_bsChecksum.ReleaseBuffer(nLen);
    FX_Free(m_pByteContext);
    m_pByteContext = NULL;
  }
}
void CXFA_ChecksumContext::GetChecksum(CFX_ByteString& bsChecksum) {
  bsChecksum = m_bsChecksum;
}
void CXFA_ChecksumContext::Update(const CFX_ByteStringC& bsText) {
  if (m_pByteContext) {
    CRYPT_SHA1Update(m_pByteContext, bsText.GetPtr(), bsText.GetLength());
  }
}
