diff options
| author | Markus Engel <markus.engel@tum.de> | 2013-09-14 11:09:15 +0000 |
|---|---|---|
| committer | Markus Engel <markus.engel@tum.de> | 2013-09-14 11:09:15 +0000 |
| commit | f62ab958909134854a42a4654d296988bc724b67 (patch) | |
| tree | 08498b78a0fe1b5e94490a95fe876175e9c179d9 /src/xml/repr-io.cpp | |
| parent | Merged from trunk (r12488). (diff) | |
| parent | fix windows build (diff) | |
| download | inkscape-f62ab958909134854a42a4654d296988bc724b67.tar.gz inkscape-f62ab958909134854a42a4654d296988bc724b67.zip | |
Merged from trunk (r12517).
(bzr r11608.1.121)
Diffstat (limited to 'src/xml/repr-io.cpp')
| -rw-r--r-- | src/xml/repr-io.cpp | 97 |
1 files changed, 78 insertions, 19 deletions
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp index af47779fe..f7e75a83b 100644 --- a/src/xml/repr-io.cpp +++ b/src/xml/repr-io.cpp @@ -98,7 +98,9 @@ public: } } - int setFile( char const * filename ); + int setFile( char const * filename, bool load_entities ); + + xmlDocPtr readXml(); static int readCb( void * context, char * buffer, int len ); static int closeCb( void * context ); @@ -112,12 +114,15 @@ private: FILE* fp; unsigned char firstFew[4]; int firstFewLen; + bool LoadEntities; // Checks for SYSTEM Entities (requires cached data) + std::string cachedData; + unsigned int cachedPos; Inkscape::URI dummy; Inkscape::IO::UriInputStream* instr; Inkscape::IO::GzipInputStream* gzin; }; -int XmlSource::setFile(char const *filename) +int XmlSource::setFile(char const *filename, bool load_entities=false) { int retVal = -1; @@ -174,14 +179,62 @@ int XmlSource::setFile(char const *filename) retVal = 0; // no error } } + if(load_entities) { + this->cachedData = std::string(""); + this->cachedPos = 0; + + // First get data from file in typical way (cache it all) + char *buffer = new char [4096]; + while(true) { + int len = this->read(buffer, 4096); + if(len <= 0) break; + buffer[len] = 0; + this->cachedData += buffer; + } + free(buffer); + + // Check for SYSTEM or PUBLIC entities and remove them from the cache + GMatchInfo *info; + gint start, end; + + GRegex *regex = g_regex_new( + "<!ENTITY\\s+[^>\\s]+\\s+(SYSTEM|PUBLIC\\s+\"[^>\"]+\")\\s+\"[^>\"]+\"\\s*>", + G_REGEX_CASELESS, G_REGEX_MATCH_NEWLINE_ANY, NULL); + + g_regex_match (regex, this->cachedData.c_str(), G_REGEX_MATCH_NEWLINE_ANY, &info); + while (g_match_info_matches (info)) { + if (g_match_info_fetch_pos (info, 1, &start, &end)) + this->cachedData.erase(start, end - start); + g_match_info_next (info, NULL); + } + g_match_info_free(info); + g_regex_unref(regex); + } + // Do this after loading cache, so reads don't return cache to fill cache. + this->LoadEntities = load_entities; return retVal; } +xmlDocPtr XmlSource::readXml() +{ + int parse_options = XML_PARSE_HUGE | XML_PARSE_RECOVER; + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool allowNetAccess = prefs->getBool("/options/externalresources/xml/allow_net_access", false); + if (!allowNetAccess) parse_options |= XML_PARSE_NONET; + + // Allow NOENT only if we're filtering out SYSTEM and PUBLIC entities + if (LoadEntities) parse_options |= XML_PARSE_NOENT; + + return xmlReadIO( readCb, closeCb, this, + filename, getEncoding(), parse_options); +} int XmlSource::readCb( void * context, char * buffer, int len ) { int retVal = -1; + if ( context ) { XmlSource* self = static_cast<XmlSource*>(context); retVal = self->read( buffer, len ); @@ -203,7 +256,15 @@ int XmlSource::read( char *buffer, int len ) int retVal = 0; size_t got = 0; - if ( firstFewLen > 0 ) { + if ( LoadEntities ) { + if (cachedPos >= cachedData.length()) { + return -1; + } else { + retVal = cachedData.copy(buffer, len, cachedPos); + cachedPos += retVal; + return retVal; // Do NOT continue. + } + } else if ( firstFewLen > 0 ) { int some = (len < firstFewLen) ? len : firstFewLen; memcpy( buffer, firstFew, some ); if ( len < firstFewLen ) { @@ -299,22 +360,20 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns) XmlSource src; if ( (src.setFile(filename) == 0) ) { - int parse_options = XML_PARSE_HUGE; // do not use XML_PARSE_NOENT ! see bug lp:1025185 - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool allowNetAccess = prefs->getBool("/options/externalresources/xml/allow_net_access", false); - if (!allowNetAccess) { - parse_options |= XML_PARSE_NONET; + doc = src.readXml(); + rdoc = sp_repr_do_read( doc, default_ns ); + // For some reason, failed ns loading results in this + // We try a system check version of load with NOENT for adobe + if(rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) { + xmlFreeDoc( doc ); + src.setFile(filename, true); + doc = src.readXml(); + rdoc = sp_repr_do_read( doc, default_ns ); } - doc = xmlReadIO( XmlSource::readCb, - XmlSource::closeCb, - &src, - localFilename, - src.getEncoding(), - parse_options); } } - rdoc = sp_repr_do_read( doc, default_ns ); + if ( doc ) { xmlFreeDoc( doc ); } @@ -947,15 +1006,15 @@ void sp_repr_write_stream_element( Node * repr, Writer & out, // THIS DOESN'T APPEAR TO DO ANYTHING. Can it be commented out or deleted? { GQuark const href_key = g_quark_from_static_string("xlink:href"); - GQuark const absref_key = g_quark_from_static_string("sodipodi:absref"); + //GQuark const absref_key = g_quark_from_static_string("sodipodi:absref"); gchar const *xxHref = 0; - gchar const *xxAbsref = 0; + //gchar const *xxAbsref = 0; for ( List<AttributeRecord const> ai(attributes); ai; ++ai ) { if ( ai->key == href_key ) { xxHref = ai->value; - } else if ( ai->key == absref_key ) { - xxAbsref = ai->value; + //} else if ( ai->key == absref_key ) { + //xxAbsref = ai->value; } } |
