summaryrefslogtreecommitdiff
path: root/xmlIO.c
diff options
context:
space:
mode:
Diffstat (limited to 'xmlIO.c')
-rw-r--r--xmlIO.c233
1 files changed, 221 insertions, 12 deletions
diff --git a/xmlIO.c b/xmlIO.c
index 8c4b68f..2f9874f 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -475,6 +475,32 @@ xmlCleanupInputCallbacks(void)
xmlInputCallbackInitialized = 0;
}
+/**
+ * xmlPopInputCallback:
+ *
+ * Clear the top input callback from the input stack. this includes the
+ * compiled-in I/O.
+ *
+ * Returns the number of input callback registered or -1 in case of error.
+ */
+int
+xmlPopInputCallbacks(void)
+{
+ if (!xmlInputCallbackInitialized)
+ return(-1);
+
+ if (xmlInputCallbackNr <= 0)
+ return(-1);
+
+ xmlInputCallbackNr--;
+ xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
+ xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
+ xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
+ xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
+
+ return(xmlInputCallbackNr);
+}
+
#ifdef LIBXML_OUTPUT_ENABLED
/**
* xmlCleanupOutputCallbacks:
@@ -2191,33 +2217,38 @@ xmlOutputBufferCreateFilename(const char *URI,
xmlCharEncodingHandlerPtr encoder,
int compression ATTRIBUTE_UNUSED) {
xmlOutputBufferPtr ret;
+ xmlURIPtr puri;
int i = 0;
void *context = NULL;
- char *unescaped;
-
- int is_http_uri = 0; /* Can't change if HTTP disabled */
+ char *unescaped = NULL;
+ int is_file_uri = 1;
if (xmlOutputCallbackInitialized == 0)
xmlRegisterDefaultOutputCallbacks();
if (URI == NULL) return(NULL);
-#ifdef LIBXML_HTTP_ENABLED
- /* Need to prevent HTTP URI's from falling into zlib short circuit */
-
- is_http_uri = xmlIOHTTPMatch( URI );
-#endif
-
+ puri = xmlParseURI(URI);
+ if (puri != NULL) {
+ if ((puri->scheme != NULL) &&
+ (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
+ is_file_uri = 0;
+ /*
+ * try to limit the damages of the URI unescaping code.
+ */
+ if (puri->scheme != NULL)
+ unescaped = xmlURIUnescapeString(URI, 0, NULL);
+ xmlFreeURI(puri);
+ }
/*
* Try to find one of the output accept method accepting that scheme
* Go in reverse to give precedence to user defined handlers.
* try with an unescaped version of the URI
*/
- unescaped = xmlURIUnescapeString(URI, 0, NULL);
if (unescaped != NULL) {
#ifdef HAVE_ZLIB_H
- if ((compression > 0) && (compression <= 9) && (is_http_uri == 0)) {
+ if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
context = xmlGzfileOpenW(unescaped, compression);
if (context != NULL) {
ret = xmlAllocOutputBuffer(encoder);
@@ -2254,7 +2285,7 @@ xmlOutputBufferCreateFilename(const char *URI,
*/
if (context == NULL) {
#ifdef HAVE_ZLIB_H
- if ((compression > 0) && (compression <= 9) && (is_http_uri == 0)) {
+ if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
context = xmlGzfileOpenW(URI, compression);
if (context != NULL) {
ret = xmlAllocOutputBuffer(encoder);
@@ -2835,6 +2866,184 @@ done:
}
/**
+ * xmlEscapeContent:
+ * @out: a pointer to an array of bytes to store the result
+ * @outlen: the length of @out
+ * @in: a pointer to an array of unescaped UTF-8 bytes
+ * @inlen: the length of @in
+ *
+ * Take a block of UTF-8 chars in and escape them.
+ * Returns 0 if success, or -1 otherwise
+ * The value of @inlen after return is the number of octets consumed
+ * if the return value is positive, else unpredictable.
+ * The value of @outlen after return is the number of octets consumed.
+ */
+static int
+xmlEscapeContent(unsigned char* out, int *outlen,
+ const xmlChar* in, int *inlen) {
+ unsigned char* outstart = out;
+ const unsigned char* base = in;
+ unsigned char* outend = out + *outlen;
+ const unsigned char* inend;
+
+ inend = in + (*inlen);
+
+ while ((in < inend) && (out < outend)) {
+ if (*in == '<') {
+ if (outend - out < 4) break;
+ *out++ = '&';
+ *out++ = 'l';
+ *out++ = 't';
+ *out++ = ';';
+ } else if (*in == '>') {
+ if (outend - out < 4) break;
+ *out++ = '&';
+ *out++ = 'g';
+ *out++ = 't';
+ *out++ = ';';
+ } else if (*in == '&') {
+ if (outend - out < 5) break;
+ *out++ = '&';
+ *out++ = 'a';
+ *out++ = 'm';
+ *out++ = 'p';
+ *out++ = ';';
+ } else if (*in == '\r') {
+ if (outend - out < 5) break;
+ *out++ = '&';
+ *out++ = '#';
+ *out++ = '1';
+ *out++ = '3';
+ *out++ = ';';
+ } else {
+ *out++ = (unsigned char) *in;
+ }
+ ++in;
+ }
+ *outlen = out - outstart;
+ *inlen = in - base;
+ return(0);
+}
+
+/**
+ * xmlOutputBufferWriteEscape:
+ * @out: a buffered parser output
+ * @str: a zero terminated UTF-8 string
+ * @escaping: an optional escaping function (or NULL)
+ *
+ * Write the content of the string in the output I/O buffer
+ * This routine escapes the caracters and then handle the I18N
+ * transcoding from internal UTF-8
+ * The buffer is lossless, i.e. will store in case of partial
+ * or delayed writes.
+ *
+ * Returns the number of chars immediately written, or -1
+ * in case of error.
+ */
+int
+xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
+ xmlCharEncodingOutputFunc escaping) {
+ int nbchars = 0; /* number of chars to output to I/O */
+ int ret; /* return from function call */
+ int written = 0; /* number of char written to I/O so far */
+ int chunk; /* number of byte currently processed from str */
+ int len; /* number of bytes in str */
+ int cons; /* byte from str consumed */
+
+ if ((out == NULL) || (out->error) || (str == NULL)) return(-1);
+ len = strlen((const char *)str);
+ if (len < 0) return(0);
+ if (out->error) return(-1);
+ if (escaping == NULL) escaping = xmlEscapeContent;
+
+ do {
+ /*
+ * how many bytes to consume and how many bytes to store.
+ */
+ cons = len;
+ chunk = (out->buffer->size - out->buffer->use) - 1;
+
+ /*
+ * first handle encoding stuff.
+ */
+ if (out->encoder != NULL) {
+ /*
+ * Store the data in the incoming raw buffer
+ */
+ if (out->conv == NULL) {
+ out->conv = xmlBufferCreate();
+ }
+ ret = escaping(out->buffer->content + out->buffer->use ,
+ &chunk, str, &cons);
+ if (ret < 0)
+ return(-1);
+ out->buffer->use += chunk;
+ out->buffer->content[out->buffer->use] = 0;
+
+ if ((out->buffer->use < MINLEN) && (cons == len))
+ goto done;
+
+ /*
+ * convert as much as possible to the output buffer.
+ */
+ ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+ if ((ret < 0) && (ret != -3)) {
+ xmlIOErr(XML_IO_ENCODER, NULL);
+ out->error = XML_IO_ENCODER;
+ return(-1);
+ }
+ nbchars = out->conv->use;
+ } else {
+ ret = escaping(out->buffer->content + out->buffer->use ,
+ &chunk, str, &cons);
+ if (ret < 0)
+ return(-1);
+ out->buffer->use += chunk;
+ out->buffer->content[out->buffer->use] = 0;
+ nbchars = out->buffer->use;
+ }
+ str += cons;
+ len -= cons;
+
+ if ((nbchars < MINLEN) && (len <= 0))
+ goto done;
+
+ if (out->writecallback) {
+ /*
+ * second write the stuff to the I/O channel
+ */
+ if (out->encoder != NULL) {
+ ret = out->writecallback(out->context,
+ (const char *)out->conv->content, nbchars);
+ if (ret >= 0)
+ xmlBufferShrink(out->conv, ret);
+ } else {
+ ret = out->writecallback(out->context,
+ (const char *)out->buffer->content, nbchars);
+ if (ret >= 0)
+ xmlBufferShrink(out->buffer, ret);
+ }
+ if (ret < 0) {
+ xmlIOErr(XML_IO_WRITE, NULL);
+ out->error = XML_IO_WRITE;
+ return(ret);
+ }
+ out->written += ret;
+ } else if (out->buffer->size - out->buffer->use < MINLEN) {
+ xmlBufferResize(out->buffer, out->buffer->size + MINLEN);
+ }
+ written += nbchars;
+ } while (len > 0);
+
+done:
+#ifdef DEBUG_INPUT
+ xmlGenericError(xmlGenericErrorContext,
+ "I/O: wrote %d chars\n", written);
+#endif
+ return(written);
+}
+
+/**
* xmlOutputBufferWriteString:
* @out: a buffered parser output
* @str: a zero terminated C string