* and just see what the format of that line will be. Here we're going
* to parse out the base64 data, decode it, strip out its opening
* <xml> and <svg> tags, and then replace the original <xi:include>
- * element with the result. Life is a little easier because the
- * closing </svg> tag always immediately follows the XInclude; we can
- * chop the whole thing off, decode the base64 stuff, and then paste
- * the result back on the end with its own closing </svg> tag intact.
+ * element with the result.
*
* @param buffer
* A buffer containing SVG file data.
gchar* xi_start;
gchar* xi;
gchar* xi_stop;
+ gchar* after_xi_element;
xi_start = g_strstr_len(buffer, buf_size, XI_SIGNATURE);
if (xi_start == NULL) {
xi = xi_start + strlen(XI_SIGNATURE);
xi_stop = g_strstr_len(xi, (buffer + buf_size) - xi, "\"");
+
if(xi_stop == NULL) {
/* We found the start of an XInclude, but not the end of its
base64-encoded data? Play it safe and do nothing. */
* leading <svg> tag. */
gchar* svg_open_start = g_strstr_len(decoded, decoded_size, "<svg ");
if (svg_open_start == NULL) {
- /* The decoded data is not what we were expecting, Give up. */
+ /* The decoded data is not what we were expecting. Give up. */
g_free(decoded);
return NULL;
}
- else {
- gchar* svg_open_end = g_strstr_len(svg_open_start, decoded_size, ">");
- if (svg_open_end == NULL) {
- /* The decoded data is not what we were expecting. Give up. */
- g_free(decoded);
- return NULL;
- }
- memset(decoded, ' ', (1 + (svg_open_end - decoded)));
+
+ gchar* svg_open_end = g_strstr_len(svg_open_start,
+ (decoded+decoded_size) - svg_open_start,
+ ">");
+ if (svg_open_end == NULL) {
+ /* The decoded data is not what we were expecting. Give up. */
+ g_free(decoded);
+ return NULL;
+ }
+
+ /* Keep in mind that we want to wipe everything up to and
+ including the <svg> tag; we'll usually overwrite an <xml> tag
+ too. */
+ memset(decoded, ' ', (1 + (svg_open_end - decoded)));
+
+ gchar* svg_close_start = g_strstr_len(svg_open_end,
+ (decoded+decoded_size)-svg_open_end,
+ "</svg>");
+ if (svg_close_start == NULL ) {
+ /* The decoded data is not what we were expecting. Give up. */
+ g_free(decoded);
+ return NULL;
}
+ memset(svg_close_start, ' ', 6);
/* We're going to keep everything up to xi_start. If the <xi:include
* started at, say, position three, then this would compute a size
* of three. Which is correct: we want to retain buffer[0],
* buffer[1], and buffer[2]. */
- gsize keep_size = xi_start - buffer;
- *new_size = keep_size + decoded_size;
+ gsize keep_before_size = xi_start - buffer;
+
+ /* We're also going to keep everything after the XInclude element. */
+ after_xi_element = xi_stop + 3; /* They all end with "/> */
+ if (after_xi_element >= buffer+buf_size) {
+ /* The document ends right after the XInclude (with no closing
+ </svg> tag or anything)? Bail. */
+ g_free(decoded);
+ return NULL;
+ }
+
+ gsize keep_after_size = (buffer+buf_size) - after_xi_element;
+ *new_size = keep_before_size + decoded_size + keep_after_size;
gchar* result = g_malloc(*new_size);
- memcpy(result, buffer, keep_size);
- memcpy(result+keep_size, decoded, decoded_size);
+ memcpy(result, buffer, keep_before_size);
+ memcpy(result+keep_before_size, decoded, decoded_size);
+ memcpy(result+keep_before_size+decoded_size,
+ after_xi_element,
+ keep_after_size);
g_free(decoded);
return result;
}