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