summaryrefslogtreecommitdiff
path: root/xfa/src/fdp/src/css/fde_csssyntax.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/src/fdp/src/css/fde_csssyntax.cpp')
-rw-r--r--xfa/src/fdp/src/css/fde_csssyntax.cpp495
1 files changed, 495 insertions, 0 deletions
diff --git a/xfa/src/fdp/src/css/fde_csssyntax.cpp b/xfa/src/fdp/src/css/fde_csssyntax.cpp
new file mode 100644
index 0000000000..b7e5da9d6c
--- /dev/null
+++ b/xfa/src/fdp/src/css/fde_csssyntax.cpp
@@ -0,0 +1,495 @@
+// 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 "../../../foxitlib.h"
+#include "fde_csssyntax.h"
+#include "fde_cssdatatable.h"
+#ifdef _cplusplus
+extern "C" {
+#endif
+ inline FX_BOOL FDE_IsSelectorStart(FX_WCHAR wch)
+ {
+ return wch == '.' || wch == '#' || wch == '*'
+ || (wch >= 'a' && wch <= 'z')
+ || (wch >= 'A' && wch <= 'Z');
+ }
+#ifdef _cplusplus
+};
+#endif
+IFDE_CSSSyntaxParser* IFDE_CSSSyntaxParser::Create()
+{
+ return FDE_New CFDE_CSSSyntaxParser;
+}
+CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser()
+ : m_pStream(NULL)
+ , m_iStreamPos(0)
+ , m_iPlaneSize(0)
+ , m_iTextDatLen(0)
+ , m_dwCheck((FX_DWORD) - 1)
+ , m_eMode(FDE_CSSSYNTAXMODE_RuleSet)
+ , m_eStatus(FDE_CSSSYNTAXSTATUS_None)
+{
+}
+CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser()
+{
+ m_TextData.Reset();
+ m_TextPlane.Reset();
+}
+FX_BOOL CFDE_CSSSyntaxParser::Init(IFX_Stream *pStream, FX_INT32 iCSSPlaneSize, FX_INT32 iTextDataSize , FX_BOOL bOnlyDeclaration )
+{
+ FXSYS_assert(pStream != NULL && iCSSPlaneSize > 0 && iTextDataSize > 0);
+ Reset(bOnlyDeclaration);
+ if (!m_TextData.EstimateSize(iTextDataSize)) {
+ return FALSE;
+ }
+ FX_BYTE bom[4];
+ m_pStream = pStream;
+ m_iStreamPos = m_pStream->GetBOM(bom);
+ m_iPlaneSize = iCSSPlaneSize;
+ return TRUE;
+}
+FX_BOOL CFDE_CSSSyntaxParser::Init(FX_LPCWSTR pBuffer, FX_INT32 iBufferSize, FX_INT32 iTextDatSize , FX_BOOL bOnlyDeclaration )
+{
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0 && iTextDatSize > 0);
+ Reset(bOnlyDeclaration);
+ if (!m_TextData.EstimateSize(iTextDatSize)) {
+ return FALSE;
+ }
+ return m_TextPlane.AttachBuffer(pBuffer, iBufferSize);
+}
+void CFDE_CSSSyntaxParser::Reset(FX_BOOL bOnlyDeclaration)
+{
+ m_TextPlane.Reset();
+ m_TextData.Reset();
+ m_pStream = NULL;
+ m_iStreamPos = 0;
+ m_iTextDatLen = 0;
+ m_dwCheck = (FX_DWORD) - 1;
+ m_eStatus = FDE_CSSSYNTAXSTATUS_None;
+ m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName : FDE_CSSSYNTAXMODE_RuleSet;
+}
+FDE_CSSSYNTAXSTATUS CFDE_CSSSyntaxParser::DoSyntaxParse()
+{
+ while (m_eStatus >= FDE_CSSSYNTAXSTATUS_None) {
+ if (m_TextPlane.IsEOF()) {
+ if (m_pStream == NULL) {
+ if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue && m_TextData.GetLength() > 0) {
+ SaveTextData();
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue;
+ }
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS;
+ }
+ FX_BOOL bEOS;
+ FX_INT32 iLen = m_TextPlane.LoadFromStream(m_pStream, m_iStreamPos, m_iPlaneSize, bEOS);
+ m_iStreamPos = m_pStream->GetPosition();
+ if (iLen < 1) {
+ if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue && m_TextData.GetLength() > 0) {
+ SaveTextData();
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue;
+ }
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS;
+ }
+ }
+ FX_WCHAR wch;
+ while (!m_TextPlane.IsEOF()) {
+ wch = m_TextPlane.GetChar();
+ switch (m_eMode) {
+ case FDE_CSSSYNTAXMODE_RuleSet:
+ switch (wch) {
+ case '@':
+ m_TextPlane.MoveNext();
+ SwitchMode(FDE_CSSSYNTAXMODE_AtRule);
+ break;
+ case '}':
+ m_TextPlane.MoveNext();
+ if (RestoreMode()) {
+ return FDE_CSSSYNTAXSTATUS_DeclClose;
+ } else {
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
+ }
+ break;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ m_ModeStack.Push(m_eMode);
+ SwitchMode(FDE_CSSSYNTAXMODE_Comment);
+ break;
+ }
+ default:
+ if (wch <= ' ') {
+ m_TextPlane.MoveNext();
+ } else if (FDE_IsSelectorStart(wch)) {
+ SwitchMode(FDE_CSSSYNTAXMODE_Selector);
+ return FDE_CSSSYNTAXSTATUS_StyleRule;
+ } else {
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
+ }
+ break;
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_Selector:
+ switch (wch) {
+ case ',':
+ m_TextPlane.MoveNext();
+ SwitchMode(FDE_CSSSYNTAXMODE_Selector);
+ if (m_iTextDatLen > 0) {
+ return FDE_CSSSYNTAXSTATUS_Selector;
+ }
+ break;
+ case '{':
+ if (m_TextData.GetLength() > 0) {
+ SaveTextData();
+ return FDE_CSSSYNTAXSTATUS_Selector;
+ } else {
+ m_TextPlane.MoveNext();
+ m_ModeStack.Push(FDE_CSSSYNTAXMODE_RuleSet);
+ SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
+ return FDE_CSSSYNTAXSTATUS_DeclOpen;
+ }
+ break;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0) {
+ return FDE_CSSSYNTAXSTATUS_Selector;
+ }
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_PropertyName:
+ switch (wch) {
+ case ':':
+ m_TextPlane.MoveNext();
+ SwitchMode(FDE_CSSSYNTAXMODE_PropertyValue);
+ return FDE_CSSSYNTAXSTATUS_PropertyName;
+ case '}':
+ m_TextPlane.MoveNext();
+ if (RestoreMode()) {
+ return FDE_CSSSYNTAXSTATUS_DeclClose;
+ } else {
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
+ }
+ break;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0) {
+ return FDE_CSSSYNTAXSTATUS_PropertyName;
+ }
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_PropertyValue:
+ switch (wch) {
+ case ';':
+ m_TextPlane.MoveNext();
+ case '}':
+ SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
+ return FDE_CSSSYNTAXSTATUS_PropertyValue;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0) {
+ return FDE_CSSSYNTAXSTATUS_PropertyValue;
+ }
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_Comment:
+ if (wch == '/' && m_TextData.GetLength() > 0
+ && m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') {
+ RestoreMode();
+ } else {
+ m_TextData.AppendChar(wch);
+ }
+ m_TextPlane.MoveNext();
+ break;
+ case FDE_CSSSYNTAXMODE_MediaType:
+ switch (wch) {
+ case ',':
+ m_TextPlane.MoveNext();
+ SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
+ if (m_iTextDatLen > 0) {
+ return FDE_CSSSYNTAXSTATUS_MediaType;
+ }
+ break;
+ case '{': {
+ FDE_CSSSYNTAXMODE *pMode = m_ModeStack.GetTopElement();
+ if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_MediaRule) {
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
+ }
+ if (m_TextData.GetLength() > 0) {
+ SaveTextData();
+ return FDE_CSSSYNTAXSTATUS_MediaType;
+ } else {
+ m_TextPlane.MoveNext();
+ *pMode = FDE_CSSSYNTAXMODE_RuleSet;
+ SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
+ return FDE_CSSSYNTAXSTATUS_DeclOpen;
+ }
+ }
+ break;
+ case ';': {
+ FDE_CSSSYNTAXMODE *pMode = m_ModeStack.GetTopElement();
+ if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_Import) {
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
+ }
+ if (m_TextData.GetLength() > 0) {
+ SaveTextData();
+ if (IsImportEnabled()) {
+ return FDE_CSSSYNTAXSTATUS_MediaType;
+ }
+ } else {
+ FX_BOOL bEnabled = IsImportEnabled();
+ m_TextPlane.MoveNext();
+ m_ModeStack.Pop();
+ SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
+ if (bEnabled) {
+ DisableImport();
+ return FDE_CSSSYNTAXSTATUS_ImportClose;
+ }
+ }
+ }
+ break;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0) {
+ return FDE_CSSSYNTAXSTATUS_MediaType;
+ }
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_URI: {
+ FDE_CSSSYNTAXMODE *pMode = m_ModeStack.GetTopElement();
+ if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_Import) {
+ return m_eStatus = FDE_CSSSYNTAXSTATUS_Error;
+ }
+ if (wch <= ' ' || wch == ';') {
+ FX_INT32 iURIStart, iURILength = m_TextData.GetLength();
+ if (iURILength > 0 && FDE_ParseCSSURI(m_TextData.GetBuffer(), iURILength, iURIStart, iURILength)) {
+ m_TextData.Subtract(iURIStart, iURILength);
+ SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
+ if (IsImportEnabled()) {
+ return FDE_CSSSYNTAXSTATUS_URI;
+ } else {
+ break;
+ }
+ }
+ }
+ AppendChar(wch);
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_AtRule:
+ if (wch > ' ') {
+ AppendChar(wch);
+ } else {
+ FX_INT32 iLen = m_TextData.GetLength();
+ FX_LPCWSTR psz = m_TextData.GetBuffer();
+ if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) {
+ SwitchMode(FDE_CSSSYNTAXMODE_Charset);
+ } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) {
+ m_ModeStack.Push(FDE_CSSSYNTAXMODE_Import);
+ SwitchMode(FDE_CSSSYNTAXMODE_URI);
+ if (IsImportEnabled()) {
+ return FDE_CSSSYNTAXSTATUS_ImportRule;
+ } else {
+ break;
+ }
+ } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) {
+ m_ModeStack.Push(FDE_CSSSYNTAXMODE_MediaRule);
+ SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
+ return FDE_CSSSYNTAXSTATUS_MediaRule;
+ } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) {
+ SwitchMode(FDE_CSSSYNTAXMODE_Selector);
+ return FDE_CSSSYNTAXSTATUS_FontFaceRule;
+ } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) {
+ SwitchMode(FDE_CSSSYNTAXMODE_Selector);
+ return FDE_CSSSYNTAXSTATUS_PageRule;
+ } else {
+ SwitchMode(FDE_CSSSYNTAXMODE_UnknownRule);
+ }
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_Charset:
+ if (wch == ';') {
+ m_TextPlane.MoveNext();
+ SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
+ if (IsCharsetEnabled()) {
+ DisableCharset();
+ if (m_iTextDatLen > 0) {
+ if (m_pStream != NULL) {
+ FX_WORD wCodePage = FX_GetCodePageFormStringW(m_TextData.GetBuffer(), m_iTextDatLen);
+ if (wCodePage < 0xFFFF && m_pStream->GetCodePage() != wCodePage) {
+ m_pStream->SetCodePage(wCodePage);
+ }
+ }
+ return FDE_CSSSYNTAXSTATUS_Charset;
+ }
+ }
+ } else {
+ AppendChar(wch);
+ }
+ break;
+ case FDE_CSSSYNTAXMODE_UnknownRule:
+ if (wch == ';') {
+ SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
+ }
+ m_TextPlane.MoveNext();
+ break;
+ default:
+ FXSYS_assert(FALSE);
+ break;
+ }
+ }
+ }
+ return m_eStatus;
+}
+FX_BOOL CFDE_CSSSyntaxParser::IsImportEnabled() const
+{
+ if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) {
+ return FALSE;
+ }
+ if (m_ModeStack.GetSize() > 1) {
+ return FALSE;
+ }
+ return TRUE;
+}
+inline FX_BOOL CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch)
+{
+ m_TextPlane.MoveNext();
+ if (m_TextData.GetLength() > 0 || wch > ' ') {
+ m_TextData.AppendChar(wch);
+ return TRUE;
+ }
+ return FALSE;
+}
+inline FX_INT32 CFDE_CSSSyntaxParser::SaveTextData()
+{
+ m_iTextDatLen = m_TextData.TrimEnd();
+ m_TextData.Clear();
+ return m_iTextDatLen;
+}
+inline void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode)
+{
+ m_eMode = eMode;
+ SaveTextData();
+}
+inline FX_INT32 CFDE_CSSSyntaxParser::SwitchToComment()
+{
+ FX_INT32 iLength = m_TextData.GetLength();
+ m_ModeStack.Push(m_eMode);
+ SwitchMode(FDE_CSSSYNTAXMODE_Comment);
+ return iLength;
+}
+inline FX_BOOL CFDE_CSSSyntaxParser::RestoreMode()
+{
+ FDE_CSSSYNTAXMODE *pMode = m_ModeStack.GetTopElement();
+ if (pMode == NULL) {
+ return FALSE;
+ }
+ SwitchMode(*pMode);
+ m_ModeStack.Pop();
+ return TRUE;
+}
+FX_LPCWSTR CFDE_CSSSyntaxParser::GetCurrentString(FX_INT32 &iLength) const
+{
+ iLength = m_iTextDatLen;
+ return m_TextData.GetBuffer();
+}
+CFDE_CSSTextBuf::CFDE_CSSTextBuf()
+ : m_bExtBuf(FALSE)
+ , m_pBuffer(NULL)
+ , m_iBufLen(0)
+ , m_iDatLen(0)
+ , m_iDatPos(0)
+{
+}
+CFDE_CSSTextBuf::~CFDE_CSSTextBuf()
+{
+ Reset();
+}
+void CFDE_CSSTextBuf::Reset()
+{
+ if (!m_bExtBuf && m_pBuffer != NULL) {
+ FDE_Free(m_pBuffer);
+ m_pBuffer = NULL;
+ }
+ m_iDatPos = m_iDatLen = m_iBufLen;
+}
+FX_BOOL CFDE_CSSTextBuf::AttachBuffer(FX_LPCWSTR pBuffer, FX_INT32 iBufLen)
+{
+ Reset();
+ m_pBuffer = (FX_LPWSTR)pBuffer;
+ m_iDatLen = m_iBufLen = iBufLen;
+ return m_bExtBuf = TRUE;
+}
+FX_BOOL CFDE_CSSTextBuf::EstimateSize(FX_INT32 iAllocSize)
+{
+ FXSYS_assert(iAllocSize > 0);
+ Clear();
+ m_bExtBuf = FALSE;
+ return ExpandBuf(iAllocSize);
+}
+FX_INT32 CFDE_CSSTextBuf::LoadFromStream(IFX_Stream *pTxtStream, FX_INT32 iStreamOffset, FX_INT32 iMaxChars, FX_BOOL &bEOS)
+{
+ FXSYS_assert(iStreamOffset >= 0 && iMaxChars > 0);
+ Clear();
+ m_bExtBuf = FALSE;
+ if (!ExpandBuf(iMaxChars)) {
+ return 0;
+ }
+ pTxtStream->Lock();
+ if (pTxtStream->GetPosition() != iStreamOffset) {
+ pTxtStream->Seek(FX_STREAMSEEK_Begin, iStreamOffset);
+ }
+ m_iDatLen = pTxtStream->ReadString(m_pBuffer, iMaxChars, bEOS);
+ pTxtStream->Unlock();
+ return m_iDatLen;
+}
+FX_BOOL CFDE_CSSTextBuf::ExpandBuf(FX_INT32 iDesiredSize)
+{
+ if (m_bExtBuf) {
+ return FALSE;
+ } else if (m_pBuffer == NULL) {
+ m_pBuffer = (FX_LPWSTR)FDE_Alloc(iDesiredSize * sizeof(FX_WCHAR));
+ } else if (m_iBufLen != iDesiredSize) {
+ m_pBuffer = (FX_LPWSTR)FDE_Realloc(m_pBuffer, iDesiredSize * sizeof(FX_WCHAR));
+ } else {
+ return TRUE;
+ }
+ if (m_pBuffer == NULL) {
+ m_iBufLen = 0;
+ return FALSE;
+ } else {
+ m_iBufLen = iDesiredSize;
+ return TRUE;
+ }
+}
+void CFDE_CSSTextBuf::Subtract(FX_INT32 iStart, FX_INT32 iLength)
+{
+ FXSYS_assert(iStart >= 0 && iLength > 0);
+ if (iLength > m_iDatLen - iStart) {
+ iLength = m_iDatLen - iStart;
+ }
+ if (iLength < 0) {
+ iLength = 0;
+ } else {
+ FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR));
+ }
+ m_iDatLen = iLength;
+}