00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029 #include <ctype.h>
00030 #include <string.h>
00031
00032 #ifdef HAVE_GRP_H
00033 #include <grp.h>
00034 #endif
00035
00036 #ifdef HAVE_PWD_H
00037 #include <pwd.h>
00038 #endif
00039
00040 #include <unistd.h>
00041 #include <stdlib.h>
00042
00043 #ifdef HAVE_SYS_STAT_H
00044 #include <sys/stat.h>
00045 #endif
00046
00047 #include <libxml/xmlreader.h>
00048 #include <libxml/xmlschemas.h>
00049
00050 #include "kdbtools.h"
00051 #include "kdbprivate.h"
00052 #include "kdb.h"
00053
00054
00055 #define KDB_SCHEMA_PATH_KEY "system/sw/kdb/current/schemapath"
00056
00057 #ifdef ELEKTRA_STATIC
00058 #define ksFromXMLfile libelektratools_LTX_ksFromXMLfile
00059 #define ksFromXML libelektratools_LTX_ksFromXML
00060 #endif
00061
00062
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 int consumeKeyNode(KeySet *ks, const char *context, xmlTextReaderPtr reader) {
00093 xmlChar *nodeName=0;
00094 xmlChar *buffer=0;
00095 xmlChar *privateContext=0;
00096 Key *newKey=0;
00097 int appended=0;
00098
00099
00100
00101 nodeName=xmlTextReaderName(reader);
00102 if (!strcmp((char *)nodeName,"key")) {
00103 uint8_t type=KEY_TYPE_STRING;
00104 uint8_t isdir=0;
00105 int end=0;
00106
00107 newKey=keyNew(0);
00108
00109 xmlFree(nodeName); nodeName=0;
00110
00111
00112
00113
00114
00115
00116
00117
00118 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"name");
00119 if (buffer) {
00120
00121 keySetName(newKey,(char *)buffer);
00122 xmlFree(buffer); buffer=0;
00123 } else {
00124
00125
00126 privateContext=xmlTextReaderGetAttribute(reader,
00127 (const xmlChar *)"parent");
00128 buffer=xmlTextReaderGetAttribute(reader,
00129 (const xmlChar *)"basename");
00130
00131 if (context) keySetName(newKey,context);
00132 if (privateContext) keyAddBaseName(newKey, (char *)privateContext);
00133 if (buffer) keyAddBaseName(newKey,(char *)buffer);
00134
00135 xmlFree(privateContext); privateContext=0;
00136 xmlFree(buffer); buffer=0;
00137 }
00138
00139
00140
00141 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"value");
00142 if (buffer) {
00143 keySetRaw(newKey,buffer,strblen((char *)buffer));
00144 xmlFree(buffer); buffer=0;
00145 }
00146
00147
00148 #ifdef HAVE_PWD_H
00149
00150 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"uid");
00151 if (buffer) {
00152 if (isdigit(*buffer))
00153 keySetUID(newKey,atoi((char *)buffer));
00154 else {
00155 struct passwd *pwd;
00156 pwd=getpwnam((char *)buffer);
00157 if (pwd) keySetUID(newKey,pwd->pw_uid);
00158 else fprintf(stderr,"%s: Ignoring invalid user %s.\n",
00159 newKey->key, buffer);
00160 }
00161 xmlFree(buffer); buffer=0;
00162 }
00163 #endif
00164
00165 #ifdef HAVE_GRP_H
00166
00167 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"gid");
00168 if (buffer) {
00169 if (isdigit(*buffer)) {
00170 keySetGID(newKey,atoi((char *)buffer));
00171 } else {
00172 struct group *grp;
00173 grp=getgrnam((char *)buffer);
00174 if (grp) keySetGID(newKey,grp->gr_gid);
00175 else fprintf(stderr,"%s: Ignoring invalid group %s.\n",
00176 newKey->key, buffer);
00177 }
00178 xmlFree(buffer); buffer=0;
00179 }
00180 #endif
00181
00182
00183 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"mode");
00184 if (buffer) keySetAccess(newKey,strtol((char *)buffer,0,0));
00185 xmlFree(buffer); buffer=0;
00186
00187
00188
00189 if (xmlTextReaderIsEmptyElement(reader)) {
00190
00191 if (newKey && !appended) {
00192 ksAppend(ks,newKey);
00193 appended=1;
00194 end=1;
00195 }
00196 }
00197
00198
00199 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"type");
00200 if (buffer) {
00201 if (!strcmp((char *)buffer,"string"))
00202 type=KEY_TYPE_STRING;
00203 else if (!strcmp((char *)buffer,"link"))
00204 type=KEY_TYPE_LINK;
00205 else if (!strcmp((char *)buffer,"directory"))
00206 isdir=1;
00207 else if (!strcmp((char *)buffer,"binary"))
00208 type=KEY_TYPE_BINARY;
00209 else if (!strcmp((char *)buffer,"undefined"))
00210 type=KEY_TYPE_UNDEFINED;
00211 else {
00212 void *converter=0;
00213
00214 type=strtol((char *)buffer,(char **)&converter,10);
00215 if ((void *)buffer==converter)
00216
00217 type=KEY_TYPE_STRING;
00218 }
00219 }
00220 xmlFree(buffer); buffer=0;
00221
00222
00223
00224 buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"isdir");
00225 if (buffer) isdir=! (strcmp((char *)buffer,"0") &&
00226 strcmp((char *)buffer,"false") &&
00227 strcmp((char *)buffer,"no"));
00228
00229 xmlFree(buffer); buffer=0;
00230
00231
00232 if (isdir) {
00233 mode_t mask=umask(0);
00234 umask(mask);
00235 keySetDir(newKey,mask);
00236 }
00237
00238 keySetType(newKey,type);
00239
00240
00241
00242 while (!end) {
00243 xmlFree(nodeName); nodeName=0;
00244 xmlTextReaderRead(reader);
00245 nodeName=xmlTextReaderName(reader);
00246
00247 if (!strcmp((char *)nodeName,"value")) {
00248 if (xmlTextReaderIsEmptyElement(reader) ||
00249 xmlTextReaderNodeType(reader)==15) continue;
00250
00251 xmlTextReaderRead(reader);
00252 buffer=xmlTextReaderValue(reader);
00253
00254 if (buffer) {
00255
00256 if (KEY_TYPE_BINARY <= type && type < KEY_TYPE_STRING) {
00257 char *unencoded=0;
00258 size_t unencodedSize;
00259
00260 unencodedSize=strblen((char *)buffer)/2;
00261 unencoded=malloc(unencodedSize);
00262 unencodedSize=unencode((char *)buffer,unencoded);
00263 if (!unencodedSize) return -1;
00264 keySetRaw(newKey,unencoded,unencodedSize);
00265 free(unencoded);
00266 } else keySetRaw(newKey,buffer,strblen((char *)buffer));
00267 }
00268 } else if (!strcmp((char *)nodeName,"comment")) {
00269 ssize_t commentSize=0;
00270
00271 if (xmlTextReaderIsEmptyElement(reader) ||
00272 xmlTextReaderNodeType(reader)==15) continue;
00273
00274 xmlTextReaderRead(reader);
00275 buffer=xmlTextReaderValue(reader);
00276
00277 if ((commentSize=keyGetCommentSize(newKey)) > 0) {
00278 char *tmpComment=0;
00279 tmpComment=malloc(commentSize+
00280 xmlStrlen(buffer)*sizeof(xmlChar)+1);
00281
00282 if (tmpComment) {
00283 keyGetComment(newKey,tmpComment,commentSize);
00284
00285 strcat(tmpComment,"\n");
00286 strcat(tmpComment,(char *)buffer);
00287
00288 keySetComment(newKey,tmpComment);
00289
00290 free(tmpComment); tmpComment=0;
00291 }
00292 } else keySetComment(newKey,(char *)buffer);
00293 } else if (!strcmp((char *)nodeName,"key")) {
00294
00295
00296 if (newKey && !appended) {
00297 ksAppend(ks,newKey);
00298 appended=1;
00299 }
00300
00301 if (xmlTextReaderNodeType(reader)==15)
00302
00303 end=1;
00304 else {
00305
00306 if (! keyIsDir(newKey)) {
00307
00308 mode_t mask=umask(0);
00309 umask(mask);
00310
00311 keySetDir(newKey,mask);
00312 }
00313
00314 consumeKeyNode(ks,newKey->key,reader);
00315 }
00316 }
00317 xmlFree(buffer); buffer=0;
00318 }
00319
00320
00321 if (privateContext) xmlFree(privateContext);
00322 }
00323
00324 if (nodeName) xmlFree(nodeName),nodeName=0;
00325 return 0;
00326 }
00327
00328
00329
00330
00331 int consumeKeySetNode(KeySet *ks, const char *context, xmlTextReaderPtr reader) {
00332 xmlChar *nodeName=0;
00333 xmlChar *privateContext=0;
00334 xmlChar fullContext[800]="";
00335
00336 nodeName=xmlTextReaderName(reader);
00337 if (!strcmp((char *)nodeName,"keyset")) {
00338 int end=0;
00339
00340 privateContext=xmlTextReaderGetAttribute(reader,(const xmlChar *)"parent");
00341 if (context && privateContext) {
00342 xmlStrPrintf(fullContext,sizeof(fullContext),
00343 (const xmlChar *)"%s/%s", context, privateContext);
00344 }
00345
00346
00347 while (!end) {
00348 xmlFree(nodeName); nodeName=0;
00349 xmlTextReaderRead(reader);
00350 nodeName=xmlTextReaderName(reader);
00351
00352 if (!strcmp((char *)nodeName,"key")) {
00353 if (privateContext) consumeKeyNode(ks,(char *)(*fullContext?fullContext:privateContext),reader);
00354 else consumeKeyNode(ks,context,reader);
00355 } else if (!strcmp((char *)nodeName,"keyset")) {
00356
00357 if (xmlTextReaderNodeType(reader)==15)
00358
00359 end=1;
00360 else if (privateContext)
00361 consumeKeySetNode(ks, (char *)(*fullContext?fullContext:privateContext), reader);
00362 else consumeKeySetNode(ks, context, reader);
00363 }
00364 }
00365 if (privateContext) xmlFree(privateContext),privateContext=0;
00366 }
00367 return 0;
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 int ksFromXMLReader(KeySet *ks,xmlTextReaderPtr reader) {
00380 int ret;
00381 xmlChar *nodeName=0;
00382
00383 ret = xmlTextReaderRead(reader);
00384 while (ret == 1) {
00385
00386 nodeName=xmlTextReaderName(reader);
00387
00388 if (!strcmp((char *)nodeName,"key"))
00389 consumeKeyNode(ks, 0, reader);
00390 else if (!strcmp((char *)nodeName,"keyset"))
00391 consumeKeySetNode(ks, 0, reader);
00392
00393 ret = xmlTextReaderRead(reader);
00394 }
00395 xmlFreeTextReader(reader);
00396 if (ret) fprintf(stderr,"kdb: Failed to parse XML input\n");
00397
00398 return ret;
00399 }
00400
00401
00402
00403 int isValidXML(xmlDocPtr doc,char *schemaPath) {
00404 xmlSchemaPtr wxschemas = NULL;
00405 xmlSchemaValidCtxtPtr ctxt;
00406 xmlSchemaParserCtxtPtr ctxt2=NULL;
00407 int ret=0;
00408
00409 ctxt2 = xmlSchemaNewParserCtxt(schemaPath);
00410
00411
00412 if (ctxt2==NULL) {
00413 xmlFreeDoc(doc);
00414 return 1;
00415 }
00416
00417 xmlSchemaSetParserErrors(ctxt2,
00418 (xmlSchemaValidityErrorFunc) fprintf,
00419 (xmlSchemaValidityWarningFunc) fprintf,
00420 stderr);
00421 wxschemas = xmlSchemaParse(ctxt2);
00422
00423 if (wxschemas==NULL) {
00424 xmlSchemaFreeParserCtxt(ctxt2);
00425 xmlFreeDoc(doc);
00426 return 1;
00427 }
00428
00429
00430 ctxt = xmlSchemaNewValidCtxt(wxschemas);
00431 xmlSchemaSetValidErrors(ctxt,
00432 (xmlSchemaValidityErrorFunc) fprintf,
00433 (xmlSchemaValidityWarningFunc) fprintf,
00434 stderr);
00435
00436 if (ctxt==NULL) {
00437 xmlSchemaFree(wxschemas);
00438 xmlSchemaFreeParserCtxt(ctxt2);
00439 xmlFreeDoc(doc);
00440 return 1;
00441 }
00442
00443 ret = xmlSchemaValidateDoc(ctxt, doc);
00444 xmlSchemaFreeValidCtxt(ctxt);
00445 xmlSchemaFree(wxschemas);
00446 xmlSchemaFreeParserCtxt(ctxt2);
00447
00448 return ret;
00449 }
00450
00451
00452
00462 int ksFromXMLfile(KeySet *ks,const char *filename) {
00463 xmlTextReaderPtr reader;
00464 xmlDocPtr doc;
00465 int ret=0;
00466 char schemaPath[513];
00467
00468 doc = xmlParseFile(filename);
00469 if (doc==NULL) return 1;
00470
00471
00472 schemaPath[0]=0;
00473
00474
00475
00476
00477
00478
00479
00480 if (!ret) {
00481 reader=xmlReaderWalker(doc);
00482 if (reader) ret=ksFromXMLReader(ks,reader);
00483 else {
00484 perror("kdb");
00485 return 1;
00486 }
00487 }
00488 xmlFreeDoc(doc);
00489 return ret;
00490 }
00491
00492
00493
00494
00495
00496
00502 int ksFromXML(KeySet *ks,int fd) {
00503
00504 char filename[]="/var/tmp/kdbeditXXXXXX";
00505 FILE *xmlfile=0;
00506 xmlfile=fdopen(mkstemp(filename),"rw+");
00507 while (! feof(xmlfile)) {
00508 char buffer[1000];
00509 ssize_t readed, writen;
00510
00511 readed=read(fd,buffer,sizeof(buffer));
00512 if (readed<0) {
00513 perror("kdb");
00514 fclose(xmlfile);
00515 remove(filename);
00516 return 1;
00517 }
00518
00519 writen=write(fileno(xmlfile),buffer,readed);
00520 if (writen<0) {
00521 perror("kdb");
00522 fclose(xmlfile);
00523 remove(filename);
00524 return 1;
00525 }
00526 }
00527 fclose(xmlfile);
00528 return ksFromXMLfile(ks,filename);
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 }
00546
00547
00548
00549
00550
00551
00552