You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
7.1 KiB
341 lines
7.1 KiB
/*
|
|
* 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 <align.h>
|
|
|
|
// 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<WCHAR> 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;
|
|
}
|