svg_loader: ommiting xml entities in the svg file (#278)

SVG files created using 'sketch' may contain xml entities,
which are not understandable by the svg loader.
For now only '"' is ommited.
This commit is contained in:
Mira Grudzinska 2021-03-23 01:22:46 +01:00 committed by GitHub
parent 79f1ba8516
commit 234a9b2f93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 13 deletions

View file

@ -89,6 +89,69 @@ static const char* _simpleXmlUnskipWhiteSpace(const char* itr, const char* itrSt
} }
static const char* _simpleXmlSkipXmlEntities(const char* itr, const char* itrEnd)
{
auto p = itr;
while (*itr == '&' && itr < itrEnd) {
for (int i = 0; i < NUMBER_OF_XML_ENTITIES; ++i) {
if (strncmp(itr, xmlEntity[i], xmlEntityLength[i]) == 0) {
itr += xmlEntityLength[i];
break;
}
}
if (itr == p) break;
p = itr;
}
return itr;
}
static const char* _simpleXmlUnskipXmlEntities(const char* itr, const char* itrStart)
{
auto p = itr;
while (*(itr - 1) == ';' && itr > itrStart) {
for (int i = 0; i < NUMBER_OF_XML_ENTITIES; ++i) {
if (itr - xmlEntityLength[i] > itrStart &&
strncmp(itr - xmlEntityLength[i], xmlEntity[i], xmlEntityLength[i]) == 0) {
itr -= xmlEntityLength[i];
break;
}
}
if (itr == p) break;
p = itr;
}
return itr;
}
static const char* _skipWhiteSpacesAndXmlEntities(const char* itr, const char* itrEnd)
{
itr = _simpleXmlSkipWhiteSpace(itr, itrEnd);
auto p = itr;
while (true) {
if (p != (itr = _simpleXmlSkipXmlEntities(itr, itrEnd))) p = itr;
else break;
if (p != (itr = _simpleXmlSkipWhiteSpace(itr, itrEnd))) p = itr;
else break;
}
return itr;
}
static const char* _unskipWhiteSpacesAndXmlEntities(const char* itr, const char* itrStart)
{
itr = _simpleXmlUnskipWhiteSpace(itr, itrStart);
auto p = itr;
while (true) {
if (p != (itr = _simpleXmlUnskipXmlEntities(itr, itrStart))) p = itr;
else break;
if (p != (itr = _simpleXmlUnskipWhiteSpace(itr, itrStart))) p = itr;
else break;
}
return itr;
}
static const char* _simpleXmlFindStartTag(const char* itr, const char* itrEnd) static const char* _simpleXmlFindStartTag(const char* itr, const char* itrEnd)
{ {
return (const char*)memchr(itr, '<', itrEnd - itr); return (const char*)memchr(itr, '<', itrEnd - itr);
@ -144,7 +207,7 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr
if (!buf || !func) return false; if (!buf || !func) return false;
while (itr < itrEnd) { while (itr < itrEnd) {
const char* p = _simpleXmlSkipWhiteSpace(itr, itrEnd); const char* p = _skipWhiteSpacesAndXmlEntities(itr, itrEnd);
const char *key, *keyEnd, *value, *valueEnd; const char *key, *keyEnd, *value, *valueEnd;
char* tval; char* tval;
@ -163,9 +226,9 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr
if (!value) return false; if (!value) return false;
value++; value++;
} }
for (; value < itrEnd; value++) { keyEnd = _simpleXmlUnskipXmlEntities(keyEnd, key);
if (!isspace((unsigned char)*value)) break;
} value = _skipWhiteSpacesAndXmlEntities(value, itrEnd);
if (value == itrEnd) return false; if (value == itrEnd) return false;
if ((*value == '"') || (*value == '\'')) { if ((*value == '"') || (*value == '\'')) {
@ -176,20 +239,28 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr
valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd); valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd);
} }
itr = valueEnd + 1;
value = _skipWhiteSpacesAndXmlEntities(value, itrEnd);
valueEnd = _unskipWhiteSpacesAndXmlEntities(valueEnd, value);
memcpy(tmpBuf, key, keyEnd - key); memcpy(tmpBuf, key, keyEnd - key);
tmpBuf[keyEnd - key] = '\0'; tmpBuf[keyEnd - key] = '\0';
tval = tmpBuf + (keyEnd - key) + 1; tval = tmpBuf + (keyEnd - key) + 1;
memcpy(tval, value, valueEnd - value); int i = 0;
tval[valueEnd - value] = '\0'; while (value < valueEnd) {
value = _simpleXmlSkipXmlEntities(value, valueEnd);
tval[i++] = *value;
value++;
}
tval[i] = '\0';
#ifdef THORVG_LOG_ENABLED #ifdef THORVG_LOG_ENABLED
if (!func((void*)data, tmpBuf, tval)) printf("SVG: Unsupported attributes used [Elements type: %s][Attribute: %s]\n", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type).c_str(), tmpBuf); if (!func((void*)data, tmpBuf, tval)) printf("SVG: Unsupported attributes used [Elements type: %s][Attribute: %s]\n", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type).c_str(), tmpBuf);
#else #else
func((void*)data, tmpBuf, tval); func((void*)data, tmpBuf, tval);
#endif #endif
itr = valueEnd + 1;
} }
return true; return true;
} }
@ -290,8 +361,8 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb
} }
if ((strip) && (type != SimpleXMLType::Error) && (type != SimpleXMLType::CData)) { if ((strip) && (type != SimpleXMLType::Error) && (type != SimpleXMLType::CData)) {
start = _simpleXmlSkipWhiteSpace(start, end); start = _skipWhiteSpacesAndXmlEntities(start, end);
end = _simpleXmlUnskipWhiteSpace(end, start + 1); end = _unskipWhiteSpacesAndXmlEntities(end, start);
} }
CB(type, start, end); CB(type, start, end);
@ -307,7 +378,8 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb
const char *p, *end; const char *p, *end;
if (strip) { if (strip) {
p = _simpleXmlSkipWhiteSpace(itr, itrEnd); p = itr;
p = _skipWhiteSpacesAndXmlEntities(p, itrEnd);
if (p) { if (p) {
CB(SimpleXMLType::Ignored, itr, p); CB(SimpleXMLType::Ignored, itr, p);
itr = p; itr = p;
@ -318,7 +390,7 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb
if (!p) p = itrEnd; if (!p) p = itrEnd;
end = p; end = p;
if (strip) end = _simpleXmlUnskipWhiteSpace(end, itr); if (strip) end = _unskipWhiteSpacesAndXmlEntities(end, itr);
if (itr != end) CB(SimpleXMLType::Data, itr, end); if (itr != end) CB(SimpleXMLType::Data, itr, end);
@ -393,7 +465,7 @@ const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength)
//User skip tagname and already gave it the attributes. //User skip tagname and already gave it the attributes.
if (*itr == '=') return buf; if (*itr == '=') return buf;
} else { } else {
itr = _simpleXmlSkipWhiteSpace(itr + 1, itrEnd); itr = _simpleXmlUnskipXmlEntities(itr, buf);
if (itr == itrEnd) return nullptr; if (itr == itrEnd) return nullptr;
return itr; return itr;
} }

View file

@ -25,6 +25,10 @@
#include "tvgSvgLoaderCommon.h" #include "tvgSvgLoaderCommon.h"
#define NUMBER_OF_XML_ENTITIES 8
const char* const xmlEntity[] = {"&quot;", "&nbsp;", "&apos;", "&amp;", "&lt;", "&gt;", "&#035;", "&#039;"};
const int xmlEntityLength[] = {6, 6, 6, 5, 4, 4, 6, 6};
enum class SimpleXMLType enum class SimpleXMLType
{ {
Open = 0, //!< \<tag attribute="value"\> Open = 0, //!< \<tag attribute="value"\>