diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2003-10-17 15:36:42 +0000 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2003-10-17 15:36:42 +0000 |
| commit | d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5 (patch) | |
| tree | 84d0cacfd0b6c1241c236c7860f7cbd7f26901bb /lib/base/nxml.cpp | |
| download | enigma2-d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5.tar.gz enigma2-d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5.zip | |
import of enigma2
Diffstat (limited to 'lib/base/nxml.cpp')
| -rw-r--r-- | lib/base/nxml.cpp | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/lib/base/nxml.cpp b/lib/base/nxml.cpp new file mode 100644 index 00000000..f32880a6 --- /dev/null +++ b/lib/base/nxml.cpp @@ -0,0 +1,339 @@ +#include <lib/base/nconfig.h> +#include <string.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_TIME_H +#include <time.h> +#endif + +#ifdef HAVE_LIBXML2 +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/parserInternals.h> +#else +#define xmlChar char +#endif /* HAVE_LIBXML2 */ + +#define DE(x) ((struct nc_de_s *) (data+(x))) +#define IDE(x, y) (DE(((unsigned *) (data+(x)->offset))[(y)])) +#define XML_DE ((const xmlChar *) "dirEntry") +#define XML_NS ((const xmlChar *) "http://hq.alert.sk/projects/nconfig") +#define XML_ROOT ((const xmlChar *) "NConfigExport") + +static char *encodeXml(const char *what) +{ + unsigned p = 0, size = 6*strlen(what)+1; + char *ret = (char *)malloc(size); + for (; *what; what++) { + switch (*what) { + case '"': + ret[p++] = '&'; + ret[p++] = 'q'; + ret[p++] = 'u'; + ret[p++] = 'o'; + ret[p++] = 't'; + ret[p++] = ';'; + continue; + case '>': + ret[p++] = '&'; + ret[p++] = 'q'; + ret[p++] = 't'; + ret[p++] = ';'; + continue; + case '<': + ret[p++] = '&'; + ret[p++] = 'l'; + ret[p++] = 't'; + ret[p++] = ';'; + continue; + case '&': + ret[p++] = '&'; + ret[p++] = 'a'; + ret[p++] = 'm'; + ret[p++] = 'p'; + ret[p++] = ';'; + continue; + } + if (*what >= 0x20 || *what == '\n' || *what == '\r' || *what == '\t') + ret[p++] = *what; + else + p += sprintf(ret+p, "&#%d;", *what); + } + ret[p] = '\0'; + return ret; +} + +void NConfig::store(nc_de_s *de, FILE *f) +{ + struct nc_de_s *cc; + for (unsigned i=0; i<de->pages; i++) + if ((cc = IDE(de, i))->type) { + char *encname = encodeXml(data+cc->name); + fprintf(f, "<nc:%s name=\"%s\" type=\"%d\" value=\"", XML_DE, encname, cc->type); + free(encname); + switch (cc->type) { + case NC_DIR: + fprintf(f, "%u\">\n", cc->pages); + store(cc, f); + fprintf(f, "</nc:%s>\n", XML_DE); + break; + case NC_STRING: + fprintf(f, "%s\"/>\n", encname = encodeXml(data+cc->offset)); + free(encname); + break; + case NC_INT: + fprintf(f, "%lld\"/>\n", *((signed long long *) (data+cc->offset))); + break; + case NC_UINT: + fprintf(f, "%llu\"/>\n", *((unsigned long long *) (data+cc->offset))); + break; + case NC_DOUBLE: + fprintf(f, "%La\"/>\n", *((long double *) (data+cc->offset))); + break; + case NC_RAW: + { + const char *raw = data+cc->offset; + for (unsigned j=0; j<cc->pages; j++) + fprintf(f, "%d%d%d", raw[j] / 100, (raw[j] % 100) / 10, raw[j] % 10); + fprintf(f, "\"/>\n"); + } + } + } +} + +int NConfig::toXML(const char *filename) +{ + if (fd < 0) + return NC_ERR_NFILE; + + FILE *f = fopen(filename, "w"); + if (!f) + return NC_ERR_PERM; + + fprintf(f, "%s", "<?xml version=\"1.0\"?>\n"); + fprintf(f, "<nc:%s xmlns:nc=\"%s\" libVersion=\"%s\"", XML_ROOT, XML_NS, VERSION); +#ifdef HAVE_TIME_H + time_t t = time(NULL); + char *tim = ctime(&t); + tim[strlen(tim)-1] = 0; + fprintf(f, " time=\"%s\"", tim); +#endif /* HAVE_TIME_H */ + fprintf(f, ">\n"); + lockFile(NC_L_RO); + + store(rdir, f); + + unLockFile(); + fprintf(f, "</nc:%s>\n", XML_ROOT); + fclose(f); + return NC_ERR_OK; +} + +#ifdef HAVE_LIBXML2 +static xmlSAXHandler sh; +enum stateEnum {noRoot = 0, inRoot, inDir, inEnt, unknown}; + +struct ncParseState { + stateEnum state, pState; + xmlChar *ns; + unsigned depth; + unsigned unDepth; + unsigned force; + NConfig *which; +}; + +static int ncXmlSAXParseFile(xmlSAXHandlerPtr sax, void *user_data, const char *filename) +{ + int ret = 0; + xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename); + if (!ctxt) + return -1; + ctxt->sax = sax; + ctxt->userData = user_data; + xmlParseDocument(ctxt); + ret = ctxt->wellFormed ? 0 : -1; + if (sax) + ctxt->sax = NULL; + xmlFreeParserCtxt(ctxt); + return ret; +} + +static xmlEntityPtr ncXmlGetEntity(void *user_data, const CHAR *name) +{ + return xmlGetPredefinedEntity(name); +} + +static void ncXmlStartElement(void *user_data, const CHAR *name, const CHAR **attrs) +{ + struct ncParseState *p = (struct ncParseState *)user_data; +#ifdef NC_DEBUG_XML + fprintf(stderr, "New element %s state=%d %s\n", name, p->state, p->ns); +#endif + if (p->state == unknown) { + p->unDepth++; + return; + } + if (p->state == noRoot) { + while (*attrs) { + if (!xmlStrncmp(*attrs, (const xmlChar *) "xmlns:", 6)) { + if (!xmlStrcmp(attrs[1], XML_NS)) { + p->ns = xmlStrdup((*attrs)+6); + break; + } + } + attrs += 2; + } + char *b = (char *) malloc(xmlStrlen(p->ns)+xmlStrlen(XML_ROOT)+2); + sprintf(b, "%s:%s", p->ns, XML_ROOT); + if (xmlStrcmp(name, (xmlChar *)b)) { +#ifdef NC_DEBUG_XML + fprintf(stderr, "NewElement, entering unknown %s\n", name); +#endif + p->pState = p->state; + p->state = unknown; + } else + p->state = inRoot; + free(b); + return; + } + if (p->state == inRoot || p->state == inDir) { + const xmlChar *value = NULL, *n = NULL; + int type = 0; + while (*attrs) { + if (!xmlStrcmp(*attrs, (const xmlChar *)"value")) + value = attrs[1]; + if (!xmlStrcmp(*attrs, (const xmlChar *)"name")) + n = attrs[1]; + if (!xmlStrcmp(*attrs, (const xmlChar *)"type")) + type = atoi(attrs[1]); + attrs += 2; + } +#ifdef NC_DEBUG_XML + fprintf(stderr, "%s %s %s %d %d\n", name, n, value, type, p->state); +#endif + char *b = (char *) malloc(xmlStrlen(p->ns)+xmlStrlen(XML_DE)+2); + sprintf(b, "%s:%s", p->ns, XML_DE); + if (xmlStrcmp(name, (xmlChar *)b) || !type || !value || !n) { +#ifdef NC_DEBUG_XML + fprintf(stderr, "NewElement, entering unknown on mismatch\n"); +#endif + p->pState = p->state; + p->state = unknown; + free(b); + return; + } + free(b); + if (p->force) + p->which->delKey((const char *)n); + + switch (type) { + case NC_DIR: + if (p->which->createDir((const char *)n, strtoul((const char *)value, NULL, 0)) != NC_ERR_OK) { + p->pState = p->state; + p->state = unknown; +#ifdef NC_DEBUG_XML + fprintf(stderr, "NewElement, entering unknown on failed mkdir\n"); +#endif + return; + } + p->which->chDir((const char *)n); + break; + case NC_STRING: + p->which->setKey((const char *)n, (const char *)value); + break; + case NC_INT: + p->which->setKey((const char *)n, strtoll((const char *)value, NULL, 0)); + break; + case NC_UINT: + p->which->setKey((const char *)n, strtoull((const char *)value, NULL, 0)); + break; + case NC_DOUBLE: + { + long double c; + sscanf((const char *)value, "%La", &c); + p->which->setKey((const char *)n, c); + } + break; + case NC_RAW: + { + unsigned size = xmlStrlen(value) / 3; + char *dec = NULL; + if (size) { + dec = (char *)malloc(size); + for (unsigned i=0, k=0; i<size; i++, k += 3) + dec[i] = value[k] * 100 + value[k+1] * 10 + value[k+2]; + } + p->which->setKey((const char *)n, dec, size); + free(dec); + } + } + if (type == NC_DIR) { + p->state = inDir; + p->depth++; + } else { + p->pState = p->state; + p->state = inEnt; + } + return; + } +} + +static void ncXmlEndElement(void *user_data, const CHAR *name) +{ + struct ncParseState *p = (struct ncParseState *)user_data; +#ifdef NC_DEBUG_XML + fprintf(stderr, "EndElement %s %s %d\n", name, p->ns, p->state); +#endif + if (p->state == inEnt) { + p->state = p->pState; + return; + } + if (p->state == unknown) { + if (p->unDepth) + p->unDepth--; + else + p->state = p->pState; + return; + } + if (p->state == inRoot) { + p->state = noRoot; + free(p->ns); + p->ns = NULL; + return; + } + if (p->state == inDir) { + p->depth--; + if (!p->depth) + p->state = inRoot; + p->which->chDir(".."); + } +} +#endif /* HAVE_LIBXML2 */ + +int NConfig::fromXML(const char *filename, int force) +{ + if (fd < 0) + return NC_ERR_NFILE; + if (omode != NC_O_RW) + return NC_ERR_PERM; +#ifndef HAVE_LIBXML2 + return NC_ERR_NOSUPPORT; +#else + struct ncParseState state = { noRoot, noRoot, NULL, 0, 0, force, this }; + sh.getEntity = ncXmlGetEntity; + sh.startElement = ncXmlStartElement; + sh.endElement = ncXmlEndElement; + + lockFile(NC_L_RW); + cdir = rdir; + int ret = ncXmlSAXParseFile(&sh, &state, filename); + cdir = rdir; + unLockFile(); + + return ret < 0 ? NC_ERR_NVAL : NC_ERR_OK; +#endif /* HAVE_LIBXML2 */ +} + |
