31 Commits

Author SHA1 Message Date
ritt cfce5afcc9 Fixed compiler warnings 2024-07-26 15:46:36 +02:00
ritt d50251ec12 Added mxml_write_tree to mxml.h 2024-02-15 15:46:45 +01:00
ritt 726495c1e5 Replaced sprintf by snprintf 2023-02-06 13:22:54 +01:00
ritt 15cd4bd1e0 Fixed incorrect buffer handling 2022-08-05 18:53:55 +02:00
ritt a97f18a2c0 Removed wrong xml element 2022-08-05 08:26:16 +02:00
ritt fce873bbef Removed strlcpy.* since mxml uses mxml_strlcpy 2022-08-04 19:32:22 +02:00
Konstantin Olchanski aef5c8b5c0 mxml use mxml_strlcpy() 2022-08-04 10:23:44 -07:00
ritt 4f0a8b6815 Added missing include file 2022-08-04 19:11:07 +02:00
ritt d29b1093ed Fixed typo 2022-08-04 16:05:29 +02:00
ritt ed60694e4c Implemented mxml_print_tree 2022-08-04 12:24:10 +02:00
ritt 4d4b4cf17b Changed assert to real test 2022-02-15 13:42:08 +01:00
Konstantin Olchanski 5e10343edb remove CMakeLists.txt 2021-07-09 18:22:47 -07:00
ritt a5a33ad29c Reduced max number of entities because of stack problems 2021-06-18 12:21:55 +02:00
Konstantin Olchanski d64f9605df add .gitignore 2021-05-27 15:45:05 -07:00
Konstantin Olchanski 1132d0260a cmake - dummy library 2021-05-27 15:36:16 -07:00
Konstantin Olchanski e6e2e64548 Remove more strcpy() 2020-05-22 14:06:34 -07:00
Konstantin Olchanski f09643b9fc Fix incorrect string resize 2020-05-22 13:52:26 -07:00
Konstantin Olchanski 5609cf96d0 Remove most strcpy() 2020-05-22 13:46:27 -07:00
Konstantin Olchanski 732f3040b3 Replace all sprintf() with std::string 2020-05-22 13:36:48 -07:00
Konstantin Olchanski 6b96d7aa9c Remove sprintf() 2020-05-22 12:55:44 -07:00
Ben Smith f6fc49d9aa Remove premature free() which can cause segfaults. It is anyway freed later when freeing writer->stack[writer->level]. 2019-08-01 15:34:10 -07:00
ritt 7ca9a5a425 Fixed correct free 2019-07-10 16:59:08 +02:00
ritt 0ebf750197 Fixed double free 2019-07-10 16:55:35 +02:00
Konstantin Olchanski 2e48b71244 mxml.cxx no longer uses strlcpy. strlcat() relaced with std::string, strlcpy() for now uses private copy mxml_strlcpy() 2019-06-17 18:11:43 -07:00
Konstantin Olchanski 2c3833710a Remove "extern C", use C++ linking 2019-06-17 17:34:16 -07:00
ritt d38f63e76d Put back KO's modifications 2019-06-10 16:05:49 +02:00
ritt e658c27302 Removed .c files 2019-06-10 15:59:42 +02:00
ritt 5d8f4a273a Changed .c files to .cxx files 2019-06-06 18:27:38 +02:00
ritt 5f9886be00 Create dummy routine to fix linker errors on empty library 2019-05-29 10:42:32 +02:00
ritt cb34fe499c Fixed debugger warning 2019-04-12 14:26:10 +02:00
ritt 75ebe0caee Fixed memory leak 2019-04-12 14:19:57 +02:00
5 changed files with 272 additions and 309 deletions
+1
View File
@@ -0,0 +1 @@
*~
+268 -142
View File
@@ -33,7 +33,7 @@
mxml_find_nodes(tree, xml_path, &nodelist); mxml_find_nodes(tree, xml_path, &nodelist);
which support a subset of the XPath specification. Another set of which support a subset of the XPath specification. Another set of
functions is availabe to retrieve attributes and values from nodes functions is available to retrieve attributes and values from nodes
in the tree and for manipulating nodes, like replacing, adding and in the tree and for manipulating nodes, like replacing, adding and
deleting nodes. deleting nodes.
@@ -60,6 +60,8 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <string>
#ifdef _MSC_VER #ifdef _MSC_VER
#include <windows.h> #include <windows.h>
@@ -91,9 +93,6 @@
#endif #endif
#include "mxml.h" #include "mxml.h"
#ifndef HAVE_STRLCPY
#include "strlcpy.h"
#endif
#define XML_INDENT " " #define XML_INDENT " "
@@ -125,6 +124,54 @@ static void *mxml_malloc(size_t size);
static void *mxml_realloc(void *p, size_t size); static void *mxml_realloc(void *p, size_t size);
static void mxml_free(void *p); static void mxml_free(void *p);
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless size == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
static size_t mxml_strlcpy(char *dst, const char *src, size_t size)
{
char *d = dst;
const char *s = src;
size_t n = size;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (size != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++);
}
return (s - src - 1); /* count does not include NUL */
}
/*------------------------------------------------------------------*/
static std::string toString(int i)
{
char buf[100];
snprintf(buf, sizeof(buf), "%d", i);
return buf;
}
/*------------------------------------------------------------------*/
static std::string toStrerror(int err)
{
char buf[256];
snprintf(buf, sizeof(buf), "errno %d (%s)", err, strerror(err));
return buf;
}
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
void *mxml_malloc(size_t size) void *mxml_malloc(size_t size)
@@ -150,9 +197,7 @@ void mxml_free(void *p)
int mxml_write_line(MXML_WRITER *writer, const char *line) int mxml_write_line(MXML_WRITER *writer, const char *line)
{ {
unsigned len; int len = strlen(line);
len = strlen(line);
if (writer->buffer) { if (writer->buffer) {
if (writer->buffer_len + len >= writer->buffer_size) { if (writer->buffer_len + len >= writer->buffer_size) {
@@ -160,7 +205,7 @@ int mxml_write_line(MXML_WRITER *writer, const char *line)
writer->buffer = (char *)mxml_realloc(writer->buffer, writer->buffer_size); writer->buffer = (char *)mxml_realloc(writer->buffer, writer->buffer_size);
assert(writer->buffer); assert(writer->buffer);
} }
strcpy(writer->buffer + writer->buffer_len, line); memcpy(writer->buffer + writer->buffer_len, line, len+1);
writer->buffer_len += len; writer->buffer_len += len;
return len; return len;
} else { } else {
@@ -177,28 +222,29 @@ int mxml_write_line(MXML_WRITER *writer, const char *line)
*/ */
MXML_WRITER *mxml_open_buffer(void) MXML_WRITER *mxml_open_buffer(void)
{ {
char str[256], line[1000]; MXML_WRITER *writer = (MXML_WRITER *)mxml_malloc(sizeof(MXML_WRITER));
time_t now;
MXML_WRITER *writer;
writer = (MXML_WRITER *)mxml_malloc(sizeof(MXML_WRITER));
memset(writer, 0, sizeof(MXML_WRITER)); memset(writer, 0, sizeof(MXML_WRITER));
writer->translate = 1; writer->translate = 1;
writer->buffer_size = 10000; writer->buffer_size = 10000;
writer->buffer = (char *)mxml_malloc(10000); writer->buffer = (char *)mxml_malloc(writer->buffer_size);
assert(writer->buffer != NULL);
writer->buffer[0] = 0; writer->buffer[0] = 0;
writer->buffer_len = 0; writer->buffer_len = 0;
/* write XML header */ /* write XML header */
strcpy(line, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"); mxml_write_line(writer, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
mxml_write_line(writer, line);
time(&now); if (mxml_suppress_date_flag == 0) {
strcpy(str, ctime(&now)); time_t now = time(NULL);
str[24] = 0; std::string str = ctime(&now);
sprintf(line, "<!-- created by MXML on %s -->\n", str); str.resize(24);
if (mxml_suppress_date_flag == 0) std::string line = "";
mxml_write_line(writer, line); line += "<!-- created by MXML on ";
line += str;
line += " -->\n";
mxml_write_line(writer, line.c_str());
}
/* initialize stack */ /* initialize stack */
writer->level = 0; writer->level = 0;
@@ -224,32 +270,35 @@ void mxml_suppress_date(int suppress)
*/ */
MXML_WRITER *mxml_open_file(const char *file_name) MXML_WRITER *mxml_open_file(const char *file_name)
{ {
char str[256], line[1000]; MXML_WRITER* writer = (MXML_WRITER *)mxml_malloc(sizeof(MXML_WRITER));
time_t now;
MXML_WRITER *writer;
writer = (MXML_WRITER *)mxml_malloc(sizeof(MXML_WRITER));
memset(writer, 0, sizeof(MXML_WRITER)); memset(writer, 0, sizeof(MXML_WRITER));
writer->translate = 1; writer->translate = 1;
writer->fh = open(file_name, O_RDWR | O_CREAT | O_TRUNC | O_TEXT, 0644); writer->fh = open(file_name, O_RDWR | O_CREAT | O_TRUNC | O_TEXT, 0644);
if (writer->fh == -1) { if (writer->fh == -1) {
sprintf(line, "Unable to open file \"%s\": ", file_name); std::string line = "";
perror(line); line += "Unable to open file \"";
line += file_name;
line += "\": ";
line += toStrerror(errno);
fprintf(stderr, "%s\n", line.c_str());
mxml_free(writer); mxml_free(writer);
return NULL; return NULL;
} }
/* write XML header */ /* write XML header */
strcpy(line, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"); mxml_write_line(writer, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
mxml_write_line(writer, line); if (mxml_suppress_date_flag == 0) {
time(&now); time_t now = time(NULL);
strcpy(str, ctime(&now)); std::string str = ctime(&now);
str[24] = 0; str.resize(24);
sprintf(line, "<!-- created by MXML on %s -->\n", str); std::string line = "";
if (mxml_suppress_date_flag == 0) line += "<!-- created by MXML on ";
mxml_write_line(writer, line); line += str;
line += " -->\n";
mxml_write_line(writer, line.c_str());
}
/* initialize stack */ /* initialize stack */
writer->level = 0; writer->level = 0;
@@ -265,7 +314,10 @@ MXML_WRITER *mxml_open_file(const char *file_name)
*/ */
void mxml_encode(char* buf, int buf_size, const char *src, int src_len, int translate) void mxml_encode(char* buf, int buf_size, const char *src, int src_len, int translate)
{ {
assert(buf_size > 6*src_len); // each input byte is expanded into 6 bytes at most if (buf_size <= 6*src_len) {
printf("mxml_encode: buffer size too small\n");
exit(0);
}
char *pd = buf; char *pd = buf;
const char* ps; const char* ps;
for (ps = src ; *ps ; ps++) { for (ps = src ; *ps ; ps++) {
@@ -377,24 +429,23 @@ int mxml_set_translate(MXML_WRITER *writer, int flag)
int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent) int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
{ {
int i; int i;
char line[1000];
if (writer->element_is_open) { if (writer->element_is_open) {
mxml_write_line(writer, ">\n"); mxml_write_line(writer, ">\n");
writer->element_is_open = FALSE; writer->element_is_open = FALSE;
} }
line[0] = 0; std::string line = "";
if (indent) if (indent)
for (i=0 ; i<writer->level ; i++) for (i=0 ; i<writer->level ; i++)
strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated line += XML_INDENT;
strlcat(line, "<", sizeof(line)); line += "<";
unsigned len = strlen(name); unsigned len = strlen(name);
unsigned name_enc_size = len*6+10; unsigned name_enc_size = len*6+10;
char* name_enc = (char*)mxml_malloc(name_enc_size); char* name_enc = (char*)mxml_malloc(name_enc_size);
mxml_encode(name_enc, name_enc_size, name, strlen(name), writer->translate); mxml_encode(name_enc, name_enc_size, name, strlen(name), writer->translate);
strlcat(line, name_enc, sizeof(line)); // FIXME: data will be truncated line += name_enc;
/* put element on stack */ /* put element on stack */
if (writer->level == 0) if (writer->level == 0)
@@ -407,7 +458,7 @@ int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
writer->element_is_open = TRUE; writer->element_is_open = TRUE;
writer->data_was_written = FALSE; writer->data_was_written = FALSE;
return mxml_write_line(writer, line) == (int)strlen(line); return mxml_write_line(writer, line.c_str()) == (int)line.length();
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@@ -443,27 +494,25 @@ int mxml_end_element(MXML_WRITER *writer)
mxml_free(writer->stack[writer->level]); mxml_free(writer->stack[writer->level]);
if (writer->level == 0) if (writer->level == 0)
mxml_free(writer->stack); mxml_free(writer->stack);
char line[10]; const char* line = "/>\n";
strcpy(line, "/>\n");
return mxml_write_line(writer, line) == (int)strlen(line); return mxml_write_line(writer, line) == (int)strlen(line);
} }
char line[1000]; std::string line = "";
line[0] = 0;
if (!writer->data_was_written) { if (!writer->data_was_written) {
for (i=0 ; i<writer->level ; i++) for (i=0 ; i<writer->level ; i++)
strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated line += XML_INDENT;
} }
strlcat(line, "</", sizeof(line)); line += "</";
strlcat(line, writer->stack[writer->level], sizeof(line)); // FIXME: truncated line += writer->stack[writer->level];
mxml_free(writer->stack[writer->level]); mxml_free(writer->stack[writer->level]);
if (writer->level == 0) if (writer->level == 0)
mxml_free(writer->stack); mxml_free(writer->stack);
strlcat(line, ">\n", sizeof(line)); line += ">\n";
writer->data_was_written = FALSE; writer->data_was_written = FALSE;
return mxml_write_line(writer, line) == (int)strlen(line); return mxml_write_line(writer, line.c_str()) == (int)line.length();
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@@ -473,22 +522,21 @@ int mxml_end_element(MXML_WRITER *writer)
*/ */
int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value) int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value)
{ {
char line[8192];
char buf[6*4096+10]; char buf[6*4096+10];
if (!writer->element_is_open) if (!writer->element_is_open)
return FALSE; return FALSE;
line[0] = 0; std::string line = "";
strlcat(line, " ", sizeof(line)); line += " ";
mxml_encode(buf, sizeof(buf), name, strlen(name), writer->translate); mxml_encode(buf, sizeof(buf), name, strlen(name), writer->translate);
strlcat(line, buf, sizeof(line)); // FIXME: truncated line += buf;
strlcat(line, "=\"", sizeof(line)); line += "=\"";
mxml_encode(buf, sizeof(buf), value, strlen(value), writer->translate); mxml_encode(buf, sizeof(buf), value, strlen(value), writer->translate);
strlcat(line, buf, sizeof(line)); // FIXME: truncated line += buf;
strlcat(line, "\"", sizeof(line)); line += "\"";
return mxml_write_line(writer, line) == (int)strlen(line); return mxml_write_line(writer, line.c_str()) == (int)line.length();
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@@ -509,7 +557,7 @@ int mxml_write_value(MXML_WRITER *writer, const char *data)
unsigned len = strlen(data); unsigned len = strlen(data);
unsigned size = 6*len + 1000; unsigned size = 6*len + 1000;
char* buf = (char*)mxml_malloc(size); char* buf = (char*)mxml_malloc(size);
strcpy(buf, data); memcpy(buf, data, len+1);
mxml_encode(buf, size, data, len, writer->translate); mxml_encode(buf, size, data, len, writer->translate);
int v = mxml_write_line(writer, buf) == (int)strlen(buf); int v = mxml_write_line(writer, buf) == (int)strlen(buf);
mxml_free(buf); mxml_free(buf);
@@ -548,15 +596,14 @@ int mxml_write_comment(MXML_WRITER *writer, const char *string)
writer->element_is_open = FALSE; writer->element_is_open = FALSE;
} }
char line[1000]; std::string line = "";
line[0] = 0;
for (i=0 ; i<writer->level ; i++) for (i=0 ; i<writer->level ; i++)
strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated line += XML_INDENT;
strlcat(line, "<!-- ", sizeof(line)); line += "<!-- ";
strlcat(line, string, sizeof(line)); // FIXME: truncated line += string;
strlcat(line, " -->\n", sizeof(line)); line += " -->\n";
if (mxml_write_line(writer, line) != (int)strlen(line)) if (mxml_write_line(writer, line.c_str()) != (int)line.length())
return FALSE; return FALSE;
return TRUE; return TRUE;
@@ -635,8 +682,8 @@ PMXML_NODE mxml_create_root_node(void)
{ {
PMXML_NODE root; PMXML_NODE root;
root = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1); root = (PMXML_NODE)calloc(1, sizeof(MXML_NODE));
strcpy(root->name, "root"); strcpy(root->name, "root"); // SAFE
root->node_type = DOCUMENT_NODE; root->node_type = DOCUMENT_NODE;
return root; return root;
@@ -674,16 +721,17 @@ PMXML_NODE mxml_add_special_node_at(PMXML_NODE parent, int node_type, const char
/* initialize new node */ /* initialize new node */
pnode = &parent->child[idx]; pnode = &parent->child[idx];
memset(pnode, 0, sizeof(MXML_NODE)); memset(pnode, 0, sizeof(MXML_NODE));
strlcpy(pnode->name, node_name, sizeof(pnode->name)); mxml_strlcpy(pnode->name, node_name, sizeof(pnode->name));
pnode->node_type = node_type; pnode->node_type = node_type;
pnode->parent = parent; pnode->parent = parent;
parent->n_children++; parent->n_children++;
if (value && *value) { if (value && *value) {
pnode->value = (char *)mxml_malloc(strlen(value)+1); int len = strlen(value);
pnode->value = (char *)mxml_malloc(len+1);
assert(pnode->value); assert(pnode->value);
strcpy(pnode->value, value); memcpy(pnode->value, value, len+1);
} }
return pnode; return pnode;
@@ -801,9 +849,11 @@ int mxml_add_attribute(PMXML_NODE pnode, const char *attrib_name, const char *at
pnode->attribute_value = (char**)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes+1)); pnode->attribute_value = (char**)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes+1));
} }
strlcpy(pnode->attribute_name+pnode->n_attributes*MXML_NAME_LENGTH, attrib_name, MXML_NAME_LENGTH); mxml_strlcpy(pnode->attribute_name+pnode->n_attributes*MXML_NAME_LENGTH, attrib_name, MXML_NAME_LENGTH);
pnode->attribute_value[pnode->n_attributes] = (char *)mxml_malloc(strlen(attrib_value)+1); int len = strlen(attrib_value);
strcpy(pnode->attribute_value[pnode->n_attributes], attrib_value); pnode->attribute_value[pnode->n_attributes] = (char *)mxml_malloc(len+1);
assert(pnode->attribute_value[pnode->n_attributes] != NULL);
memcpy(pnode->attribute_value[pnode->n_attributes], attrib_value, len+1);
pnode->n_attributes++; pnode->n_attributes++;
return TRUE; return TRUE;
@@ -914,7 +964,7 @@ int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelis
/* evaluate [<@attrib>/<subnode>=<value>] */ /* evaluate [<@attrib>/<subnode>=<value>] */
while (*p2 && isspace((unsigned char)*p2)) while (*p2 && isspace((unsigned char)*p2))
p2++; p2++;
strlcpy(condition, p2, sizeof(condition)); mxml_strlcpy(condition, p2, sizeof(condition));
if (strchr(condition, ']')) if (strchr(condition, ']'))
*strchr(condition, ']') = 0; *strchr(condition, ']') = 0;
else else
@@ -923,9 +973,9 @@ int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelis
if ((p3 = strchr(condition, '=')) != NULL) { if ((p3 = strchr(condition, '=')) != NULL) {
if (condition[0] == '@') { if (condition[0] == '@') {
cond_type[num_cond] = 1; cond_type[num_cond] = 1;
strlcpy(cond_name[num_cond], &condition[1], sizeof(cond_name[num_cond])); mxml_strlcpy(cond_name[num_cond], &condition[1], sizeof(cond_name[num_cond]));
} else { } else {
strlcpy(cond_name[num_cond], condition, sizeof(cond_name[num_cond])); mxml_strlcpy(cond_name[num_cond], condition, sizeof(cond_name[num_cond]));
} }
*strchr(cond_name[num_cond], '=') = 0; *strchr(cond_name[num_cond], '=') = 0;
@@ -936,19 +986,19 @@ int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelis
while (*p3 && isspace(*p3)) while (*p3 && isspace(*p3))
p3++; p3++;
if (*p3 == '\"') { if (*p3 == '\"') {
strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond])); mxml_strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1])) while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0; cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\"') if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\"')
cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0; cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
} else if (*p3 == '\'') { } else if (*p3 == '\'') {
strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond])); mxml_strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1])) while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0; cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\'') if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\'')
cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0; cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
} else { } else {
strlcpy(cond_value[num_cond], p3, sizeof(cond_value[num_cond])); mxml_strlcpy(cond_value[num_cond], p3, sizeof(cond_value[num_cond]));
while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1])) while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0; cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
} }
@@ -1098,7 +1148,7 @@ char *mxml_get_attribute(PMXML_NODE pnode, const char *name)
int mxml_replace_node_name(PMXML_NODE pnode, const char *name) int mxml_replace_node_name(PMXML_NODE pnode, const char *name)
{ {
strlcpy(pnode->name, name, sizeof(pnode->name)); mxml_strlcpy(pnode->name, name, sizeof(pnode->name));
return TRUE; return TRUE;
} }
@@ -1106,15 +1156,16 @@ int mxml_replace_node_name(PMXML_NODE pnode, const char *name)
int mxml_replace_node_value(PMXML_NODE pnode, const char *value) int mxml_replace_node_value(PMXML_NODE pnode, const char *value)
{ {
int len = strlen(value);
if (pnode->value) if (pnode->value)
pnode->value = (char *)mxml_realloc(pnode->value, strlen(value)+1); pnode->value = (char *)mxml_realloc(pnode->value, len+1);
else if (value) else if (value)
pnode->value = (char *)mxml_malloc(strlen(value)+1); pnode->value = (char *)mxml_malloc(len+1);
else else
pnode->value = NULL; pnode->value = NULL;
if (value) if (value)
strcpy(pnode->value, value); memcpy(pnode->value, value, len+1);
return TRUE; return TRUE;
} }
@@ -1160,7 +1211,7 @@ int mxml_replace_attribute_name(PMXML_NODE pnode, const char *old_name, const ch
if (i == pnode->n_attributes) if (i == pnode->n_attributes)
return FALSE; return FALSE;
strlcpy(pnode->attribute_name+i*MXML_NAME_LENGTH, new_name, MXML_NAME_LENGTH); mxml_strlcpy(pnode->attribute_name+i*MXML_NAME_LENGTH, new_name, MXML_NAME_LENGTH);
return TRUE; return TRUE;
} }
@@ -1180,8 +1231,9 @@ int mxml_replace_attribute_value(PMXML_NODE pnode, const char *attrib_name, cons
if (i == pnode->n_attributes) if (i == pnode->n_attributes)
return FALSE; return FALSE;
pnode->attribute_value[i] = (char *)mxml_realloc(pnode->attribute_value[i], strlen(attrib_value)+1); int len = strlen(attrib_value);
strcpy(pnode->attribute_value[i], attrib_value); pnode->attribute_value[i] = (char *)mxml_realloc(pnode->attribute_value[i], len+1);
memcpy(pnode->attribute_value[i], attrib_value, len+1);
return TRUE; return TRUE;
} }
@@ -1236,7 +1288,7 @@ int mxml_delete_attribute(PMXML_NODE pnode, const char *attrib_name)
mxml_free(pnode->attribute_value[i]); mxml_free(pnode->attribute_value[i]);
for (j=i ; j<pnode->n_attributes-1 ; j++) { for (j=i ; j<pnode->n_attributes-1 ; j++) {
strcpy(pnode->attribute_name+j*MXML_NAME_LENGTH, pnode->attribute_name+(j+1)*MXML_NAME_LENGTH); mxml_strlcpy(pnode->attribute_name+j*MXML_NAME_LENGTH, pnode->attribute_name+(j+1)*MXML_NAME_LENGTH, MXML_NAME_LENGTH);
pnode->attribute_value[j] = pnode->attribute_value[j+1]; pnode->attribute_value[j] = pnode->attribute_value[j+1];
} }
@@ -1260,27 +1312,34 @@ int mxml_delete_attribute(PMXML_NODE pnode, const char *attrib_name)
*/ */
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, ...) 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, ...)
{ {
char *msg, str[1000]; std::string msg;
if (file_name && file_name[0]) {
msg += "XML read error in file \"";
msg += file_name;
msg += "\", line ";
msg += toString(line_number);
msg += ": ";
} else {
msg += "XML read error, line ";
msg += toString(line_number);
msg += ": ";
}
char str[1000];
va_list argptr; va_list argptr;
if (file_name && file_name[0])
sprintf(str, "XML read error in file \"%s\", line %d: ", file_name, line_number);
else
sprintf(str, "XML read error, line %d: ", line_number);
msg = (char *)mxml_malloc(error_size);
if (error)
strlcpy(error, str, error_size);
va_start(argptr, format); va_start(argptr, format);
vsprintf(str, (char *) format, argptr); vsnprintf(str, sizeof(str), (char *) format, argptr);
va_end(argptr); va_end(argptr);
if (error) msg += str;
strlcat(error, str, error_size);
if (error_line) if (error) {
mxml_strlcpy(error, msg.c_str(), error_size);
}
if (error_line) {
*error_line = line_number; *error_line = line_number;
}
mxml_free(msg);
mxml_free_tree(root); mxml_free_tree(root);
return NULL; return NULL;
@@ -1624,17 +1683,13 @@ int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_
int entity_type[MXML_MAX_ENTITY]; /* internal or external */ int entity_type[MXML_MAX_ENTITY]; /* internal or external */
int entity_line_number[MXML_MAX_ENTITY]; int entity_line_number[MXML_MAX_ENTITY];
int nentity; int nentity;
int fh, length, len; int fh, length;
char *buffer;
int ip; /* counter for entity value */
char directoryname[FILENAME_MAX];
char filename[FILENAME_MAX];
int entity_value_length[MXML_MAX_ENTITY]; int entity_value_length[MXML_MAX_ENTITY];
int entity_name_length[MXML_MAX_ENTITY]; int entity_name_length[MXML_MAX_ENTITY];
PMXML_NODE root = mxml_create_root_node(); /* dummy for 'HERE' */ PMXML_NODE root = mxml_create_root_node(); /* dummy for 'HERE' */
for (ip = 0; ip < MXML_MAX_ENTITY; ip++) for (int ip = 0; ip < MXML_MAX_ENTITY; ip++)
entity_value[ip] = NULL; entity_value[ip] = NULL;
line_number = 1; line_number = 1;
@@ -1644,17 +1699,19 @@ int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_
if (!buf || !(*buf) || !strlen(*buf)) if (!buf || !(*buf) || !strlen(*buf))
return 0; return 0;
strcpy(directoryname, file_name); char directoryname[FILENAME_MAX];
mxml_strlcpy(directoryname, file_name, FILENAME_MAX);
mxml_dirname(directoryname); mxml_dirname(directoryname);
/* copy string to temporary space */ /* copy string to temporary space */
buffer = (char *) mxml_malloc(strlen(*buf) + 1); int len = strlen(*buf);
char* buffer = (char *) mxml_malloc(len+1);
if (buffer == NULL) { if (buffer == NULL) {
read_error(HERE, "Cannot allocate memory."); read_error(HERE, "Cannot allocate memory.");
status = 1; status = 1;
goto error; goto error;
} }
strcpy(buffer, *buf); memcpy(buffer, *buf, len+1);
p = strstr(buffer, "!DOCTYPE"); p = strstr(buffer, "!DOCTYPE");
if (p == NULL) { /* no entities */ if (p == NULL) { /* no entities */
@@ -1857,15 +1914,16 @@ int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_
mxml_decode(replacement); mxml_decode(replacement);
if (entity_type[nentity] == EXTERNAL_ENTITY) { if (entity_type[nentity] == EXTERNAL_ENTITY) {
strcpy(entity_reference_name[nentity], replacement); mxml_strlcpy(entity_reference_name[nentity], replacement, sizeof(entity_reference_name[nentity]));
} else { } else {
entity_value[nentity] = (char *) mxml_malloc(strlen(replacement)); int rlen = strlen(replacement);
entity_value[nentity] = (char *) mxml_malloc(rlen+1);
if (entity_value[nentity] == NULL) { if (entity_value[nentity] == NULL) {
read_error(HERE, "Cannot allocate memory."); read_error(HERE, "Cannot allocate memory.");
status = 1; status = 1;
goto error; goto error;
} }
strcpy(entity_value[nentity], replacement); memcpy(entity_value[nentity], replacement, rlen+1);
} }
mxml_free(replacement); mxml_free(replacement);
@@ -1895,11 +1953,15 @@ int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_
/* read external file */ /* read external file */
for (i = 0; i < nentity; i++) { for (i = 0; i < nentity; i++) {
if (entity_type[i] == EXTERNAL_ENTITY) { if (entity_type[i] == EXTERNAL_ENTITY) {
if ( entity_reference_name[i][0] == DIR_SEPARATOR ) /* absolute path */ std::string filename;
strcpy(filename, entity_reference_name[i]); if ( entity_reference_name[i][0] == DIR_SEPARATOR ) { /* absolute path */
else /* relative path */ filename = entity_reference_name[i];
sprintf(filename, "%s%c%s", directoryname, DIR_SEPARATOR, entity_reference_name[i]); } else { /* relative path */
fh = open(filename, O_RDONLY | O_TEXT, 0644); filename += directoryname;
filename += DIR_SEPARATOR;
filename += entity_reference_name[i];
}
fh = open(filename.c_str(), O_RDONLY | O_TEXT, 0644);
if (fh == -1) { if (fh == -1) {
line_number = entity_line_number[i]; line_number = entity_line_number[i];
@@ -1933,7 +1995,7 @@ int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_
close(fh); close(fh);
/* recursive parse */ /* recursive parse */
if (mxml_parse_entity(&entity_value[i], filename, error, error_size, error_line) != 0) { if (mxml_parse_entity(&entity_value[i], filename.c_str(), error, error_size, error_line) != 0) {
status = 1; status = 1;
goto error; goto error;
} }
@@ -1986,11 +2048,13 @@ int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_
} while (*p); } while (*p);
*pv = 0; *pv = 0;
mxml_free_tree(root);
error: error:
if (buffer != NULL) if (buffer != NULL)
mxml_free(buffer); mxml_free(buffer);
for (ip = 0; ip < MXML_MAX_ENTITY; ip++) for (int ip = 0; ip < MXML_MAX_ENTITY; ip++)
if (entity_value[ip] != NULL) if (entity_value[ip] != NULL)
mxml_free(entity_value[ip]); mxml_free(entity_value[ip]);
@@ -2005,35 +2069,55 @@ error:
*/ */
PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line) PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line)
{ {
char *buf, line[1000];
int fh, length;
PMXML_NODE root;
if (error) if (error)
error[0] = 0; error[0] = 0;
fh = open(file_name, O_RDONLY | O_TEXT, 0644); int fh = open(file_name, O_RDONLY | O_TEXT, 0644);
if (fh == -1) { if (fh == -1) {
sprintf(line, "Unable to open file \"%s\": ", file_name); std::string msg = "";
strlcat(line, strerror(errno), sizeof(line)); msg += "Cannot open file \"";
strlcpy(error, line, error_size); msg += file_name;
msg += "\": ";
msg += toStrerror(errno);
mxml_strlcpy(error, msg.c_str(), error_size);
return NULL; return NULL;
} }
length = (int)lseek(fh, 0, SEEK_END); off_t length = lseek(fh, 0, SEEK_END);
lseek(fh, 0, SEEK_SET); lseek(fh, 0, SEEK_SET);
buf = (char *)mxml_malloc(length+1);
char* buf = (char *)mxml_malloc(length+1);
if (buf == NULL) { if (buf == NULL) {
close(fh); close(fh);
sprintf(line, "Cannot allocate buffer: "); std::string msg = "";
strlcat(line, strerror(errno), sizeof(line)); msg += "Cannot allocate buffer size ";
strlcpy(error, line, error_size); msg += toString(length);
msg += " for file \"";
msg += file_name;
msg += "\": ";
msg += toStrerror(errno);
mxml_strlcpy(error, msg.c_str(), error_size);
return NULL; return NULL;
} }
/* read complete file at once */ /* read complete file at once */
length = (int)read(fh, buf, length); int rd = read(fh, buf, length);
if (rd != length) {
std::string msg = "";
msg += "Cannot read file \"";
msg += file_name;
msg += "\", read of ";
msg += toString(length);
msg += " returned ";
msg += toString(rd);
msg += ": ";
msg += toStrerror(errno);
mxml_strlcpy(error, msg.c_str(), error_size);
mxml_free(buf);
return NULL;
}
buf[length] = 0; buf[length] = 0;
close(fh); close(fh);
@@ -2042,7 +2126,7 @@ PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, i
return NULL; return NULL;
} }
root = mxml_parse_buffer(buf, error, error_size, error_line); PMXML_NODE root = mxml_parse_buffer(buf, error, error_size, error_line);
mxml_free(buf); mxml_free(buf);
@@ -2102,12 +2186,47 @@ int mxml_write_tree(const char *file_name, PMXML_NODE tree)
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/**
* write a complete XML tree to a buffer
*/
int mxml_print_tree(char *buffer, int *buffer_size, PMXML_NODE tree)
{
int len;
char *p;
MXML_WRITER *writer;
/* open file */
writer = mxml_open_buffer();
if (writer == NULL)
return FALSE;
for (int i=0 ; i<tree->n_children ; i++)
if (tree->child[i].node_type == ELEMENT_NODE) /* skip PI and comments */
if (!mxml_write_subtree(writer, &tree->child[i], TRUE))
return FALSE;
p = mxml_close_buffer(writer);
len = strlen(p) + 1;
if (len > *buffer_size) {
free(p);
*buffer_size = 0;
return FALSE;
}
mxml_strlcpy(buffer, p, *buffer_size);
free(p);
*buffer_size = len;
return TRUE;
}
/*------------------------------------------------------------------*/
PMXML_NODE mxml_clone_tree(PMXML_NODE tree) PMXML_NODE mxml_clone_tree(PMXML_NODE tree)
{ {
PMXML_NODE clone; PMXML_NODE clone;
int i; int i;
clone = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1); clone = (PMXML_NODE)calloc(1, sizeof(MXML_NODE));
/* copy name, node_type, n_attributes and n_children */ /* copy name, node_type, n_attributes and n_children */
memcpy(clone, tree, sizeof(MXML_NODE)); memcpy(clone, tree, sizeof(MXML_NODE));
@@ -2304,7 +2423,7 @@ void mxml_dirname(char *path)
if (p == 0) /* current directory */ if (p == 0) /* current directory */
strcpy(path, "."); strcpy(path, ".");
else if (p == path) /* root directory */ else if (p == path) /* root directory */
sprintf(path, "%c", *p); snprintf(path, FILENAME_MAX, "%c", *p);
else else
*p = 0; *p = 0;
@@ -2333,3 +2452,10 @@ PMXML_NODE mxml_get_node_at_line(PMXML_NODE tree, int line_number)
return NULL; return NULL;
} }
/* emacs
* Local Variables:
* tab-width: 8
* c-basic-offset: 3
* indent-tabs-mode: nil
* End:
*/
+3 -11
View File
@@ -38,7 +38,7 @@
#define INTERNAL_ENTITY 0 #define INTERNAL_ENTITY 0
#define EXTERNAL_ENTITY 1 #define EXTERNAL_ENTITY 1
#define MXML_MAX_ENTITY 500 #define MXML_MAX_ENTITY 50
#define MXML_MAX_CONDITION 10 #define MXML_MAX_CONDITION 10
@@ -78,11 +78,6 @@ typedef struct mxml_struct {
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* make functions callable from a C++ program */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EXPRT #ifndef EXPRT
#if defined(EXPORT_DLL) #if defined(EXPORT_DLL)
#define EXPRT __declspec(dllexport) #define EXPRT __declspec(dllexport)
@@ -141,16 +136,13 @@ PMXML_NODE mxml_create_root_node(void);
PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line); PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line);
PMXML_NODE mxml_parse_buffer(const char *buffer, char *error, int error_size, int *error_line); PMXML_NODE mxml_parse_buffer(const char *buffer, char *error, int error_size, int *error_line);
int mxml_parse_entity(char **buf, const char* file_name, char *error, int error_size, int *error_line); int mxml_parse_entity(char **buf, const char* file_name, char *error, int error_size, int *error_line);
int mxml_write_tree(const char *file_name, PMXML_NODE tree); int mxml_print_tree(char *buffer, int *buffer_size, PMXML_NODE tree);
void mxml_debug_tree(PMXML_NODE tree, int level); void mxml_debug_tree(PMXML_NODE tree, int level);
void mxml_free_tree(PMXML_NODE tree); void mxml_free_tree(PMXML_NODE tree);
int mxml_write_tree(const char *file_name, PMXML_NODE tree);
void mxml_dirname(char* path); void mxml_dirname(char* path);
void mxml_basename(char *path); void mxml_basename(char *path);
#ifdef __cplusplus
}
#endif
#endif /* _MXML_H_ */ #endif /* _MXML_H_ */
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
-101
View File
@@ -1,101 +0,0 @@
/********************************************************************\
Name: strlcpy.c
Created by: Stefan Ritt
Copyright 2000 + Stefan Ritt
Contents: Contains strlcpy and strlcat which are versions of
strcpy and strcat, but which avoid buffer overflows
This file is part of MIDAS XML Library.
MIDAS XML Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
MIDAS XML Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>.
\********************************************************************/
#include <stdio.h>
#include <string.h>
#include "strlcpy.h"
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless size == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
#ifndef STRLCPY_DEFINED
size_t strlcpy(char *dst, const char *src, size_t size)
{
char *d = dst;
const char *s = src;
size_t n = size;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (size != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++);
}
return (s - src - 1); /* count does not include NUL */
}
/*-------------------------------------------------------------------*/
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless size <= strlen(dst)).
* Returns strlen(src) + MIN(size, strlen(initial dst)).
* If retval >= size, truncation occurred.
*/
size_t strlcat(char *dst, const char *src, size_t size)
{
char *d = dst;
const char *s = src;
size_t n = size;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = size - dlen;
if (n == 0)
return (dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return (dlen + (s - src)); /* count does not include NUL */
}
/*-------------------------------------------------------------------*/
#endif // STRLCPY_DEFINED
-55
View File
@@ -1,55 +0,0 @@
/********************************************************************\
Name: strlcpy.h
Created by: Stefan Ritt
Copyright 2000 + Stefan Ritt
Contents: Header file for strlcpy.c
This file is part of MIDAS XML Library.
MIDAS XML Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
MIDAS XML Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>.
\********************************************************************/
#ifndef _STRLCPY_H_
#define _STRLCPY_H_
// some version of gcc have a built-in strlcpy
#ifdef strlcpy
#define STRLCPY_DEFINED
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EXPRT
#if defined(EXPORT_DLL)
#define EXPRT __declspec(dllexport)
#else
#define EXPRT
#endif
#endif
#ifndef STRLCPY_DEFINED
size_t EXPRT strlcpy(char *dst, const char *src, size_t size);
size_t EXPRT strlcat(char *dst, const char *src, size_t size);
#endif
#ifdef __cplusplus
}
#endif
#endif /*_STRLCPY_H_ */