/* nXml - Copyright (C) 2005-2007 bakunin - Andrea Marchesini * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #else # error Use configure; make; make install #endif #include "nxml.h" static int __nxml_parse_unique_attribute (nxml_attr_t * attr, char *name) { /* * Rule [40] - Well-formedness contraint: Unique Att Spec */ while (attr) { if (!strcmp (attr->name, name)) return 1; attr = attr->next; } return 0; } static char * __nxml_parse_string (nxml_t * doc, char *buffer, int size) { char *real; int i; int q; __nxml_string_t *ret; ret = __nxml_string_new (); for (q = i = 0; i < size; i++) { if (*(buffer + i) == 0xd) continue; if (*(buffer + i) == 0xa || *(buffer + i) == 0x9 || *(buffer + i) == 0x20) { if (!q) { if (!doc->priv.textindent) q = 1; __nxml_string_add (ret, buffer + i, 1); } } else if (*(buffer + i) == '&') { if (!strncmp (buffer + i, "<", 4)) { __nxml_string_add (ret, "<", 1); i += 3; q = 0; } else if (!strncmp (buffer + i, ">", 4)) { __nxml_string_add (ret, ">", 1); i += 3; q = 0; } else if (!strncmp (buffer + i, "&", 5)) { __nxml_string_add (ret, "&", 1); i += 4; q = 0; } else if (!strncmp (buffer + i, "'", 6)) { __nxml_string_add (ret, "'", 1); i += 5; q = 0; } else if (!strncmp (buffer + i, """, 6)) { __nxml_string_add (ret, "\"", 1); i += 5; q = 0; } else if (*(buffer + i + 1) == '#') { char buf[1024]; int k = i; int last; while (*(buffer + k) != ';' && k < size) k++; last = k - (i + 2) > sizeof (buf) ? sizeof (buf) : k - (i + 2); strncpy (buf, buffer + i + 2, last); buf[last] = 0; if (buf[0] != 'x') last = atoi (buf); else last = __nxml_atoi (&buf[1]); if ((last = __nxml_int_charset (last, (unsigned char *) buf, doc->encoding)) > 0) __nxml_string_add (ret, buf, last); else __nxml_string_add (ret, buffer + i, 1); i += k - i; q = 0; } else { __nxml_entity_t *entity; char buf[1024]; int k = i; int last; while (*(buffer + k) != ';' && k < size) k++; last = k - (i + 1) > sizeof (buf) ? sizeof (buf) : k - (i + 1); strncpy (buf, buffer + i + 1, last); buf[last] = 0; for (entity = doc->priv.entities; entity; entity = entity->next) { if (!strcmp (entity->name, buf)) { __nxml_string_add (ret, entity->entity, strlen (entity->entity)); break; } } if (!entity) __nxml_string_add (ret, buffer + i, 1); else i += strlen (entity->name) + 1; q = 0; } } else { q = 0; __nxml_string_add (ret, buffer + i, 1); } } if (!(real = __nxml_string_free (ret))) real = strdup (""); return real; } static char * __nxml_parse_get_attr (nxml_t * doc, char **buffer, size_t * size) { char attr[1024]; int i; int byte; int64_t ch; if (!*size) return NULL; if (!__NXML_NAMESTARTCHARS) return NULL; memcpy (&attr[0], *buffer, byte); i = byte; (*buffer) += byte; (*size) -= byte; while (__NXML_NAMECHARS && *size && i < sizeof (attr) - 1) { memcpy (&attr[i], *buffer, byte); i += byte; (*buffer) += byte; (*size) -= byte; } if (**buffer != 0x20 && **buffer != 0x9 && **buffer != 0xa && **buffer != 0xd && **buffer != '=') { (*buffer) -= i; (*size) += i; return NULL; } i += __nxml_escape_spaces (doc, buffer, size); if (**buffer != '=') { (*buffer) -= i; (*size) += i; return NULL; } (*buffer)++; (*size)--; __nxml_escape_spaces (doc, buffer, size); attr[i] = 0; return strdup (attr); } static nxml_error_t __nxml_parse_get_attribute (nxml_t * doc, char **buffer, size_t * size, nxml_attr_t ** attr) { /* * Rule [41] - Attribute ::= Name Eq AttValue * Rule [25] - Eq ::= S? '=' S? * Rule [5] - Name ::= NameStartChar (NameChar)* * Rule [4] - NameStartChar ::= ":" | [A-Z] | ["_"] | [a-z] | Unicode... * Rule [4a] - NameChar ::= NameStarChar | "-" | "." | [0-9] | Unicode... * Rule [10] - AttValue ::= '"' ([^<&"] | Reference)* '"' | * "'" ([^<&'] | Reference)* "'" */ char *tag, *value, *v; if (!*size) return NXML_OK; *attr = NULL; __nxml_escape_spaces (doc, buffer, size); if (!(tag = __nxml_parse_get_attr (doc, buffer, size))) return NXML_OK; if (!(value = __nxml_get_value (doc, buffer, size))) { free (tag); if (doc->priv.func) doc->priv.func ("%s: expected value of attribute (line %d)\n", doc->file ? doc->file : "", doc->priv.line); return NXML_ERR_PARSER; } if (!(v = __nxml_parse_string (doc, value, strlen (value)))) { free (tag); return NXML_ERR_POSIX; } free (value); value = v; __nxml_escape_spaces (doc, buffer, size); if (!(*attr = (nxml_attr_t *) calloc (1, sizeof (nxml_attr_t)))) { free (tag); free (value); return NXML_ERR_POSIX; } (*attr)->name = tag; (*attr)->value = value; return NXML_OK; } static nxml_error_t __nxml_parse_cdata (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data) { /* * Rule [18] - CDSect ::= CDStart CData CDEnd * Rule [19] - CDStart ::= '' Char *)) * Rule [21] - CDEnd ::= ']]>' */ int i = 0; nxml_data_t *t; char *value; while (i < *size) { if (!strncmp (*buffer + i, "]]>", 3)) break; if (*(*buffer + i) == 0xa && doc->priv.func) doc->priv.line++; i++; } if (strncmp (*buffer + i, "]]>", 3)) { if (doc->priv.func) doc->priv.func ("%s: expected ']]>' as close of a CDATA (line %d)\n", doc->file ? doc->file : "", doc->priv.line); return NXML_ERR_PARSER; } if (!(t = (nxml_data_t *) calloc (1, sizeof (nxml_data_t)))) return NXML_ERR_POSIX; t->doc = doc; if (!(value = (char *) malloc (sizeof (char) * (i + 1)))) { free (t); return NXML_ERR_POSIX; } strncpy (value, *buffer, i); value[i] = 0; t->value = value; t->type = NXML_TYPE_TEXT; (*buffer) += i + 3; (*size) -= i + 3; *data = t; return NXML_OK; } static void __nxml_parse_entity (nxml_t * doc, char **buffer, size_t * size) { /* * [70] EntityDecl ::= GEDecl | PEDecl * [71] GEDecl ::= '' * [72] PEDecl ::= '' * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) * [74] PEDef ::= EntityValue | ExternalID */ int i; char name[1024]; char *entity; int byte; int64_t ch; __nxml_escape_spaces (doc, buffer, size); if (strncmp (*buffer, "' || q) && i < *size) { if (*(*buffer + i) == '<') q++; else if (*(*buffer + i) == '>') q--; i++; } if (*(*buffer) == '>') i++; (*buffer) += i; (*size) -= i; return; } *buffer += 8; *size -= 8; __nxml_escape_spaces (doc, buffer, size); /* Name */ if (!__NXML_NAMESTARTCHARS) { int q = i = 0; while ((*(*buffer + i) != '>' || q) && i < *size) { if (*(*buffer + i) == '<') q++; else if (*(*buffer + i) == '>') q--; i++; } if (*(*buffer) == '>') i++; (*buffer) += i; (*size) -= i; return; } memcpy (&name[0], *buffer, byte); i = byte; (*buffer) += byte; (*size) -= byte; while (__NXML_NAMECHARS && *size && i < sizeof (name) - 1) { memcpy (&name[i], *buffer, byte); i += byte; (*buffer) += byte; (*size) -= byte; } name[i] = 0; if (!i || !strcmp (name, "%")) { int q = i = 0; while ((*(*buffer + i) != '>' || q) && i < *size) { if (*(*buffer + i) == '<') q++; else if (*(*buffer + i) == '>') q--; i++; } if (*(*buffer) == '>') i++; (*buffer) += i; (*size) -= i; return; } __nxml_escape_spaces (doc, buffer, size); entity = __nxml_get_value (doc, buffer, size); __nxml_escape_spaces (doc, buffer, size); if (**buffer == '>') { (*buffer)++; (*size)--; } if (entity) { __nxml_entity_t *e; if (!(e = calloc (1, sizeof (__nxml_entity_t)))) { free (entity); return; } if (!(e->name = strdup (name))) { free (e); free (entity); return; } e->entity = entity; if (!doc->priv.entities) doc->priv.entities = e; else { __nxml_entity_t *tmp = doc->priv.entities; while (tmp->next) tmp = tmp->next; tmp->next = e; } } } static nxml_error_t __nxml_parse_doctype (nxml_t * doc, char **buffer, size_t * size, int *doctype) { /* * Rule [28] - doctypedecl ::= '' */ nxml_doctype_t *t; nxml_doctype_t *tmp; char str[1024]; char *value; int i; int byte; int64_t ch; int q = 0; __nxml_escape_spaces (doc, buffer, size); if (!__NXML_NAMESTARTCHARS) { if (doc->priv.func) doc->priv.func ("%s: abnormal char '%c' (line %d)\n", doc->file ? doc->file : "", **buffer, doc->priv.line); return NXML_ERR_PARSER; } memcpy (&str[0], *buffer, byte); i = byte; (*buffer) += byte; (*size) -= byte; while (__NXML_NAMECHARS && *size && i < sizeof (str) - 1) { memcpy (&str[i], *buffer, byte); i += byte; (*buffer) += byte; (*size) -= byte; } str[i] = 0; if (!(t = (nxml_doctype_t *) calloc (1, sizeof (nxml_doctype_t)))) return NXML_ERR_POSIX; t->doc = doc; if (!(t->name = strdup (str))) { free (t); return NXML_ERR_POSIX; } __nxml_escape_spaces (doc, buffer, size); i = 0; while ((*(*buffer + i) != '>' || q) && i < *size) { if (*(*buffer + i) == '<') q++; else if (*(*buffer + i) == '>') q--; if (*(*buffer + i) == 0xa && doc->priv.func) doc->priv.line++; i++; } if (*(*buffer + i) != '>') { if (doc->priv.func) doc->priv.func ("%s: expected '>' as close of a doctype (line %d)\n", doc->file ? doc->file : "", doc->priv.line); free (t->value); free (t); return NXML_ERR_PARSER; } if (!(value = __nxml_parse_string (doc, *buffer, i))) { free (t->value); free (t); return NXML_ERR_POSIX; } t->value = value; (*buffer) += i + 1; (*size) -= i + 1; tmp = doc->doctype; if (!tmp) doc->doctype = t; else { while (tmp->next) tmp = tmp->next; tmp->next = t; } *doctype = 1; while (value && *value && *value != '[') value++; if (value && *value == '[') { unsigned int size; value++; size = strlen (value); while (size > 0 && value && *value) __nxml_parse_entity (doc, &value, (size_t *)&size); } return NXML_OK; } static nxml_error_t __nxml_parse_comment (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data) { /* * Rule [15] - Comment ::= '' */ int i = 0; nxml_data_t *t; char *value; while (strncmp (*buffer + i, "-->", 3) && i < *size) { if (*(*buffer + i) == 0xa && doc->priv.func) doc->priv.line++; i++; } if (strncmp (*buffer + i, "-->", 3)) { if (doc->priv.func) doc->priv.func ("%s: expected '--' as close comment (line %d)\n", doc->file ? doc->file : "", doc->priv.line); return NXML_ERR_PARSER; } if (!(t = (nxml_data_t *) calloc (1, sizeof (nxml_data_t)))) return NXML_ERR_POSIX; t->doc = doc; if (!(value = __nxml_parse_string (doc, *buffer, i))) { free (t); return NXML_ERR_POSIX; } t->value = value; (*buffer) += i + 3; (*size) -= i + 3; t->type = NXML_TYPE_COMMENT; *data = t; return NXML_OK; } static nxml_error_t __nxml_parse_pi (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data) { /* * Rule [16] - PI ::= '' Char *)))? * '?>' * Rule [17] - PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) */ int i = 0; nxml_data_t *t; char *value; if (!*size) return NXML_OK; *data = NULL; (*buffer) += 1; (*size) -= 1; while (strncmp (*buffer + i, "?>", 2) && i < *size) { if (*(*buffer + i) == 0xa && doc->priv.func) doc->priv.line++; i++; } if (strncmp (*buffer + i, "?>", 2)) { if (doc->priv.func) doc->priv.func ("%s: expected '?' as close pi tag (line %d)\n", doc->file ? doc->file : "", doc->priv.line); return NXML_ERR_PARSER; } if (!strncasecmp (*buffer, "?xml", 4)) { if (doc->priv.func) doc->priv.func ("%s: pi xml is reserved! (line %d)\n", doc->file ? doc->file : "", doc->priv.line); return NXML_ERR_PARSER; } if (!(t = (nxml_data_t *) calloc (1, sizeof (nxml_data_t)))) return NXML_ERR_POSIX; t->doc = doc; if (!(value = __nxml_parse_string (doc, *buffer, i))) { free (t); return NXML_ERR_POSIX; } t->value = value; (*buffer) += i + 2; (*size) -= i + 2; t->type = NXML_TYPE_PI; *data = t; return NXML_OK; } static nxml_error_t __nxml_parse_other (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data, int *doctype) { /* Tags 'priv.func) doc->priv.func ("%s: abnormal tag (line %d)\n", doc->file ? doc->file : "", doc->priv.line); return NXML_ERR_PARSER; } } static nxml_error_t __nxml_parse_text (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data) { int i = 0; nxml_data_t *t; char *value; char *value_new; *data = NULL; if (!*size) return NXML_OK; while (*(*buffer + i) != '<' && i < *size) { if (*(*buffer + i) == 0xa && doc->priv.func) doc->priv.line++; i++; } if (!(t = (nxml_data_t *) calloc (1, sizeof (nxml_data_t)))) return NXML_ERR_POSIX; t->doc = doc; if (!(value = __nxml_parse_string (doc, *buffer, i))) { free (t); return NXML_ERR_POSIX; } (*buffer) += i; (*size) -= i; value_new = __nxml_trim (value); free (value); if (!value_new) { free (t); return NXML_ERR_POSIX; } t->value = value_new; t->type = NXML_TYPE_TEXT; *data = t; return NXML_OK; } static nxml_error_t __nxml_parse_close (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data) { /* * Rule [42] - ETag ::= '' */ nxml_data_t *tag; char str[1024]; int i; int byte; int64_t ch; *data = NULL; if (!*size) return NXML_OK; if (!__NXML_NAMESTARTCHARS) { if (doc->priv.func) doc->priv.func ("%s: abnormal char '%c' (line %d)\n", doc->file ? doc->file : "", **buffer, doc->priv.line); return NXML_ERR_PARSER; } memcpy (&str[0], *buffer, byte); i = byte; (*buffer) += byte; (*size) -= byte; while (__NXML_NAMECHARS && *size && i < sizeof (str) - 1) { memcpy (&str[i], *buffer, byte); i += byte; (*buffer) += byte; (*size) -= byte; } str[i] = 0; __nxml_escape_spaces (doc, buffer, size); if (**buffer != '>') { if (doc->priv.func) doc->priv.func ("%s: expected char '>' after tag %s (line %d)\n", doc->file ? doc->file : "", str, doc->priv.line); return NXML_ERR_PARSER; } (*buffer) += 1; (*size) -= 1; if (!(tag = (nxml_data_t *) calloc (1, sizeof (nxml_data_t)))) return NXML_ERR_POSIX; tag->doc = doc; if (!(tag->value = strdup (str))) { free (tag); return NXML_ERR_POSIX; } tag->type = NXML_TYPE_ELEMENT_CLOSE; *data = tag; return NXML_OK; } static nxml_error_t __nxml_parse_get_tag (nxml_t * doc, char **buffer, size_t * size, nxml_data_t ** data, int *doctype) { /* Parse the element... */ nxml_attr_t *attr, *last; nxml_data_t *tag, *child, *child_last; nxml_error_t err; char str[1024]; int i; int closed = 0; int byte; int64_t ch; *data = NULL; *doctype = 0; if (!*size) return NXML_OK; __nxml_escape_spaces (doc, buffer, size); /* Text */ if (**buffer != '<') return __nxml_parse_text (doc, buffer, size, data); (*buffer) += 1; (*size) -= 1; /* Comment, CData, DocType or other elements */ if (**buffer == '!') return __nxml_parse_other (doc, buffer, size, data, doctype); /* PI */ else if (**buffer == '?') return __nxml_parse_pi (doc, buffer, size, data); /* Close tag */ else if (**buffer == '/') { (*buffer) += 1; (*size) -= 1; return __nxml_parse_close (doc, buffer, size, data); } __nxml_escape_spaces (doc, buffer, size); if (!__NXML_NAMESTARTCHARS) { if (doc->priv.func) doc->priv.func ("%s: abnormal char '%c' (line %d)\n", doc->file ? doc->file : "", **buffer, doc->priv.line); return NXML_ERR_PARSER; } memcpy (&str[0], *buffer, byte); i = byte; (*buffer) += byte; (*size) -= byte; while (__NXML_NAMECHARS && *size && i < sizeof (str) - 1) { memcpy (&str[i], *buffer, byte); i += byte; (*buffer) += byte; (*size) -= byte; } str[i] = 0; if (**buffer != 0x20 && **buffer != 0x9 && **buffer != 0xa && **buffer != 0xd && **buffer != '>' && **buffer != '/') { (*buffer) -= i; (*size) += i; if (doc->priv.func) doc->priv.func ("%s: abnormal char '%c' after tag %s (line %d)\n", doc->file ? doc->file : "", *(*buffer + i), str, doc->priv.line); return NXML_ERR_PARSER; } if (!(tag = (nxml_data_t *) calloc (1, sizeof (nxml_data_t)))) return NXML_ERR_POSIX; tag->doc = doc; if (!(tag->value = strdup (str))) { free (tag); return NXML_ERR_POSIX; } last = NULL; /* Get attribute: */ while (!(err = __nxml_parse_get_attribute (doc, buffer, size, &attr)) && attr) { if (__nxml_parse_unique_attribute (tag->attributes, attr->name)) { if (doc->priv.func) doc->priv. func ("%s: Duplicate attribute '%s' in tag '%s' (line %d)\n", doc->file ? doc->file : "", attr->name, tag->value, doc->priv.line); nxml_free_attribute (attr); nxml_free_data (tag); return NXML_ERR_PARSER; } if (last) last->next = attr; else tag->attributes = attr; last = attr; } if (err) { nxml_free_data (tag); return err; } /* Closed element */ if (**buffer == '/') { closed++; (*buffer) += 1; (*size) -= 1; __nxml_escape_spaces (doc, buffer, size); } if (**buffer != '>') { if (doc->priv.func) doc->priv.func ("%s: expected char '>' after tag %s (line %d)\n", doc->file ? doc->file : "", tag->value, doc->priv.line); nxml_free_data (tag); return NXML_ERR_PARSER; } (*buffer) += 1; (*size) -= 1; if (!closed) { child_last = NULL; /* Search children: */ while (! (err = __nxml_parse_get_tag (doc, buffer, size, &child, doctype)) && (*doctype || child)) { if (*doctype) continue; /* If the current child, break: */ if (child->type == NXML_TYPE_ELEMENT_CLOSE) { if (!strcmp (child->value, tag->value)) { closed = 1; nxml_free_data (child); break; } else { if (doc->priv.func) doc->priv. func ("%s: expected tag '/%s' and not '%s' (line %d)\n", doc->file ? doc->file : "", tag->value, child->value, doc->priv.line); nxml_free_data (child); nxml_free_data (tag); return NXML_ERR_PARSER; } } /* Set the parent */ child->parent = tag; if (child_last) child_last->next = child; else tag->children = child; child_last = child; } if (err) { nxml_free_data (tag); return err; } } tag->type = NXML_TYPE_ELEMENT; if (!closed) { if (doc->priv.func) doc->priv.func ("%s: expected tag '/%s' (line %d)\n", doc->file ? doc->file : "", tag->value, doc->priv.line); nxml_free_data (tag); return NXML_ERR_PARSER; } *data = tag; return NXML_OK; } static nxml_error_t __nxml_parse_buffer (nxml_t * nxml, char *r_buffer, size_t r_size) { /* * Rule [1] - Document ::= prolog element Misc* - Char* RestrictedChar Char* */ nxml_attr_t *attr; nxml_error_t err; nxml_charset_t charset; nxml_data_t *tag, *last, *root; int doctype; int freed; char *buffer = NULL; size_t size; if (!r_buffer || !nxml) return NXML_ERR_DATA; if (!r_size) r_size = strlen (r_buffer); switch ((freed = __nxml_utf_detection (r_buffer, r_size, &buffer, &size, &charset))) { case 0: buffer = r_buffer; size = r_size; break; case -1: return NXML_ERR_POSIX; } nxml->priv.line = 1; nxml->version = NXML_VERSION_1_0; nxml->standalone = 1; /* * Rule [22] - prolog ::= XMLDecl Misc* (doctypedecl Misc*)? * Rule [23] - XMLDecl ::= '' */ if (!strncmp (buffer, "priv.func) nxml->priv.func ("%s: expected 'version' attribute (line %d)\n", nxml->file ? nxml->file : "", nxml->priv.line); if (freed) free (buffer); return NXML_ERR_PARSER; } if (!strcmp (attr->value, "1.0")) nxml->version = NXML_VERSION_1_0; else if (!strcmp (attr->value, "1.1")) nxml->version = NXML_VERSION_1_1; else { if (nxml->priv.func) nxml->priv. func (PACKAGE " " VERSION " suports only xml 1.1 or 1.0 (line %d)\n", nxml->priv.line); if (freed) free (buffer); return NXML_ERR_PARSER; } nxml_free_attribute (attr); while (!(err = __nxml_parse_get_attribute (nxml, &buffer, &size, &attr)) && attr) { if (!strcmp (attr->name, "standalone")) { if (!strcmp (attr->value, "yes")) nxml->standalone = 1; else nxml->standalone = 0; } else if (!strcmp (attr->name, "encoding")) { nxml->encoding = strdup (attr->value); if (!nxml->encoding) { nxml_empty (nxml); nxml_free_attribute (attr); if (freed) free (buffer); return NXML_ERR_POSIX; } } else { if (nxml->priv.func) nxml->priv.func ("%s: unexpected attribute '%s' (line %d)\n", nxml->file ? nxml->file : "", attr->name, nxml->priv.line); nxml_empty (nxml); nxml_free_attribute (attr); if (freed) free (buffer); return NXML_ERR_PARSER; } nxml_free_attribute (attr); } if (err || strncmp (buffer, "?>", 2)) { if (nxml->priv.func) nxml->priv.func ("%s expected '?>' (line %d)\n", nxml->file ? nxml->file : "", nxml->priv.line); nxml_empty (nxml); if (freed) free (buffer); return NXML_ERR_PARSER; } buffer += 2; size -= 2; } root = last = NULL; while (!(err = __nxml_parse_get_tag (nxml, &buffer, &size, &tag, &doctype)) && (doctype || tag)) { if (doctype) continue; if (tag->type == NXML_TYPE_ELEMENT && !root) root = tag; if (last) last->next = tag; else nxml->data = tag; last = tag; } if (err) { nxml_empty (nxml); if (freed) free (buffer); return NXML_ERR_PARSER; } if (!root) { if (nxml->priv.func) nxml->priv.func ("%s: No root element founded!\n", nxml->file ? nxml->file : ""); nxml_empty (nxml); if (freed) free (buffer); return NXML_ERR_PARSER; } if (freed) free (buffer); nxml->charset_detected = charset; __nxml_namespace_parse (nxml); return NXML_OK; } /* EXTERNAL FUNCTIONS *******************************************************/ nxml_error_t nxml_parse_url (nxml_t * nxml, char *url) { nxml_error_t err; char *buffer; size_t size; if (!url || !nxml) return NXML_ERR_DATA; if ((err = nxml_download_file (nxml, url, &buffer, &size)) != NXML_OK) return err; if (nxml->file) free (nxml->file); if (!(nxml->file = strdup (url))) { nxml_empty (nxml); return NXML_ERR_POSIX; } nxml->size = size; nxml_empty (nxml); err = __nxml_parse_buffer (nxml, buffer, size); free (buffer); return err; } nxml_error_t nxml_parse_file (nxml_t * nxml, char *file) { nxml_error_t err; char *buffer; struct stat st; int fd, len, ret; if (!file || !nxml) return NXML_ERR_DATA; if (stat (file, &st)) return NXML_ERR_POSIX; if ((fd = open (file, O_RDONLY)) < 0) return NXML_ERR_POSIX; if (!(buffer = (char *) malloc (sizeof (char) * (st.st_size + 1)))) return NXML_ERR_POSIX; len = 0; while (len < st.st_size) { if ((ret = read (fd, buffer + len, st.st_size - len)) <= 0) { free (buffer); close (fd); return NXML_ERR_POSIX; } len += ret; } buffer[len] = 0; close (fd); nxml_empty (nxml); if (nxml->file) free (nxml->file); if (!(nxml->file = strdup (file))) { nxml_empty (nxml); free (buffer); return NXML_ERR_POSIX; } nxml->size = st.st_size; err = __nxml_parse_buffer (nxml, buffer, st.st_size); free (buffer); return err; } nxml_error_t nxml_parse_buffer (nxml_t * nxml, char *buffer, size_t size) { if (!buffer || !nxml) return NXML_ERR_DATA; nxml_empty (nxml); if (nxml->file) free (nxml->file); if (!(nxml->file = strdup ("buffer"))) { nxml_empty (nxml); return NXML_ERR_POSIX; } nxml->size = size; return __nxml_parse_buffer (nxml, buffer, size); } /* EOF */