1 #include <lib/base/nconfig.h>
13 #include <libxml/tree.h>
14 #include <libxml/parser.h>
15 #include <libxml/parserInternals.h>
18 #endif /* HAVE_LIBXML2 */
20 #define DE(x) ((struct nc_de_s *) (data+(x)))
21 #define IDE(x, y) (DE(((unsigned *) (data+(x)->offset))[(y)]))
22 #define XML_DE ((const xmlChar *) "dirEntry")
23 #define XML_NS ((const xmlChar *) "http://hq.alert.sk/projects/nconfig")
24 #define XML_ROOT ((const xmlChar *) "NConfigExport")
26 static char *encodeXml(const char *what)
28 unsigned p = 0, size = 6*strlen(what)+1;
29 char *ret = (char *)malloc(size);
30 for (; *what; what++) {
60 if (*what >= 0x20 || *what == '\n' || *what == '\r' || *what == '\t')
63 p += sprintf(ret+p, "&#%d;", *what);
69 void NConfig::store(nc_de_s *de, FILE *f)
72 for (unsigned i=0; i<de->pages; i++)
73 if ((cc = IDE(de, i))->type) {
74 char *encname = encodeXml(data+cc->name);
75 fprintf(f, "<nc:%s name=\"%s\" type=\"%d\" value=\"", XML_DE, encname, cc->type);
79 fprintf(f, "%u\">\n", cc->pages);
81 fprintf(f, "</nc:%s>\n", XML_DE);
84 fprintf(f, "%s\"/>\n", encname = encodeXml(data+cc->offset));
88 fprintf(f, "%lld\"/>\n", *((signed long long *) (data+cc->offset)));
91 fprintf(f, "%llu\"/>\n", *((unsigned long long *) (data+cc->offset)));
94 fprintf(f, "%La\"/>\n", *((long double *) (data+cc->offset)));
98 const char *raw = data+cc->offset;
99 for (unsigned j=0; j<cc->pages; j++)
100 fprintf(f, "%d%d%d", raw[j] / 100, (raw[j] % 100) / 10, raw[j] % 10);
101 fprintf(f, "\"/>\n");
107 int NConfig::toXML(const char *filename)
112 FILE *f = fopen(filename, "w");
116 fprintf(f, "%s", "<?xml version=\"1.0\"?>\n");
117 fprintf(f, "<nc:%s xmlns:nc=\"%s\" libVersion=\"%s\"", XML_ROOT, XML_NS, VERSION);
119 time_t t = time(NULL);
120 char *tim = ctime(&t);
121 tim[strlen(tim)-1] = 0;
122 fprintf(f, " time=\"%s\"", tim);
123 #endif /* HAVE_TIME_H */
130 fprintf(f, "</nc:%s>\n", XML_ROOT);
136 static xmlSAXHandler sh;
137 enum stateEnum {noRoot = 0, inRoot, inDir, inEnt, unknown};
139 struct ncParseState {
140 stateEnum state, pState;
148 static int ncXmlSAXParseFile(xmlSAXHandlerPtr sax, void *user_data, const char *filename)
151 xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
155 ctxt->userData = user_data;
156 xmlParseDocument(ctxt);
157 ret = ctxt->wellFormed ? 0 : -1;
160 xmlFreeParserCtxt(ctxt);
164 static xmlEntityPtr ncXmlGetEntity(void *user_data, const CHAR *name)
166 return xmlGetPredefinedEntity(name);
169 static void ncXmlStartElement(void *user_data, const CHAR *name, const CHAR **attrs)
171 struct ncParseState *p = (struct ncParseState *)user_data;
173 fprintf(stderr, "New element %s state=%d %s\n", name, p->state, p->ns);
175 if (p->state == unknown) {
179 if (p->state == noRoot) {
181 if (!xmlStrncmp(*attrs, (const xmlChar *) "xmlns:", 6)) {
182 if (!xmlStrcmp(attrs[1], XML_NS)) {
183 p->ns = xmlStrdup((*attrs)+6);
189 char *b = (char *) malloc(xmlStrlen(p->ns)+xmlStrlen(XML_ROOT)+2);
190 sprintf(b, "%s:%s", p->ns, XML_ROOT);
191 if (xmlStrcmp(name, (xmlChar *)b)) {
193 fprintf(stderr, "NewElement, entering unknown %s\n", name);
195 p->pState = p->state;
202 if (p->state == inRoot || p->state == inDir) {
203 const xmlChar *value = NULL, *n = NULL;
206 if (!xmlStrcmp(*attrs, (const xmlChar *)"value"))
208 if (!xmlStrcmp(*attrs, (const xmlChar *)"name"))
210 if (!xmlStrcmp(*attrs, (const xmlChar *)"type"))
211 type = atoi(attrs[1]);
215 fprintf(stderr, "%s %s %s %d %d\n", name, n, value, type, p->state);
217 char *b = (char *) malloc(xmlStrlen(p->ns)+xmlStrlen(XML_DE)+2);
218 sprintf(b, "%s:%s", p->ns, XML_DE);
219 if (xmlStrcmp(name, (xmlChar *)b) || !type || !value || !n) {
221 fprintf(stderr, "NewElement, entering unknown on mismatch\n");
223 p->pState = p->state;
230 p->which->delKey((const char *)n);
234 if (p->which->createDir((const char *)n, strtoul((const char *)value, NULL, 0)) != NC_ERR_OK) {
235 p->pState = p->state;
238 fprintf(stderr, "NewElement, entering unknown on failed mkdir\n");
242 p->which->chDir((const char *)n);
245 p->which->setKey((const char *)n, (const char *)value);
248 p->which->setKey((const char *)n, strtoll((const char *)value, NULL, 0));
251 p->which->setKey((const char *)n, strtoull((const char *)value, NULL, 0));
256 sscanf((const char *)value, "%La", &c);
257 p->which->setKey((const char *)n, c);
262 unsigned size = xmlStrlen(value) / 3;
265 dec = (char *)malloc(size);
266 for (unsigned i=0, k=0; i<size; i++, k += 3)
267 dec[i] = value[k] * 100 + value[k+1] * 10 + value[k+2];
269 p->which->setKey((const char *)n, dec, size);
273 if (type == NC_DIR) {
277 p->pState = p->state;
284 static void ncXmlEndElement(void *user_data, const CHAR *name)
286 struct ncParseState *p = (struct ncParseState *)user_data;
288 fprintf(stderr, "EndElement %s %s %d\n", name, p->ns, p->state);
290 if (p->state == inEnt) {
291 p->state = p->pState;
294 if (p->state == unknown) {
298 p->state = p->pState;
301 if (p->state == inRoot) {
307 if (p->state == inDir) {
311 p->which->chDir("..");
314 #endif /* HAVE_LIBXML2 */
316 int NConfig::fromXML(const char *filename, int force)
320 if (omode != NC_O_RW)
323 return NC_ERR_NOSUPPORT;
325 struct ncParseState state = { noRoot, noRoot, NULL, 0, 0, force, this };
326 sh.getEntity = ncXmlGetEntity;
327 sh.startElement = ncXmlStartElement;
328 sh.endElement = ncXmlEndElement;
332 int ret = ncXmlSAXParseFile(&sh, &state, filename);
336 return ret < 0 ? NC_ERR_NVAL : NC_ERR_OK;
337 #endif /* HAVE_LIBXML2 */