diff --git a/mxml.cxx b/mxml.cxx index 8c609bb..437fa37 100644 --- a/mxml.cxx +++ b/mxml.cxx @@ -114,7 +114,7 @@ static int mxml_suppress_date_flag = 0; /* suppress writing date at the top of f /* local prototypes */ static PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...) MXML_GNUC_PRINTF(7, 8); -static void mxml_encode(char *src, int size, int translate); +static void mxml_encode(char* buf, int buf_size, const char *src, int src_len, int translate); static void mxml_decode(char *str); static int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent); static int mxml_write_line(MXML_WRITER *writer, const char *line); @@ -124,12 +124,6 @@ static int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE ** static void *mxml_malloc(size_t size); static void *mxml_realloc(void *p, size_t size); static void mxml_free(void *p); -static void mxml_deallocate(void); - -/*------------------------------------------------------------------*/ - -static char *_encode_buffer = NULL; -static char *_data_enc = NULL; /*------------------------------------------------------------------*/ @@ -154,20 +148,6 @@ void mxml_free(void *p) /*------------------------------------------------------------------*/ -void mxml_deallocate(void) -{ - if (_encode_buffer != NULL) { - mxml_free(_encode_buffer); - _encode_buffer = NULL; - } - if (_data_enc != NULL) { - mxml_free(_data_enc); - _data_enc = NULL; - } -} - -/*------------------------------------------------------------------*/ - int mxml_write_line(MXML_WRITER *writer, const char *line) { unsigned len; @@ -175,10 +155,10 @@ int mxml_write_line(MXML_WRITER *writer, const char *line) len = strlen(line); if (writer->buffer) { - if (writer->buffer_len + len >= writer->buffer_size) { + if (writer->buffer_len + (int)len >= writer->buffer_size) { writer->buffer_size += len + 10000; writer->buffer = (char *)mxml_realloc(writer->buffer, writer->buffer_size); - assert(writer->buffer); + assert(writer->buffer); } strcpy(writer->buffer + writer->buffer_len, line); writer->buffer_len += len; @@ -283,25 +263,12 @@ MXML_WRITER *mxml_open_file(const char *file_name) /** * convert '<' '>' '&' '"' ''' into &xx; */ -void mxml_encode(char *src, int size, int translate) +void mxml_encode(char* buf, int buf_size, const char *src, int src_len, int translate) { - char *ps, *pd; - static int buffer_size = 1000; - - assert(size); - - if (_encode_buffer == NULL) { - _encode_buffer = (char *) mxml_malloc(buffer_size); - atexit(mxml_deallocate); - } - - if (size > buffer_size) { - _encode_buffer = (char *) mxml_realloc(_encode_buffer, size*2); - buffer_size = size; - } - - pd = _encode_buffer; - for (ps = src ; *ps && (size_t)pd - (size_t)_encode_buffer < (size_t)(size-10) ; ps++) { + assert(buf_size > 6*src_len); // each input byte is expanded into 6 bytes at most + char *pd = buf; + const char* ps; + for (ps = src ; *ps ; ps++) { if (translate) { /* tranlate "<", ">", "&", """, "'" */ switch (*ps) { @@ -329,7 +296,7 @@ void mxml_encode(char *src, int size, int translate) *pd++ = *ps; } } else { - switch (*ps) { /* translate only illegal XML characters "<" and "&" */ + switch (*ps) { /* translate only special XML characters "<" and "&" */ case '<': strcpy(pd, "<"); pd += 4; @@ -345,7 +312,7 @@ void mxml_encode(char *src, int size, int translate) } *pd = 0; - strlcpy(src, _encode_buffer, size); + //printf("mxml_encode: size %d, in %d, out %d, [%s] -> [%s]\n", buf_size, src_len, (int)strlen(buf), src, buf); } /*------------------------------------------------------------------*/ @@ -410,7 +377,7 @@ int mxml_set_translate(MXML_WRITER *writer, int flag) int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent) { int i; - char line[1000], name_enc[1000]; + char line[1000]; if (writer->element_is_open) { mxml_write_line(writer, ">\n"); @@ -420,11 +387,14 @@ int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent) line[0] = 0; if (indent) for (i=0 ; ilevel ; i++) - strlcat(line, XML_INDENT, sizeof(line)); + strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated strlcat(line, "<", sizeof(line)); - strlcpy(name_enc, name, sizeof(name_enc)); - mxml_encode(name_enc, sizeof(name_enc), writer->translate); - strlcat(line, name_enc, sizeof(line)); + + unsigned len = strlen(name); + unsigned name_enc_size = len*6+10; + char* name_enc = (char*)mxml_malloc(name_enc_size); + mxml_encode(name_enc, name_enc_size, name, strlen(name), writer->translate); + strlcat(line, name_enc, sizeof(line)); // FIXME: data will be truncated /* put element on stack */ if (writer->level == 0) @@ -432,8 +402,7 @@ int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent) else writer->stack = (char **)mxml_realloc(writer->stack, sizeof(char *)*(writer->level+1)); - writer->stack[writer->level] = (char *) mxml_malloc(strlen(name_enc)+1); - strcpy(writer->stack[writer->level], name_enc); + writer->stack[writer->level] = name_enc; writer->level++; writer->element_is_open = TRUE; writer->data_was_written = FALSE; @@ -463,7 +432,6 @@ int mxml_start_element_noindent(MXML_WRITER *writer, const char *name) int mxml_end_element(MXML_WRITER *writer) { int i; - char line[1000]; if (writer->level == 0) return 0; @@ -475,18 +443,20 @@ int mxml_end_element(MXML_WRITER *writer) mxml_free(writer->stack[writer->level]); if (writer->level == 0) mxml_free(writer->stack); + char line[10]; strcpy(line, "/>\n"); return mxml_write_line(writer, line) == (int)strlen(line); } + char line[1000]; line[0] = 0; if (!writer->data_was_written) { for (i=0 ; ilevel ; i++) - strlcat(line, XML_INDENT, sizeof(line)); + strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated } strlcat(line, "stack[writer->level], sizeof(line)); + strlcat(line, writer->stack[writer->level], sizeof(line)); // FIXME: truncated mxml_free(writer->stack[writer->level]); if (writer->level == 0) mxml_free(writer->stack); @@ -503,17 +473,20 @@ int mxml_end_element(MXML_WRITER *writer) */ int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value) { - char name_enc[4096], val_enc[4096], line[8192]; + char line[8192]; + char buf[6*4096+10]; if (!writer->element_is_open) return FALSE; - strcpy(name_enc, name); - mxml_encode(name_enc, sizeof(name_enc), writer->translate); - strcpy(val_enc, value); - mxml_encode(val_enc, sizeof(val_enc), writer->translate); - - sprintf(line, " %s=\"%s\"", name_enc, val_enc); + line[0] = 0; + strlcat(line, " ", sizeof(line)); + mxml_encode(buf, sizeof(buf), name, strlen(name), writer->translate); + strlcat(line, buf, sizeof(line)); // FIXME: truncated + strlcat(line, "=\"", sizeof(line)); + mxml_encode(buf, sizeof(buf), value, strlen(value), writer->translate); + strlcat(line, buf, sizeof(line)); // FIXME: truncated + strlcat(line, "\"", sizeof(line)); return mxml_write_line(writer, line) == (int)strlen(line); } @@ -525,8 +498,6 @@ int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *valu */ int mxml_write_value(MXML_WRITER *writer, const char *data) { - static int data_size = 0; - if (!writer->element_is_open) return FALSE; @@ -535,17 +506,14 @@ int mxml_write_value(MXML_WRITER *writer, const char *data) writer->element_is_open = FALSE; writer->data_was_written = TRUE; - if (data_size == 0) { - _data_enc = (char *)mxml_malloc(1000); - data_size = 1000; - } else if ((int)strlen(data)*2+1000 > data_size) { - data_size = 1000+(int)strlen(data)*2; - _data_enc = (char *)mxml_realloc(_data_enc, data_size); - } - - strcpy(_data_enc, data); - mxml_encode(_data_enc, data_size, writer->translate); - return mxml_write_line(writer, _data_enc) == (int)strlen(_data_enc); + unsigned len = strlen(data); + unsigned size = 6*len + 1000; + char* buf = (char*)mxml_malloc(size); + strcpy(buf, data); + mxml_encode(buf, size, data, len, writer->translate); + int v = mxml_write_line(writer, buf) == (int)strlen(buf); + mxml_free(buf); + return v; } /*------------------------------------------------------------------*/ @@ -574,19 +542,19 @@ int mxml_write_empty_line(MXML_WRITER *writer) int mxml_write_comment(MXML_WRITER *writer, const char *string) { int i; - char line[1000]; if (writer->element_is_open) { mxml_write_line(writer, ">\n"); writer->element_is_open = FALSE; } + char line[1000]; line[0] = 0; for (i=0 ; ilevel ; i++) - strlcat(line, XML_INDENT, sizeof(line)); + strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated strlcat(line, "\n", sizeof(line)); if (mxml_write_line(writer, line) != (int)strlen(line)) return FALSE; @@ -2025,6 +1993,7 @@ error: for (ip = 0; ip < MXML_MAX_ENTITY; ip++) if (entity_value[ip] != NULL) mxml_free(entity_value[ip]); + mxml_free_tree(root); return status; }