📄 looseprs.cpp
字号:
tag = NULL;
return XMLPBadAttribute;
}
}
else
{
tag->new_attribute()->name = 0;
}
if(bUseNonQuotedValues)
{
if(bHasDirectives)
{
res = GetString(cur, close,
tag->m_cur_attribute->value,
AttributeValueDirective);
}
else
{
res = GetString(cur, close,
tag->m_cur_attribute->value,
AttributeValueNoQuote);
}
}
else
{
res = GetString(cur, close,
tag->m_cur_attribute->value,
AttributeValue);
}
if(res == GSMissingQuote)
{
delete tag;
tag = NULL;
return XMLPAttributeValueNotQuoted;
}
else if(res != GSFoundExpected)
{
delete tag;
tag = NULL;
return XMLPBadAttribute;
}
}
}
if(m_bStrictCompliance)
{
// error on duplicate attributes
CHXMapStringToOb dupMap;
BOOL bDupFound = FALSE;
XMLAttribute* pAttr = NULL;
for(UINT32 i=0;i<tag->m_numAttributes;++i)
{
pAttr = tag->attribute(i);
void* pLookupValue = NULL;
if(pAttr->name)
{
if(dupMap.Lookup(pAttr->name, pLookupValue))
{
bDupFound = TRUE;
break;
}
else
{
dupMap.SetAt(pAttr->name, NULL);
}
}
}
if(bDupFound)
{
#if defined(XXXEH_CHECK_THIS_IN_AFTER_U2_RELEASE)
return XMLPDupAttribute;
#else /* XXXEH- Back out BAB's fix for PR 9172 because it breaks a lot of
* old content (this rebreaks PR 9172 and fixes PR 12447)
*/
HX_ASSERT(1); //line exists only for setting a breakpoint.
#endif
}
}
return XMLPTag;
}
XMLParseResult
XMLParser::ScanTag(const char* open, const char* close, XMLTag* tag)
{
const char* cur = open+1;
const char* afterclose = close+1;
char cQuote = '"';
CHXXMLEncode xmlStr(m_pEncoding, (BYTE*)cur, close - cur);
UINT16 uLen = 0;
const char* ptr = (const char*)xmlStr.GetNextChar(uLen);
//tag->m_need_close
//tag->m_type;
// check the spacing....
switch (tag->m_type)
{
case XMLEndTag:
{
// scan name...
if (!xmlStr.IsNameValid((const BYTE*)tag->m_name, strlen(tag->m_name)))
{
XMLError* err = NULL;
SetError(err, XMLErrorInvalidName, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
}
}
break;
case XMLPlainTag:
case XMLProcInstTag:
{
// scan tag
if (!xmlStr.IsNameValid((const BYTE*)tag->m_name, strlen(tag->m_name)))
{
XMLError* err = NULL;
SetError(err, XMLErrorInvalidName, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
}
// check PI name
//if (!xmlStr.IsPINameValid(tag->m_name, strlen(tag->m_name)))
//{
// XMLError* err = NULL;
// SetError(err, XMLErrorInvalidPITarget, m_ulTagStartLine, m_ulTagStartCol,
// tag->m_name, strlen(tag->m_name), 0);
// tag->m_errs->Add(err);
// }
// check the spacing.
enum { InTagName, InTag, InBeginAttributeName, InAttributeName,
InEndAttributeName, InBeginAttributeValue, InAttributeValue, Done } state;
state = InTagName;
for (const char* pos = cur; *pos && pos < close && state != Done;
pos = (const char*)xmlStr.GetNextChar(uLen))
{
switch (state)
{
case InTagName:
{
// go to first white space
if ( isspace(*pos) )
{
state = InBeginAttributeName;
}
else if ( *pos == '>' )
{
// done
state = Done;
}
}
break;
case InTag:
{
if ( *pos == '>' || (*pos == '/' &&
*(pos+1) == '>'))
{
// done.
state = Done;
}
else
{
// grab the first char... keep it and switch states.
// it should be a space...
state = InBeginAttributeName;
if (!isspace(*pos))
{
XMLError* err = NULL;
SetError(err, XMLErrorMissingReqSpace, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
}
}
}
break;
case InBeginAttributeName:
{
if ( isspace(*pos) )
{
// continue...
}
else if ( *pos == '=' )
{
XMLError* err = NULL;
SetError(err, XMLErrorMissingEquals, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
state = InBeginAttributeValue;
}
else if ( *pos == '>' || (*pos == '/'
&& *(pos+1) == '>'))
{
// done
state = Done;
}
else
{
state = InAttributeName;
}
}
break;
case InAttributeName:
{
if ( isspace(*pos) )
{
state = InEndAttributeName;
}
else if ( *pos == '=' )
{
state = InBeginAttributeValue;
}
else if ( *pos == '>' )
{
XMLError* err = NULL;
SetError(err, XMLErrorMissingEquals, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
// done
state = Done;
}
else if (*pos == '\'' || *pos == '"')
{
XMLError* err = NULL;
SetError(err, XMLErrorBadAttribute, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
cQuote = *pos;
state = InAttributeValue;
}
}
break;
case InEndAttributeName:
{
if ( isspace(*pos) )
{
// continue..
}
else if ( *pos == '=' )
{
state = InBeginAttributeValue;
}
else if ( *pos == '>' )
{
XMLError* err = NULL;
SetError(err, XMLErrorMissingEquals, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
state = Done;
}
else
{
// hmm. we got a non whitespace before the =
//First, let's see if we have a ["] or a [']
// (i.e., an attribute value start) in which
// case the author must have forgotten to
// put an '=' between the name/value pair.
// In this case, we need to keep the renderers
// from firing off an error with old bad content,
// so we pretend we're in the "InAttributeValue"
// state:
if ( *pos == '\'' )
{
XMLError* err = NULL;
SetError(err, XMLErrorBadAttribute, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
cQuote = *pos;
state = InAttributeValue;
}
else if ( *pos == '\"' )
{
XMLError* err = NULL;
SetError(err, XMLErrorBadAttribute, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
cQuote = *pos;
state = InAttributeValue;
}
else
{
XMLError* err = NULL;
SetError(err, XMLErrorBadAttribute, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
// lets go back to the attribute name state.
state = InAttributeName;
}
}
}
break;
case InBeginAttributeValue:
{
if ( isspace(*pos) )
{
}
else if ( *pos == '\'' || *pos == '\"')
{
cQuote = *pos;
state = InAttributeValue;
}
else if ( *pos == '>' )
{
XMLError* err = NULL;
SetError(err, XMLErrorMissingEquals, m_ulTagStartLine, m_ulTagStartCol,
tag->m_name, strlen(tag->m_name), 0);
tag->m_errs->Add(err);
// done
state = Done;
}
}
break;
case InAttributeValue:
{
if ( *pos == cQuote )
{
state = InTag;
}
}
break;
}
}
}
break;
case XMLCommentTag:
{
// we will not scan...
}
break;
case XMLDirectiveTag:
{
// TODO: scan Directive.
}
break;
}
// error on duplicate attributes
// also validate the names and attributes.
CHXMapStringToOb dupMap;
BOOL bDupFound = FALSE;
XMLAttribute* pAttr = NULL;
const char* name = NULL;
for(UINT32 i=0;i<tag->m_numAttributes;++i)
{
pAttr = tag->attribute(i);
if (!xmlStr.IsNameValid((const BYTE*)pAttr->name, strlen(pAttr->name)))
{
XMLError* err = NULL;
SetError(err, XMLErrorInvalidName, m_ulTagStartLine, m_ulTagStartCol,
pAttr->name, strlen(pAttr->name), 0);
tag->m_errs->Add(err);
}
if (!xmlStr.IsAttValueValid((const BYTE*)pAttr->value, strlen(pAttr->value)))
{
XMLError* err = NULL;
SetError(err, XMLErrorInvalidCharInDoc, m_ulTagStartLine, m_ulTagStartCol,
pAttr->value, strlen(pAttr->value), 0);
tag->m_errs->Add(err);
}
void* pLookupValue = NULL;
if(pAttr->name)
{
if(dupMap.Lookup(pAttr->name, pLookupValue))
{
name = pAttr->name;
bDupFound = TRUE;
break;
}
else
{
dupMap.SetAt(pAttr->name, NULL);
}
}
}
if (bDupFound)
{
XMLError* err = NULL;
SetError(err, XMLErrorDupAttribute, m_ulTagStartLine, m_ulTagStartCol,
name, strlen(name), 0);
tag->m_errs->Add(err);
}
return XMLPTag;
}
void XMLParser::SetEncoding(const char* pszEncoding)
{
if (pszEncoding)
{
INT32 lLen = strlen(pszEncoding);
if (lLen > 0)
{
HX_VECTOR_DELETE(m_pEncoding);
m_pEncoding = new char [lLen + 1];
if (m_pEncoding)
{
strcpy(m_pEncoding, pszEncoding);
}
}
}
}
HX_RESULT XMLParser::GetEncoding(REF(char*) rpszEncoding)
{
HX_RESULT retVal = HXR_FAIL;
if (m_pEncoding)
{
HX_VECTOR_DELETE(rpszEncoding);
rpszEncoding = new char [strlen(m_pEncoding) + 1];
if (rpszEncoding)
{
strcpy(rpszEncoding, m_pEncoding);
retVal = HXR_OK;
}
}
return retVal;
}
void
XMLParser::SetError(REF(XMLError*) pErr, XMLErrorTag tag, INT32 lLine,
INT32 lPos, const char* pErrorText, INT32 lErrorTextLen,
const char* pFrameText)
{
HX_DELETE(m_pLastError);
INT32 lTextLen =
(lErrorTextLen > MAX_ERROR_LEN) ? MAX_ERROR_LEN: lErrorTextLen;
char tmpBuf[MAX_ERROR_LEN * 2]; // overdo it a bit...
// convert control characters to spaces
INT32 j = 0;
for(INT32 i = 0; i < lTextLen; ++i)
{
if(iscntrl(pErrorText[i]))
{
tmpBuf[j++] = ' ';
}
else
{
tmpBuf[j++] = pErrorText[i];
}
}
tmpBuf[j] = 0;
pErr = new XMLError(tag, lLine, lPos, tmpBuf, pFrameText);
}
XMLTag::XMLTag(BOOL bStrictCompliance, BOOL bStoreErrors):
m_bStrictCompliance(bStrictCompliance)
{
m_numAttributes = 0;
m_name = NULL;
m_type = XMLPlainTag;
m_need_close = TRUE;
m_errs = NULL;
if (bStoreErrors)
{
m_errs = new CHXPtrArray();
}
}
XMLTag::~XMLTag()
{
UINT32 i;
for(i = 0; i < m_numAttributes; i++)
{
delete (XMLAttribute*)m_attributes[(int)i];
}
HX_VECTOR_DELETE(m_name);
if (m_errs)
{
UINT32 size = m_errs->GetSize();
for(i = 0; i < size; i++)
{
delete (XMLError*)(*m_errs)[(int)i];
}
HX_DELETE(m_errs);
}
}
XMLAttribute*
XMLTag::new_attribute()
{
m_cur_attribute = new XMLAttribute;
m_attributes.SetAtGrow((int)m_numAttributes, m_cur_attribute);
m_numAttributes++;
return m_cur_attribute;
}
const char*
XMLTag::get_attribute(const char* name)
{
for(UINT32 i = 0; i < m_numAttributes; i++)
{
if(((XMLAttribute*)m_attributes[(int)i])->name)
{
if(m_bStrictCompliance)
{
if(strcmp(((XMLAttribute*)m_attributes[(int)i])->name, name) == 0)
{
return (const char*)((XMLAttribute*)m_attributes[(int)i])->value;
}
}
else
{
if(strcasecmp(((XMLAttribute*)m_attributes[(int)i])->name, name) == 0)
{
return (const char*)((XMLAttribute*)m_attributes[(int)i])->value;
}
}
}
}
return NULL;
}
/*
* XMLError methods
*/
XMLError::XMLError(XMLErrorTag errorTag,
INT32 lLineNumber,
INT32 lLinePosition,
const char* pErrorString,
const char* pFrameString):
m_errorTag(errorTag),
m_lLineNumber(lLineNumber),
m_lLinePosition(lLinePosition),
m_pErrorString(0),
m_pFrameString(0)
{
if(pErrorString)
{
m_pErrorString = new_string(pErrorString);
}
if(pFrameString)
{
m_pFrameString = new_string(pFrameString);
}
}
XMLError::~XMLError()
{
delete[] m_pErrorString;
delete[] m_pFrameString;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -