📄 dialplanparser.cpp
字号:
goto exit;
}
break;
case DialingRuleAttributeDial:
case DialingRuleAttributeDisplay:
case DialingRuleAttributeTransfer:
{
TemplateAttribute_t sc_TemplateMappings[3] =
{
{&ThisRule.m_DialString , DRF_TYPE_DIAL_STRING },
{&ThisRule.m_DisplayString , DRF_TYPE_DISPLAY_STRING },
{&ThisRule.m_TransferString, DRF_TYPE_TRANSFER_STRING },
};
// Mapping assumes template-type attributes are grouped together in enum
CASSERT(DialingRuleAttributeDisplay == (DialingRuleAttributeDial + 1));
CASSERT(DialingRuleAttributeTransfer == (DialingRuleAttributeDisplay + 1));
int i = static_cast<int>(RuleAttributeType - DialingRuleAttributeDial);
ASSERT(i < _countof(sc_TemplateMappings));
if ((m_Flags & VALIDATE_XML_ONLY) || (AttributeValueLength == 0))
{
// No need to allocate
ThisRule.m_Flags |= sc_TemplateMappings[i].Flags;
break;
}
hr = DuplicateTemplateString(
pAttributeValue,
AttributeValueLength,
sc_TemplateMappings[i].pTemplate
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to duplicate rule's template(%d). Error 0x%08x -- ", i, hr));
goto exit;
}
ThisRule.m_Flags |= sc_TemplateMappings[i].Flags;
break;
}
case DialingRuleAttributeRestrict:
{
ce::wstring CopyOfCharacters;
const WCHAR* pNextOption = pAttributeValue;
int CharactersToRead = AttributeValueLength;
while (pNextOption && SUCCEEDED(hr))
{
const WCHAR *pOption = pNextOption;
int OptionIndex;
while ((CharactersToRead > 0) && (*pNextOption != L','))
{
pNextOption++;
CharactersToRead--;
}
// Make a copy of the current option
if (!CopyOfCharacters.assign(pOption, (pNextOption - pOption)))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to allocate restrict option"));
// break out of this loop
hr = E_OUTOFMEMORY;
break;
}
// Remove any spaces it could have
CopyOfCharacters.trim(sc_Spaces);
CASSERT(UnknownOption == _countof(sc_RestrictOptions));
CASSERT(DRF_RESTRICT_OPTION_VOIP == (DRF_RESTRICT_OPTION_VOIP << RestrictOptionVoIP));
CASSERT(DRF_RESTRICT_OPTION_CELL == (DRF_RESTRICT_OPTION_VOIP << RestrictOptionCell));
CASSERT(DRF_RESTRICT_OPTION_SMS == (DRF_RESTRICT_OPTION_VOIP << RestrictOptionSMS));
OptionIndex = FindString(
CopyOfCharacters.get_buffer(),
CopyOfCharacters.length(),
sc_RestrictOptions,
_countof(sc_RestrictOptions)
);
switch (OptionIndex)
{
case RestrictOptionVoIP:
case RestrictOptionCell:
case RestrictOptionSMS:
if (ThisRule.m_Flags & (DRF_RESTRICT_OPTION_VOIP << OptionIndex))
{
// Do not allow invalid syntax (duplicated option)
hr = E_UNEXPECTED;
}
else
{
// Enable the restriction
ThisRule.m_Flags |= (DRF_RESTRICT_OPTION_VOIP << OptionIndex);
}
break;
case RestrictOptionAll:
hr = (ThisRule.m_Flags & DRF_RESTRICT_OPTION_ALL) ? E_UNEXPECTED : S_OK;
ThisRule.m_Flags |= DRF_RESTRICT_OPTION_ALL;
break;
default:
ASSERT(UnknownOption == OptionIndex);
hr = E_INVALIDARG;
break;
}
// Skip over the separator; if there are no more characters to read
// then there is no next option
if (CharactersToRead > 0)
{
pNextOption++;
CharactersToRead--;
}
else
{
pNextOption = NULL;
}
}
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Invalid restrict option(s). Error 0x%08x -- ", hr));
goto exit;
}
}
break;
default:
ASSERT(UnknownAttribute == RuleAttributeType);
// Ignore unknown attribute
break;
}
}
// A rule must be defined by the regular expression and
// should define at least another supported attribute
ASSERT((ThisRule.m_RegexString != NULL) && (ThisRule.m_Flags & DRF_ALL_FLAGS_MASK));
pNewRule = new DialingRule_t();
*pNewRule = ThisRule;
if (!m_NewDialingRules.push_back(pNewRule))
{
delete pNewRule;
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to push rule into queue"));
hr = E_OUTOFMEMORY;
}
exit:
if (FAILED(hr))
{
ThisRule.CleanUpDialingRule();
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot process dialing rule. Error 0x%08x -- ", hr));
}
return hr;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::ProcessAutoDial
Parses a auto dial element and processes it at the same time
Parameters:
: IN - ISAXAttributes* - The attributes of the rule
Returns:
- S_OK returned if no errors occur
- Error code returned otherwise
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::ProcessAutoDial(
ISAXAttributes * pAttributes
)
{
HRESULT hr;
AutoDialRule_t ThisRule;
AutoDialRule_t* pNewRule;
int NumberOfAttributes;
int Index;
if (pAttributes == NULL)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Missing dialing rule attributes"));
return E_INVALIDARG;
}
hr = pAttributes->getLength(&NumberOfAttributes);
if (FAILED(hr) || (NumberOfAttributes != 2))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Missing dialing rule attributes. Error 0x%08x -- ", hr));
return hr;
}
// Reset rule's structure
memset(&ThisRule, 0, sizeof(ThisRule));
// Process the rule attributes
for (Index = 0; Index < NumberOfAttributes; Index++)
{
const wchar_t* pAttributeName;
const wchar_t* pAttributeValue;
int AttributeNameLength;
int AttributeValueLength;
AutoDialAttribute_e AutoDialAttributeType;
hr = pAttributes->getLocalName(Index, &pAttributeName, &AttributeNameLength);
if (FAILED(hr))
{
ASSERT(0);
goto exit;
}
hr = GetAutoDialAttributeType(pAttributeName,AttributeNameLength, &AutoDialAttributeType);
if (FAILED(hr))
{
ASSERT(0);
goto exit;
}
hr = pAttributes->getValue(Index, &pAttributeValue, &AttributeValueLength);
if (FAILED(hr))
{
ASSERT(0);
goto exit;
}
TraceDialingRuleAttribute(
L"%s=%s",
pAttributeName,
AttributeNameLength,
pAttributeValue,
AttributeValueLength
);
switch (AutoDialAttributeType)
{
case AutoDialAttributePrefix:
if (pAttributeValue != NULL)
{
ThisRule.m_Prefix = SysAllocStringLen(pAttributeValue, AttributeValueLength);
if (ThisRule.m_Prefix == NULL)
{
hr = E_OUTOFMEMORY;
goto exit;
}
ThisRule.m_PrefixLength = AttributeValueLength;
}
break;
case AutoDialAttributeLength:
if (pAttributeValue != NULL)
{
hr = ConvertAttributeToNumber(pAttributeValue, AttributeValueLength, &ThisRule.m_TotalLength);
if (FAILED(hr))
{
goto exit;
}
}
break;
default:
ASSERT(UnknownAutoDialAttribute == AutoDialAttributeType);
// Ignore unknown attribute
break;
}
}
pNewRule = new AutoDialRule_t();
*pNewRule = ThisRule;
if (!m_NewAutoDialRules.push_back(pNewRule))
{
delete pNewRule;
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - Failed to push rule into queue"));
hr = E_OUTOFMEMORY;
}
exit:
if (FAILED(hr))
{
ThisRule.CleanUpAutoDialRule();
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot process dialing rule. Error 0x%08x -- ", hr));
}
return hr;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::ProcessXML
Parses the XML and processes it at the same time
Parameters:
: IN - BSTR - The XML string for the dial plan
Returns:
- S_OK returned if no errors occur
- Error code returned if the operation fails
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::ProcessXML(
BSTR DialPlan,
BOOL ValidateOnly
)
{
HRESULT hr;
CComPtr<ISAXXMLReader> cpISAXReader;
VARIANT varXML;
VariantInit(&varXML);
if ((m_Flags & PROCESSING_XML) || !(m_Flags & FLUSHED_NEW_RULES))
{
return E_FAIL;
}
m_Flags |= PROCESSING_XML;
m_Flags &= ~FLUSHED_NEW_RULES;
if (ValidateOnly)
{
m_Flags |= VALIDATE_XML_ONLY;
}
// Instantiate the SAX reader and add our event hook
hr = cpISAXReader.CoCreateInstance(__uuidof(SAXXMLReader));
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot co create the SAX XML reader. Error 0x%08x -- ", hr));
goto exit;
}
hr = cpISAXReader->putContentHandler(this);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot register ContentHandler. Error 0x%08x -- ", hr));
goto exit;
}
// Create regular expression parser once
if (m_pIRegularExpressionParser == NULL)
{
hr = CreateRegularExpression(&m_pIRegularExpressionParser);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to create Regex parser. Error 0x%08x -- ", hr));
goto exit;
}
}
static const WCHAR sc_FileScheme[] = L"file:\\\\";
if (0 != PhoneAppUtilities_t::InvStrCmpNI(
DialPlan,
sc_FileScheme,
_countof(sc_FileScheme)-1
))
{
varXML.vt = VT_BSTR;
varXML.bstrVal = DialPlan;
// Parse the XML and process it at the same time
hr = cpISAXReader->parse(varXML);
}
else
{
// Parse XML from file and process it at the same time
hr = cpISAXReader->parseURL(DialPlan);
}
// Always reset the stack
m_ElementsStack.clear();
// Clear token buffers
m_XMLTokens[DialPlanTokenHost].m_Value.clear();
if (m_pIRegularExpressionParser != NULL)
{
m_pIRegularExpressionParser->Release();
m_pIRegularExpressionParser = NULL;
}
exit:
m_Flags &= ~(PROCESSING_XML | VALIDATE_XML_ONLY);
if (FAILED(hr))
{
// Discard any new rules that could have been created
FlushNewRules(FlushOperationDiscard);
}
return hr;
}
/*------------------------------------------------------------------------------
DialPlanParser_t::ValidateBooleanAttribute
Validates a boolean attribute
Parameters:
: IN - const WCHAR* - The attribute's value
: IN - int - The length of the value
: OUT - bool* - The attribute's boolean value
Returns:
- S_OK returned if is a valid boolen value
- E_INVALIDARG returned otherwise
------------------------------------------------------------------------------*/
HRESULT
DialPlanParser_t::ValidateBooleanAttribute(
const WCHAR *pAttributeValue,
int AttributeValueLength,
bool *pEnabled
)
{
static const WCHAR sc_BooleanValueTrue[] = L"true";
static const WCHAR sc_BooleanValueFalse[] = L"false";
ASSERT(pEnabled);
if (((AttributeValueLength == 1) && (pAttributeValue[0] == L'1')) ||
(AttributeValueLength == _countof(sc_BooleanValueTrue)-1) &&
(0 == PhoneAppUtilities_t::InvStrCmpNI(sc_BooleanValueTrue, pAttributeValue, AttributeValueLength)))
{
*pEnabled = true;
return S_OK;
}
else if (((AttributeValueLength == 1) && (pAttributeValue[0] == L'0')) ||
(AttributeValueLength == _countof(sc_BooleanValueFalse)-1) &&
(0 == PhoneAppUtilities_t::InvStrCmpNI(sc_BooleanValueFalse, pAttributeValue, AttributeValueLength)))
{
*pEnabled = false;
return S_OK;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -