summaryrefslogtreecommitdiffstats
path: root/src/xml/repr-io.cpp
diff options
context:
space:
mode:
authorMartin Owens <doctormo@gmail.com>2014-03-27 01:33:44 +0000
committerMartin Owens <doctormo@gmail.com>2014-03-27 01:33:44 +0000
commit5a4fb2325f60d292b47330f540b26a3279341c90 (patch)
treed2aa7967be25450b83e625025366c618101ae49f /src/xml/repr-io.cpp
parentThe Polar Arrange Tab of the Arrange Dialog now hides the parametric (diff)
parentRemove Snap menu item and improve grid menu item text (diff)
downloadinkscape-5a4fb2325f60d292b47330f540b26a3279341c90.tar.gz
inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.zip
Commit a merge to trunk, with probabal errors
(bzr r11073.1.36)
Diffstat (limited to 'src/xml/repr-io.cpp')
-rw-r--r--src/xml/repr-io.cpp140
1 files changed, 109 insertions, 31 deletions
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index b85e58899..0319bb5e3 100644
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
@@ -37,6 +37,8 @@
#include "preferences.h"
+#include <glibmm/miscutils.h>
+
using Inkscape::IO::Writer;
using Inkscape::Util::List;
using Inkscape::Util::cons;
@@ -76,11 +78,14 @@ public:
XmlSource()
: filename(0),
encoding(0),
- fp(0),
+ fp(NULL),
firstFewLen(0),
+ LoadEntities(false),
+ cachedData(),
+ cachedPos(0),
dummy("x"),
- instr(0),
- gzin(0)
+ instr(NULL),
+ gzin(NULL)
{
for (int k=0;k<4;k++)
{
@@ -96,7 +101,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 );
@@ -110,12 +117,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;
@@ -172,14 +182,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;
+ }
+ delete[] 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 );
@@ -201,7 +259,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 ) {
@@ -268,7 +334,10 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
xmlSubstituteEntitiesDefault(1);
g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS ), NULL);
+ if (!Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS )) {
+ g_warning("Can't open file: %s (doesn't exist)", filename);
+ return NULL;
+ }
/* fixme: A file can disappear at any time, including between now and when we actually try to
* open it. Get rid of the above test once we're sure that we correctly handle
* non-existence. */
@@ -297,16 +366,20 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
XmlSource src;
if ( (src.setFile(filename) == 0) ) {
- doc = xmlReadIO( XmlSource::readCb,
- XmlSource::closeCb,
- &src,
- localFilename,
- src.getEncoding(),
- XML_PARSE_NOENT | XML_PARSE_HUGE);
+ 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 );
+ }
}
}
- rdoc = sp_repr_do_read( doc, default_ns );
+
if ( doc ) {
xmlFreeDoc( doc );
}
@@ -471,13 +544,19 @@ Document *sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns)
gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *name, const gchar */*default_ns*/, GHashTable *prefix_map)
{
const xmlChar *prefix;
- if ( ns && ns->href ) {
- prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href),
- reinterpret_cast<const char*>(ns->prefix)) );
- void* p0 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(prefix));
- void* p1 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(ns->href));
- g_hash_table_insert( prefix_map, p0, p1 );
- } else {
+ if (ns){
+ if (ns->href ) {
+ prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href),
+ reinterpret_cast<const char*>(ns->prefix)) );
+ void* p0 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(prefix));
+ void* p1 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(ns->href));
+ g_hash_table_insert( prefix_map, p0, p1 );
+ }
+ else {
+ prefix = NULL;
+ }
+ }
+ else {
prefix = NULL;
}
@@ -490,7 +569,6 @@ gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *nam
static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_ns, GHashTable *prefix_map)
{
- Node *repr, *crepr;
xmlAttrPtr prop;
xmlNodePtr child;
gchar c[256];
@@ -530,7 +608,7 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc
}
sp_repr_qualified_name (c, 256, node->ns, node->name, default_ns, prefix_map);
- repr = xml_doc->createElement(c);
+ Node *repr = xml_doc->createElement(c);
/* TODO remember node->ns->prefix if node->ns != NULL */
for (prop = node->properties; prop != NULL; prop = prop->next) {
@@ -547,7 +625,7 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc
child = node->xmlChildrenNode;
for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
- crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map);
+ Node *crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map);
if (crepr) {
repr->appendChild(crepr);
Inkscape::GC::release(crepr);
@@ -600,10 +678,10 @@ Glib::ustring sp_repr_save_buf(Document *doc)
sp_repr_save_writer(doc, &outs, SP_INKSCAPE_NS_URI, 0, 0);
- outs.close();
- Glib::ustring buf = souts.getString();
+ outs.close();
+ Glib::ustring buf = souts.getString();
- return buf;
+ return buf;
}
@@ -934,15 +1012,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;
}
}