00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "xmlprofile.h"
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include "jutils.h"
00028
00029 #define XML_ELEMENT_NONE 0
00030 #define XML_ELEMENT_START 1
00031 #define XML_ELEMENT_VALUE 2
00032 #define XML_ELEMENT_END 3
00033 #define XML_ELEMENT_UNIQUE 4
00034
00035 #define SKIP_BLANKS(__p) \
00036 while((*__p==' ' || *__p=='\t' || *__p=='\r' || *__p == '\n') && *__p!=0) __p++;
00037
00038 #define ADVANCE_ELEMENT(__p) \
00039 while(*__p!='>' && *__p!=' ' && *__p!='\t' && *__p!='\r' && *__p != '\n' && *__p!=0) __p++;
00040
00041 #define ADVANCE_TO_ATTR_VALUE(__p) \
00042 while(*__p!='=' && *__p!=' ' && *__p!='\t' && *__p!='\r' && *__p != '\n' && *__p!=0) __p++;\
00043 SKIP_BLANKS(__p);
00044
00045 XmlProfile::XmlProfile(char *category,char *repository) {
00046 int fd;
00047
00048 rootElements = new Linklist;
00049
00050 xmlFile=(char *)malloc(strlen(category)+strlen(repository)+6);
00051 sprintf(xmlFile,"%s/%s.xml",repository,category);
00052 XmlErr err=XmlParseFile(xmlFile);
00053 }
00054
00055 XmlProfile::~XmlProfile() {
00056 if(xmlFile) free(xmlFile);
00057 for(int i=1;i<=rootElements->len();i++) {
00058 Entry *entry = rootElements->pick(i);
00059 if(entry) {
00060 XmlTag *element = (XmlTag *)entry->get_value();
00061 if(element) delete element;
00062 }
00063 }
00064 delete rootElements;
00065 }
00066
00067 XmlErr XmlProfile::XmlStartHandler(char *element,
00068 char **attr_names, char **attr_values)
00069 {
00070 XmlTag *newTag = new XmlTag(element,cTag);
00071 XmlErr err;
00072 func("new tag found %s\n",element);
00073 if(cTag) {
00074 err = cTag->addChild(newTag);
00075 if(err!=XML_NOERR)
00076 error("Can't add new child %s for element %s ",newTag->name(),cTag->name());
00077 else
00078 func("Added new child %s for element %s ",newTag->name(),cTag->name());
00079 }
00080 else {
00081 err = addRootElement(newTag);
00082 if(err!=XML_NOERR)
00083 error("Can't add new root element %s",newTag->name());
00084 else
00085 func("Added new root element %s",newTag->name());
00086 }
00087 cTag = newTag;
00088 unsigned int offset = 0;
00089 if(attr_names && attr_values) {
00090 while(attr_names[offset]!=NULL) {
00091 err=newTag->addAttribute(attr_names[offset],attr_values[offset]);
00092 if(err==XML_NOERR) {
00093 func("Added new attr %s => %s for element %s",
00094 attr_names[offset],attr_values[offset],newTag->name());
00095 } else {
00096 error("Can't add new attr %s => %s for element %s",
00097 attr_names[offset],attr_values[offset],newTag->name());
00098 }
00099 offset++;
00100 }
00101 }
00102 return XML_NOERR;
00103 }
00104
00105 XmlErr XmlProfile::XmlEndHandler(char *element)
00106 {
00107 if(cTag) {
00108 XmlTag *parent = cTag->parent();
00109 cTag = parent;
00110 return XML_NOERR;
00111 }
00112 return -1;
00113 }
00114
00115 XmlErr XmlProfile::XmlValueHandler(char *text)
00116 {
00117 char *val = (char *)text;
00118 if(val) {
00119 while((*val == ' ' || *val == '\t' ||
00120 *val == '\r' || *val == '\n') && *val != 0) val++;
00121 char *p = val+strlen(val)-1;
00122 while((*p == ' ' || *p == '\t' ||
00123 *p == '\r' || *p == '\n') && p != val)
00124 {
00125 *p=0;
00126 p--;
00127 }
00128 if(strlen(val)>0) {
00129 if(cTag) cTag->value((char *)val);
00130 else error("cTag == NULL while handling a value!!");
00131 }
00132 return XML_NOERR;
00133 }
00134 return -1;
00135 }
00136
00137 XmlErr XmlProfile::XmlParseFile(char *path) {
00138 struct stat fileStat;
00139 if(!path) return XML_BADARGS;
00140 stat(path,&fileStat);
00141 FILE *inFile=NULL;
00142 XmlErr err;
00143 cTag=NULL;
00144 if(fileStat.st_size>0) {
00145 char *buffer=(char *)malloc(fileStat.st_size+1);
00146 inFile=fopen(path,"r");
00147 fread(buffer,1,fileStat.st_size,inFile);
00148 buffer[fileStat.st_size]=0;
00149
00150 err=XmlParseBuffer(buffer);
00151 free(buffer);
00152 }
00153 }
00154
00155 XmlErr XmlProfile::XmlParseBuffer(char *buffer) {
00156 XmlErr err;
00157 int state=XML_ELEMENT_NONE;
00158 char *p=buffer;
00159
00160 while(*p!=0) {
00161 SKIP_BLANKS(p);
00162 char *mark;
00163 if(*p=='<') {
00164 p++;
00165 if(*p=='/') {
00166 p++;
00167 SKIP_BLANKS(p);
00168 mark=p;
00169 while(*p!='>' && *p!=0) p++;
00170 if(*p=='>') {
00171 char *end=(char *)malloc(p-mark+1);
00172 strncpy(end,mark,p-mark);
00173 end[p-mark]=0;
00174 p++;
00175 state=XML_ELEMENT_END;
00176 err=XmlEndHandler(end);
00177 if(end) free(end);
00178 if(err!=XML_NOERR) return(err);
00179 }
00180 }
00181 else {
00182 char *start = NULL;
00183 char **attrs = NULL;
00184 char **values = NULL;
00185 unsigned int nAttrs = 0;
00186 state=XML_ELEMENT_START;
00187 SKIP_BLANKS(p);
00188 mark=p;
00189 ADVANCE_ELEMENT(p);
00190 start = (char *)malloc(p-mark+1);
00191 strncpy(start,mark,p-mark);
00192 start[p-mark]=0;
00193 SKIP_BLANKS(p);
00194 while(*p!='>' && *p!=0) {
00195 if(*p=='/' && *(p+1)=='>') {
00196 state=XML_ELEMENT_UNIQUE;
00197 p++;
00198 }
00199 else {
00200 mark=p;
00201 ADVANCE_TO_ATTR_VALUE(p);
00202 if(*p=='=') {
00203 char *tmpAttr=(char *)malloc(p-mark+1);
00204 strncpy(tmpAttr,mark,p-mark);
00205 tmpAttr[p-mark]=0;
00206 p++;
00207 SKIP_BLANKS(p);
00208 if(*p == '"' || *p == '\'') {
00209 int quote = *p;
00210 p++;
00211 mark=p;
00212 while(*p!=quote && *p!=0) p++;
00213 if(*p==quote) {
00214 char *tmpVal = (char *)malloc(p-mark+1);
00215 strncpy(tmpVal,mark,p-mark);
00216 tmpVal[p-mark]=0;
00217
00218 nAttrs++;
00219 attrs=(char **)realloc(attrs,sizeof(char *)*nAttrs+1);
00220 attrs[nAttrs-1]=tmpAttr;
00221 attrs[nAttrs]=NULL;
00222 values=(char **)realloc(values,sizeof(char *)*nAttrs+1);
00223 values[nAttrs-1]=tmpVal;
00224 values[nAttrs]=NULL;
00225 p++;
00226 SKIP_BLANKS(p);
00227 }
00228 else {
00229 free(tmpAttr);
00230 }
00231 }
00232 else {
00233 free(tmpAttr);
00234 }
00235 }
00236 }
00237 }
00238 err = XmlStartHandler(start,attrs,values);
00239 #define XML_FREE_ATTRIBUTES \
00240 if(nAttrs>0) {\
00241 for(int i=0;i<nAttrs;i++) {\
00242 if(attrs[i]) free(attrs[i]);\
00243 if(values[i]) free(values[i]);\
00244 }\
00245 free(attrs);\
00246 attrs=NULL;\
00247 free(values);\
00248 values=NULL;\
00249 nAttrs=0;\
00250 }\
00251 if(start) free(start);
00252 if(err!=XML_NOERR) {
00253 XML_FREE_ATTRIBUTES
00254 return err;
00255 }
00256 if(state==XML_ELEMENT_UNIQUE) {
00257 err = XmlEndHandler(start);
00258 if(err!=XML_NOERR) {
00259 XML_FREE_ATTRIBUTES
00260 return err;
00261 }
00262 }
00263 XML_FREE_ATTRIBUTES
00264 p++;
00265 }
00266 }
00267 else if(state == XML_ELEMENT_START) {
00268 state=XML_ELEMENT_VALUE;
00269 mark=p;
00270 while(*p != '<' && *p != 0) p++;
00271 if(*p == '<') {
00272 char *value = (char *)malloc(p-mark);
00273 strncpy(value,mark,p-mark);
00274 value[p-mark]=0;
00275 err=XmlValueHandler(value);
00276 if(value) free(value);
00277 if(err!=XML_NOERR) return(err);
00278
00279 }
00280 }
00281 else {
00282
00283 p++;
00284 }
00285 }
00286 return XML_NOERR;
00287 }
00288
00289 XmlErr XmlProfile::addRootElement(XmlTag *element) {
00290 if(!element) return XML_BADARGS;
00291 Entry *newEntry = new Entry((void *)element);
00292 if(newEntry) rootElements->append(newEntry);
00293 return XML_NOERR;
00294 }
00295
00296 XmlTag *XmlProfile::getRootElement(char *name) {
00297 for(int i=1;i<rootElements->len();i++) {
00298 XmlTag *element = getRootElement(i);
00299 if(element && strcmp(element->name(),name) == 0)
00300 return(element);
00301 }
00302 return NULL;
00303 }
00304
00305 XmlTag *XmlProfile::getRootElement(int index) {
00306 Entry *entry = rootElements->pick(index);
00307 if(entry) {
00308 XmlTag *element = (XmlTag *)entry->get_value();
00309 if(element) return(element);
00310 }
00311 return NULL;
00312 }
00313
00314
00315
00316 XmlTag *XmlProfile::getElement(char *path) {
00317 char *tagName,*tkContext;
00318 XmlTag *tag = NULL;
00319 if(!path) return NULL;
00320 if(*path == '/') path++;
00321 char *lbuf = strdup(path);
00322 char *rootTagName = strtok_r(lbuf,"/",&tkContext);
00323 if(rootTagName) {
00324 tag=getRootElement(rootTagName);
00325 for (tagName = strtok_r(lbuf,"/",&tkContext);
00326 tagName; tagName = strtok_r(NULL,"/",&tkContext))
00327 {
00328 tag=tag->getChild(tagName);
00329 if(!tag) {
00330 free(lbuf);
00331 return NULL;
00332 }
00333 }
00334 }
00335 else {
00336 tag=getRootElement(path);
00337 }
00338 free(lbuf);
00339 return tag;
00340 }
00341
00342 char *XmlProfile::dumpXml() {
00343 char *dump = (char *)malloc(1);
00344 *dump=0;
00345 for (int i=1;i<=rootElements->len();i++) {
00346 Entry *rEntry = rootElements->pick(i);
00347 XmlTag *rTag = (XmlTag *)rEntry->get_value();
00348 if(rTag) {
00349 char *branch = dumpBranch(rTag,0);
00350 if(branch) {
00351 dump=(char *)realloc(dump,strlen(dump)+strlen(branch)+1);
00352 strcat(dump,branch);
00353 free(branch);
00354 }
00355 }
00356 }
00357 return(dump);
00358 }
00359
00360 char *XmlProfile::dumpBranch(XmlTag *rTag,unsigned int depth) {
00361 int i,n;
00362 char *out = NULL;
00363 char *startTag = (char *)malloc(depth+strlen(rTag->name()+5));
00364 char *endTag = (char *)malloc(depth+strlen(rTag->name()+5));
00365 char *value = NULL;;
00366 char *childDump = (char *)malloc(1);
00367 *childDump=0;
00368 *startTag=0;
00369 *endTag=0;
00370 char *vTemp = rTag->value();
00371 if(vTemp) {
00372 value = (char *)malloc(depth+strlen(vTemp)+2);
00373
00374
00375 strcat(value,vTemp);
00376 strcat(value," ");
00377
00378 free(vTemp);
00379 }
00380
00381 for(n=0;n<depth;n++) strcat(startTag,"\t");
00382 strcat(startTag,"<");
00383 strcat(startTag,rTag->name());
00384 if(rTag->numAttributes()>0) {
00385 for(i=1;i<=rTag->attributes->len();i++) {
00386 XmlTagAttribute *attr = rTag->getAttribute(i);
00387 if(attr) {
00388 startTag = (char *)realloc(startTag,strlen(startTag)+
00389 strlen(attr->name)+strlen(attr->value)+6);
00390 strcat(startTag," ");
00391 strcat(startTag,attr->name);
00392 strcat(startTag,"=\"");
00393 strcat(startTag,attr->value);
00394
00395 strcat(startTag,"\" ");
00396 }
00397 }
00398 }
00399 if(value||rTag->numChildren()) {
00400 if(rTag->numChildren() > 0) {
00401 strcat(startTag,">\n");
00402 for(n=0;n<depth;n++) strcat(endTag,"\t");
00403 for(i=1;i<=rTag->numChildren();i++) {
00404 XmlTag *child = rTag->getChild(i);
00405 if(child) {
00406 char *childBuff = dumpBranch(child,depth+1);
00407 childDump = (char *)realloc(childDump,strlen(childDump)+strlen(childBuff)+2);
00408 strcat(childDump,childBuff);
00409
00410 free(childBuff);
00411 }
00412 }
00413 }
00414 else {
00415 strcat(startTag,"> ");
00416 }
00417 strcat(endTag,"</");
00418 strcat(endTag,rTag->name());
00419 strcat(endTag,">\n");
00420 out = (char *)malloc(strlen(startTag)+strlen(endTag)+
00421 (value?strlen(value)+1:0)+strlen(childDump)+1);
00422 strcpy(out,startTag);
00423 if(value) {
00424
00425 if(rTag->numChildren()) {
00426 for(n=0;n<=depth;n++) strcat(out,"\t");
00427 strcat(out,value);
00428 strcat(out,"\n");
00429 }
00430 else {
00431 strcat(out,value);
00432 }
00433 }
00434 strcat(out,childDump);
00435 strcat(out,endTag);
00436 if(value) free(value);
00437 }
00438 else {
00439 strcat(startTag,"/>\n");
00440 out=strdup(startTag);
00441 }
00442 free(startTag);
00443 free(endTag);
00444 free(childDump);
00445 return out;
00446 }
00447
00448 XmlErr XmlProfile::update() {
00449 struct stat fileStat;
00450 stat(xmlFile,&fileStat);
00451 FILE *saveFile=NULL;
00452 if(fileStat.st_size>0) {
00453 saveFile=fopen(xmlFile,"r");
00454 if(!saveFile) {
00455 error("Can't open %s for reading !!",xmlFile);
00456 return XML_UPDATE_ERR;
00457 }
00458 char *backup = (char *)malloc(fileStat.st_size+1);
00459 fread(backup,1,fileStat.st_size,saveFile);
00460 backup[fileStat.st_size]=0;
00461 fclose(saveFile);
00462 char *backupPath = (char *)malloc(strlen(xmlFile+5));
00463 sprintf(backupPath,"%s.bck",xmlFile);
00464 FILE *backupFile=fopen(backupPath,"w+");
00465 if(backupFile) {
00466 fwrite(backup,1,fileStat.st_size,backupFile);
00467 fclose(backupFile);
00468 }
00469 else {
00470 error("Can't open backup file (%s) for writing! ",backupPath);
00471 if(!saveFile) return XML_UPDATE_ERR;
00472 }
00473 free(backupPath);
00474 free(backup);
00475 }
00476
00477 char *dump = dumpXml();
00478 if(dump) {
00479 saveFile=fopen(xmlFile,"w+");
00480 if(saveFile) {
00481 fwrite(dump,1,strlen(dump),saveFile);
00482 free(dump);
00483 fclose(saveFile);
00484 }
00485 else {
00486 error("Can't open output file %s",xmlFile);
00487 if(!saveFile) return XML_UPDATE_ERR;
00488 }
00489 }
00490 }
00491
00492
00493
00494
00495 XmlTag::XmlTag(const char *name,XmlTag *parentEntry) {
00496 _parent = parentEntry;
00497 _name = strdup(name);
00498 _value=NULL;
00499 children = new Linklist();
00500 attributes = new Linklist();
00501 if(_parent) {
00502 char *pPath = _parent->path();
00503 if(pPath) {
00504 unsigned int pathLen = strlen(pPath)+1+strlen(_parent->name())+1;
00505 _path = (char *)malloc(pathLen);
00506 memset(_path,0,pathLen);
00507 sprintf(_path,"%s/%s",pPath,_parent->name());
00508 }
00509 else {
00510 _path=strdup(_parent->name());
00511 }
00512 }
00513 else {
00514 _path = NULL;
00515 }
00516 }
00517
00518 XmlTag::XmlTag(const char *name,char *val,XmlTag *parentEntry) {
00519 XmlTag(name,parentEntry);
00520 _value = strdup(val);
00521 }
00522
00523 XmlTag::~XmlTag() {
00524 int i;
00525 Entry *entry;
00526 if(_value) free(_value);
00527 if(_name) free(_name);
00528 if(_path) free(_path);
00529 for (i=1;i<= children->len();i++) {
00530 entry = children->pick(i);
00531 if(entry) {
00532 XmlTag *tag = (XmlTag *)entry->get_value();
00533 if(tag)
00534 delete tag;
00535 }
00536 }
00537 delete children;
00538 for (i=1;i<=attributes->len();i++) {
00539 entry = attributes->pick(i);
00540 if(entry) {
00541 XmlTagAttribute *attr = (XmlTagAttribute *)entry->get_value();
00542 if(attr) {
00543 if(attr->name) free(attr->name);
00544 if(attr->value) free(attr->value);
00545 free(attr);
00546 }
00547 }
00548 }
00549 delete attributes;
00550 }
00551
00552 char *XmlTag::path() {
00553 return _path;
00554 }
00555
00556 char *XmlTag::name() {
00557 return _name;
00558 }
00559
00560 char *XmlTag::value() {
00561 return _value;
00562 }
00563
00564 XmlTag *XmlTag::parent() {
00565 return _parent;
00566 }
00567
00568 XmlErr XmlTag::value(char *val) {
00569 unsigned int valLen=0;
00570 if(!val) return XML_BADARGS;
00571 _value=(char *)realloc(_value,strlen(val)+1);
00572 strcpy(_value,val);
00573 return XML_NOERR;
00574 }
00575
00576 XmlErr XmlTag::addChild(XmlTag *child) {
00577 if(!child) return XML_BADARGS;
00578 Entry *newEntry = new Entry((void *)child);
00579 children->append(newEntry);
00580 return XML_NOERR;
00581 }
00582
00583 XmlErr XmlTag::numChildren() {
00584 return children->len();
00585 }
00586
00587 XmlTag *XmlTag::getChild(int index) {
00588 Entry *entry = children->pick(index);
00589 if(entry) return (XmlTag *)entry->get_value();
00590 return NULL;
00591 }
00592
00593 XmlTag *XmlTag::getChild(char *name) {
00594 for(int i=1;i<=children->len();i++) {
00595 XmlTag *child=getChild(i);
00596 if(strcmp(child->name(),name)==0)
00597 return child;
00598 }
00599 return NULL;
00600 }
00601
00602 XmlErr XmlTag::addAttribute(char *attrName, char *attrValue) {
00603 if(!attrName||!attrValue) return XML_BADARGS;
00604 XmlTagAttribute *newAttr = (XmlTagAttribute *)malloc(sizeof(XmlTagAttribute));
00605 newAttr->name = strdup(attrName);
00606 newAttr->value = strdup(attrValue);
00607 Entry *newEntry = new Entry((void *)newAttr);
00608 attributes->append(newEntry);
00609 return XML_NOERR;
00610 }
00611
00612 XmlTagAttribute *XmlTag::getAttribute(int index) {
00613 if(index > attributes->len()) return NULL;
00614 Entry *entry = attributes->pick(index);
00615 if(entry) {
00616 return (XmlTagAttribute *)entry->get_value();
00617 }
00618 return NULL;
00619 }
00620
00621 XmlTagAttribute *XmlTag::getAttribute(char *name) {
00622 for(int i=1;i<=attributes->len();i++) {
00623 XmlTagAttribute *attr = getAttribute(i);
00624 if(attr && strcmp(attr->name,name) == 0)
00625 return attr;
00626 }
00627 return NULL;
00628 }
00629
00630 int XmlTag::numAttributes() {
00631 return attributes->len();
00632 }
00633