📄 dialplanparser.cpp
字号:
*pEnabled = false;
return E_INVALIDARG;
}
}
/*------------------------------------------------------------------------------
DialPlanParser_t::ValidateRegularExpressionAttribute
Validates a regular expression attribute
Parameters:
: IN - const WCHAR* - The attribute's value
: IN - int - The length of the value
: OUT - BSTR* - The regular expression string
Returns:
- S_OK returned if is a valid regular expression
- E_OUTOFMEMORY returned if allocation fails
- Error code returned otherwise
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::ValidateRegularExpressionAttribute(
const WCHAR *pAttributeValue,
int AttributeValueLength,
BSTR* pRegexString
)
{
HRESULT hr;
ce::auto_bstr CopyOfRegexString;
ASSERT(pRegexString);
*pRegexString = NULL;
CopyOfRegexString = SysAllocStringLen(pAttributeValue, AttributeValueLength);
if (CopyOfRegexString == NULL)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to allocate rule's regex string"));
return E_OUTOFMEMORY;
}
// Validate regular expression
hr = m_pIRegularExpressionParser->SetExpression(CopyOfRegexString);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Invalid regular expression. Error 0x%08x -- ", hr));
return hr;
}
*pRegexString = CopyOfRegexString.release();
return S_OK;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::ValidateDialPlan
Validates XML dial plan
Parameters:
: IN - BSTR - The element's name space URI
Returns:
- S_OK returned if no errors occur
- Error code returned otherwise
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::ValidateDialPlan(
BSTR DialPlanXML
)
{
HRESULT hr;
if (DialPlanXML == NULL)
{
return E_INVALIDARG;
}
// Parse the XML (Validate only)
hr = ProcessXML(DialPlanXML, TRUE);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to parse custom dial plan. Error 0x%08x -- ", hr));
return hr;
}
DebugDumpDialingRuleQueue(&m_NewDialingRules);
DebugDumpAutoDialRuleQueue(&m_NewAutoDialRules);
// Discard any new rules that could have been created
FlushNewRules(FlushOperationDiscard);
return hr;
}
////////////////////////////////////////////////////////////////////////////////
// IUnknown
/*------------------------------------------------------------------------------
DialPlanParser_t::AddRef
IUnknown::AddRef - adds a reference to the object
------------------------------------------------------------------------------*/
ULONG
DialPlanParser_t::AddRef(
void
)
{
InterlockedIncrement(reinterpret_cast<LONG*>(&m_RefCount));
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_REFCOUNT, (L"New ref count: %d", m_RefCount));
return m_RefCount;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::Release
IUnknown::Release implementation
------------------------------------------------------------------------------*/
ULONG
DialPlanParser_t::Release(
void
)
{
LONG cRet = InterlockedDecrement(reinterpret_cast<LONG*>(&m_RefCount));
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_REFCOUNT, (L"New ref count: %d", cRet));
if (cRet == 0)
{
delete this;
}
return cRet;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::QueryInterface
IUnknown::QueryInterface implementation
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::QueryInterface(
REFIID riid,
void** ppvObject
)
{
if (! ppvObject)
{
return E_POINTER;
}
if (riid == IID_IUnknown)
{
*ppvObject = static_cast<IUnknown*>(this);
}
else if (riid == IID_ISAXContentHandler)
{
*ppvObject = static_cast<ISAXContentHandler*>(this);
}
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppvObject)->AddRef();
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////
// ISAXContentHandler methods
/*------------------------------------------------------------------------------
DialPlanParser_t::characters
Receives notification of character data
Parameters:
: IN - const wchar_t* - The character data
: IN - int - The length of the character string
Returns:
- S_OK returned if no errors occur
- E_FAIL returned if the parse operation should be aborted
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::characters(
const wchar_t *pwchChars,
int cchChars
)
{
ce::wstring CopyOfCharacters;
if (DialPlanElementHost != m_ElementsStack.front())
{
// Ignore characters invoked for other elements
return S_OK;
}
if (!CopyOfCharacters.append(pwchChars, cchChars))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to allocate Host string"));
return E_OUTOFMEMORY;
}
// Remove spaces
CopyOfCharacters.trim(sc_Spaces);
// Store these characters in member variable
if (!m_XMLTokens[DialPlanTokenHost].m_Value.append(CopyOfCharacters.get_buffer()))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to allocate Host string"));
return E_OUTOFMEMORY;
}
return S_OK;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::endDocument
Receives notification of the end of document
Parameters:
: none
Returns:
- S_OK returned if no errors occur
- E_FAIL returned if the parse operation should be aborted
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::endDocument(
void
)
{
// XML dial plan must have at least one valid dialing rule
return (m_NewDialingRules.empty() ? E_FAIL : S_OK);
}
/*------------------------------------------------------------------------------
DialPlanParser_t::endElement
Receives notification of the end of an element
Parameters:
: IN - const wchar_t* - The element's name space URI
: IN - int - The length for the namespace URI
: IN - const wchar_t* - The element's local name string
: IN - int - The length of the local name
: IN - const wchar_t* - The QName (with prefix)
: IN - int - The length of the QName
: IN - ISAXAttributes* - The attributes attached to the element
Returns:
- S_OK returned if no errors occur
- E_FAIL returned if the parse operation should be aborted
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::endElement(
const wchar_t *pwchNamespaceUri,
int cchNamespaceUri,
const wchar_t *pwchLocalName,
int cchLocalName,
const wchar_t *pwchQName,
int cchQName
)
{
HRESULT hr;
DialPlanElement_e DialPlanElementType;
TraceDialPlanElement(L"XML End of Element <%s>", pwchLocalName, cchLocalName);
if (m_ElementsStack.empty())
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Unexpected XML End of Element"));
return E_FAIL;
}
hr = GetElementType(pwchLocalName, cchLocalName, &DialPlanElementType);
if (SUCCEEDED(hr))
{
hr = (DialPlanElementType == m_ElementsStack.front()) ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
m_ElementsStack.pop_front();
ASSERT((DialPlanElementStart != DialPlanElementType) || m_ElementsStack.empty());
}
}
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Invalid XML End of Element. Error 0x%08x -- ", hr));
}
return hr;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::startDocument
Receives notification of the beginning of document
Parameters:
: none
Returns:
- S_OK returned if no errors occur
- E_FAIL returned if the parse operation should be aborted
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::startDocument(
void
)
{
// Before parsing the XML the state should be the following:
// 1. No XML elements in the stack
// 2. No new rules
// 3. No auto dial rules
if (!m_ElementsStack.empty() || !m_NewDialingRules.empty() || !m_NewAutoDialRules.empty())
{
ASSERT(0);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Invalid parser state... cannot process XML"));
return E_FAIL;
}
return S_OK;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::startElement
Receives notification of the start of an element
Parameters:
: IN - const wchar_t* - The element's name space URI
: IN - int - The length for the namespace URI
: IN - const wchar_t* - The element's local name string
: IN - int - The length of the local name
: IN - const wchar_t* - The QName (with prefix)
: IN - int - The length of the QName
: IN - ISAXAttributes* - The attributes attached to the element
Returns:
- S_OK returned if no errors occur
- E_FAIL returned if the parse operation should be aborted
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::startElement(
const wchar_t *pwchNamespaceUri,
int cchNamespaceUri,
const wchar_t *pwchLocalName,
int cchLocalName,
const wchar_t *pwchQName,
int cchQName,
ISAXAttributes *pAttributes
)
{
HRESULT hr;
DialPlanElement_e DialPlanElementType;
TraceDialPlanElement(L"XML Start of Element <%s>", pwchLocalName, cchLocalName);
hr = GetElementType(pwchLocalName, cchLocalName, &DialPlanElementType);
if (FAILED(hr))
{
goto exit;
}
// Assume XML is malformed
hr = E_FAIL;
switch (DialPlanElementType)
{
case DialPlanElementStart:
// Opening element must be at level 0
if (m_ElementsStack.empty() &&
(cchNamespaceUri == _countof(sc_NameSpaceURI)-1) &&
(0 == PhoneAppUtilities_t::InvStrCmpNI(
sc_NameSpaceURI,
pwchNamespaceUri,
cchNamespaceUri
)))
{
hr = S_OK;
}
break;
case DialPlanElementHeader:
case DialPlanElementHost:
if (IsXMLElementHierarchyValid(&sc_DialPlanElements[DialPlanElementType]))
{
hr = S_OK;
}
break;
case DialPlanElementRule:
// Rule element must be at level 1
if (!IsXMLElementHierarchyValid(&sc_DialPlanElements[DialPlanElementType]))
{
break;
}
hr = ProcessDialingRule(pAttributes);
if (FAILED(hr) && (hr != E_OUTOFMEMORY))
{
// Ignore this rule... but do not abort XML processing
hr = S_OK;
}
break;
case DialPlanElementAutoDial:
//AutoDial element must be at level 1
if (!IsXMLElementHierarchyValid(&sc_DialPlanElements[DialPlanElementType]))
{
break;
}
hr = ProcessAutoDial(pAttributes);
if (FAILED(hr) && (hr != E_OUTOFMEMORY))
{
// Ignore this rule.. but do not abort XML processing
hr = S_OK;
}
break;
default:
ASSERT(UnknownElement == DialPlanElementType);
break;
}
exit:
if (SUCCEEDED(hr))
{
if (!m_ElementsStack.push_front(DialPlanElementType))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to push XML element into the stack"));
hr = E_OUTOFMEMORY;
}
}
else
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Invalid XML Start of Element. Error 0x%08x -- ", hr));
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -