/* * X S E A R C H . C P P * * XML push model parsing for MS-SEARCH requests * * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved */ #include "_xml.h" #include // class CNFSearch ------------------------------------------------------------- // SCODE CNFSearch::ScCompleteAttribute (void) { SCODE sc = S_OK; switch (m_state) { case ST_RANGE_TYPE: // Find the range type. // m_state = ST_RANGE; if (0 == wcsncmp (m_sb.PContents(), L"row", m_sb.CchSize())) m_uRT = RANGE_ROW; else if (0 == wcsncmp (m_sb.PContents(), L"url", m_sb.CchSize())) m_uRT = RANGE_URL; else if (0 == wcsncmp (m_sb.PContents(), L"find", m_sb.CchSize())) m_uRT = RANGE_FIND; else m_uRT = RANGE_UNKNOWN; m_sb.Reset(); break; case ST_RANGE_ROWS: // Find the number of rows to retrieve // m_state = ST_RANGE; m_sb.Append (sizeof(WCHAR), L""); m_lcRows = wcstol (m_sb.PContents(), NULL, 10 /* base 10 only */); m_sb.Reset(); break; } return sc; } SCODE CNFSearch::ScCompleteChildren ( /* [in] */ BOOL fEmptyNode, /* [in] */ DWORD dwType, /* [in] */ const WCHAR __RPC_FAR *pwcText, /* [in] */ ULONG ulLen) { SCODE sc = S_OK; switch (m_state) { case ST_SEARCH: Assert (dwType == XML_ELEMENT); m_state = ST_NODOC; break; // Exiting the base repl node // case ST_REPL: Assert (dwType == XML_ELEMENT); m_state = ST_SEARCH; break; case ST_QUERY: Assert (dwType == XML_ELEMENT); m_state = ST_SEARCH; // Set the search text into the context // m_sb.Append (sizeof(WCHAR), L""); sc = m_csc.ScSetSQL (this, m_sb.PContents()); if (FAILED (sc)) goto ret; break; case ST_QUERYENTITY: m_state = ST_QUERY; break; case ST_REPLCOLLBLOB: Assert (dwType == XML_ELEMENT); m_state = ST_REPL; // Set the collblob text into the context // m_sb.Append (sizeof(WCHAR), L""); sc = m_csc.ScSetCollBlob (m_sb.PContents()); if (FAILED (sc)) goto ret; break; case ST_REPLRESTAGLIST: Assert (dwType == XML_ELEMENT); m_state = ST_REPL; break; case ST_REPLRESTAGADD: Assert (dwType == XML_ELEMENT); m_state = ST_REPLRESTAGLIST; // Set the restag text into the context // m_sb.Append (sizeof(WCHAR), L""); sc = m_csc.ScSetResTagAdds (m_sb.PContents()); if (FAILED (sc)) goto ret; break; case ST_RANGE: Assert (XML_ELEMENT == dwType); m_state = ST_SEARCH; // Add the range to the list // m_sb.Append (sizeof(WCHAR), L""); sc = m_csc.ScAddRange (m_uRT, m_sb.PContents(), m_lcRows); if (FAILED (sc)) goto ret; // Clear all range elements // m_uRT = RANGE_UNKNOWN; m_lcRows = 0; break; case ST_GROUP_EXPANSION: Assert (XML_ELEMENT == dwType); m_state = ST_SEARCH; // Add the expansion level to the context // m_sb.Append (sizeof(WCHAR), L""); sc = m_csc.ScSetExpansion (wcstol(m_sb.PContents(), NULL, 10)); if (FAILED (sc)) goto ret; break; } ret: return sc; } SCODE CNFSearch::ScHandleNode ( /* [in] */ DWORD dwType, /* [in] */ DWORD dwSubType, /* [in] */ BOOL fTerminal, /* [in] */ const WCHAR __RPC_FAR *pwcText, /* [in] */ ULONG ulLen, /* [in] */ ULONG ulNamespaceLen, /* [in] */ const WCHAR __RPC_FAR *pwcNamespace, /* [in] */ const ULONG ulNsPrefixLen) { CStackBuffer wsz; LPCWSTR pwszTag; SCODE sc = S_FALSE; UINT cch; switch (dwType) { case XML_ELEMENT: // Construct the full name of the node // cch = ulNamespaceLen + ulLen; pwszTag = wsz.resize(CbSizeWsz(cch)); if (NULL == pwszTag) { sc = E_OUTOFMEMORY; goto ret; } wcsncpy (wsz.get(), pwcNamespace, ulNamespaceLen); wcsncpy (wsz.get() + ulNamespaceLen, pwcText, ulLen); *(wsz.get() + cch) = 0; switch (m_state) { case ST_NODOC: // If this is the topmost node in a propSearch request, // transition to the next state. Since there is no parent // node to provide scoping, FIsTag() cannot be used here! // if (!wcscmp (pwszTag, gc_wszSearchRequest)) { m_state = ST_SEARCH; sc = S_OK; } break; case ST_SEARCH: // Look for our well know node types // if (FIsTag (pwszTag, gc_wszSql)) { m_state = ST_QUERY; m_sb.Reset(); sc = S_OK; } // Check for our top-level repl node. // All repl items should appear inside this node. // Tell our caller this is a REPL request, and // switch our state to ST_REPL. // else if (FIsTag (pwszTag, gc_wszReplNode)) { m_state = ST_REPL; sc = m_csc.ScSetReplRequest (TRUE); if (FAILED (sc)) goto ret; } else if (FIsTag (pwszTag, gc_wszRange)) { m_state = ST_RANGE; m_sb.Reset(); sc = S_OK; } else if (FIsTag (pwszTag, gc_wszExpansion)) { m_state = ST_GROUP_EXPANSION; m_sb.Reset(); sc = S_OK; } break; case ST_REPL: // Handle the nodes under the top-level repl node. // if (FIsTag (pwszTag, gc_wszReplCollBlob)) { m_sb.Reset(); m_state = ST_REPLCOLLBLOB; sc = S_OK; } else if (FIsTag (pwszTag, gc_wszReplResTagList)) { m_sb.Reset(); m_state = ST_REPLRESTAGLIST; sc = S_OK; } break; case ST_REPLRESTAGLIST: // Handle the restag nodes under the restaglist node. // if (FIsTag (pwszTag, gc_wszReplResTagItem)) { m_sb.Reset(); m_state = ST_REPLRESTAGADD; sc = S_OK; } break; } break; case XML_ATTRIBUTE: if (ST_RANGE == m_state) { // Construct the full name of the node // cch = ulNamespaceLen + ulLen; pwszTag = wsz.resize(CbSizeWsz(cch)); if (NULL == pwszTag) { sc = E_OUTOFMEMORY; goto ret; } wcsncpy (wsz.get(), pwcNamespace, ulNamespaceLen); wcsncpy (wsz.get() + ulNamespaceLen, pwcText, ulLen); *(wsz.get() + cch) = 0; // There are two attributes node for the DAV:range // node. DAV:type, and DAV:rows. // if (FIsTag (pwszTag, gc_wszRangeType)) { m_state = ST_RANGE_TYPE; sc = S_OK; } else if (FIsTag (pwszTag, gc_wszRangeRows)) { m_state = ST_RANGE_ROWS; sc = S_OK; } break; } break; case XML_PCDATA: // If this is SQL query data, or repl collblob data, // repl resourcetag data, or any of the range items, // then remember it in our buffer. // if ((m_state == ST_QUERY) || (m_state == ST_REPLCOLLBLOB) || (m_state == ST_REPLRESTAGADD) || (m_state == ST_RANGE_TYPE) || (m_state == ST_RANGE_ROWS) || (m_state == ST_RANGE) || (m_state == ST_GROUP_EXPANSION)) { // Append the current bits to the buffer // m_sb.Append (ulLen * sizeof(WCHAR), pwcText); sc = S_OK; } break; } ret: return sc; }