/* Use to walk the XML produced by bolixod */ #include #include #include #include #include #include #include #include #include "bolixo.h" void _F_boxml::user ( const char *owner, int ownerid, int documentid, const char *id, const char *name, const char *passw, bool &end, bool &skip) { } void _F_boxml::document( const char *owner, const char *name, const char *descr, bool &end, bool &skip, int &documentid, int &ownerid) { } void _F_boxml::node( int documentid, const char *name, const char *descr, const char *image, const char *modif, const char *uuid, const char *owner, const char *type, bool &end, bool &skip) { } void _F_boxml::oldnode( int documentid, const char *name, const char *descr, const char *image, const char *modif, const char *uuid, const char *owner, const char *type, bool &end, bool &skip) { } void _F_boxml::delnode( int documentid, const char *uuid, bool &end, bool &skip) { } void _F_boxml::relation( int documentid, int docownerid, const char *owner, const char *uuid1, const char *uuid2, const char *relate, const char *descr, const char *modif, const char *type, const char *altname, char orderpol, unsigned int orderkey, bool &end, bool &skip) { } void _F_boxml::oldrelation( int documentid, int docownerid, const char *owner, const char *uuid1, const char *uuid2, const char *relate, const char *descr, const char *modif, const char *type, bool &end, bool &skip) { } void _F_boxml::delrelation( int documentid, const char *uuid1, const char *uuid2, const char *relate, bool &end, bool &skip) { } static unsigned char *boxml_getcontent( xmlNodePtr cur, const unsigned char *key) { unsigned char *ret = NULL; xmlNodePtr sub = cur->xmlChildrenNode; while (sub != NULL){ if (xmlStrcmp(sub->name,key)==0){ ret = xmlNodeGetContent(sub); break; } sub = sub->next; } return ret; } // Class to avoid casting and freeing over and over // Should really be used with xmlGetProp() only class XMLDATA{ protected: unsigned char *data; public: operator const char *(){ return data == NULL ? "" : (const char*)data; } ~XMLDATA(){ free (data); } operator int(){ return data == NULL ? -1 : atoi((const char*)data); } operator unsigned int(){ return data == NULL ? 0 : atoi((const char*)data); } operator char(){ return data == NULL ? ' ' : *data; } }; class XMLPROP: public XMLDATA{ public: XMLPROP(xmlNodePtr cur, const unsigned char key[]){ data = xmlGetProp(cur,key); } }; class XMLCONTENT: public XMLDATA{ public: XMLCONTENT(xmlNodePtr cur){ data = xmlNodeGetContent(cur); } XMLCONTENT(xmlNodePtr cur, const unsigned char key[]){ data = boxml_getcontent(cur,key); } }; static void boxml_walk ( _F_boxml &c, xmlNodePtr cur, int documentid, const char *owner, int ownerid) { bool end = false; bool skipuser = false; bool skipnode = false; bool skiprelation = false; while (!end && cur != NULL){ if (xmlStrcmp(cur->name,K_BOLIXO)==0){ xmlNodePtr sub = cur->xmlChildrenNode; boxml_walk (c,sub,documentid,owner,ownerid); }else if (xmlStrcmp(cur->name,K_DOCUMENT)==0){ XMLPROP docowner (cur,K_OWNER); XMLPROP name (cur,K_NAME); XMLCONTENT descr (cur,K_DESCRIPTION); bool skip = false; int docid = -1; int docownerid=-1; c.document (docowner,name,descr,end,skip,docid,docownerid); if (!skip && !end){ xmlNodePtr sub = cur->xmlChildrenNode; boxml_walk (c,sub,docid,docowner,docownerid); } }else if (xmlStrcmp(cur->name,K_USER)==0){ XMLPROP id (cur,K_ID); XMLPROP name (cur,K_NAME); XMLPROP passw (cur,K_PASSW); c.user (owner,ownerid,documentid,id,name,passw,end,skipuser); }else if (xmlStrcmp(cur->name,K_NODE)==0){ XMLPROP image (cur,K_IMAGE); XMLPROP name (cur,K_NAME); XMLPROP modif (cur,K_MODIF); XMLPROP uuid (cur,K_UUID); XMLPROP owner (cur,K_OWNER); XMLPROP type (cur,K_TYPE); XMLCONTENT descr (cur); c.node (documentid,name,descr,image,modif,uuid,owner,type,end,skipnode); }else if (xmlStrcmp(cur->name,K_OLDNODE)==0){ XMLPROP image (cur,K_IMAGE); XMLPROP name (cur,K_NAME); XMLPROP modif (cur,K_MODIF); XMLPROP uuid (cur,K_UUID); XMLPROP owner (cur,K_OWNER); XMLPROP type (cur,K_TYPE); XMLCONTENT descr (cur); c.oldnode (documentid,name,descr,image,modif,uuid,owner,type,end,skipnode); }else if (xmlStrcmp(cur->name,K_DELNODE)==0){ XMLPROP uuid (cur,K_UUID); c.delnode (documentid,uuid,end,skipnode); }else if (xmlStrcmp(cur->name,K_RELATION)==0){ XMLPROP uuid1 (cur,K_UUID1); XMLPROP uuid2 (cur,K_UUID2); XMLPROP relowner (cur,K_OWNER); XMLPROP relate (cur,K_RELATE); XMLPROP modif (cur,K_MODIF); XMLPROP type (cur,K_TYPE); XMLPROP altname (cur,K_ALTNAME); XMLPROP _orderpol (cur,K_ORDERPOL); char orderpol = _orderpol; if (!isalpha(orderpol)) orderpol = 'T'; XMLPROP orderkey (cur,K_ORDERKEY); XMLCONTENT descr (cur); c.relation (documentid,ownerid,relowner,uuid1,uuid2,relate,descr,modif,type,altname,orderpol,orderkey,end,skiprelation); }else if (xmlStrcmp(cur->name,K_OLDRELATION)==0){ XMLPROP uuid1 (cur,K_UUID1); XMLPROP uuid2 (cur,K_UUID2); XMLPROP relowner (cur,K_OWNER); XMLPROP relate (cur,K_RELATE); XMLPROP modif (cur,K_MODIF); XMLPROP type (cur,K_TYPE); XMLCONTENT descr (cur); c.oldrelation (documentid,ownerid,relowner,uuid1,uuid2,relate,descr,modif,type,end,skiprelation); }else if (xmlStrcmp(cur->name,K_DELRELATION)==0){ XMLPROP uuid1 (cur,K_UUID1); XMLPROP uuid2 (cur,K_UUID2); XMLPROP relate (cur,K_RELATE); c.delrelation (documentid,uuid1,uuid2,relate,end,skiprelation); } cur = cur->next; } } static int boxml_gen(_F_boxml &c, xmlDocPtr doc, int documentid) { int ret = -1; if (doc != NULL){ ret = 0; xmlNodePtr cur = xmlDocGetRootElement(doc); boxml_walk (c,cur,documentid,"root",0); xmlFreeDoc(doc); } return ret; } int boxml (_F_boxml &c, const char *fname) { int ret = -1; c.priv = NULL; xmlDocPtr doc = xmlParseFile(fname); return boxml_gen (c,doc,0); } int boxml (_F_boxml &c, BOXML_READER &reader, int documentid) { int ret = -1; c.priv = NULL; xmlDocPtr doc = reader.getxmldoc (); return boxml_gen (c,doc,documentid); } int boxml (_F_boxml &c, BOXML_READER &reader) { return boxml (c,reader,0); } PUBLIC BOXML_READER::BOXML_READER() { ctxt = NULL; } PUBLIC void BOXML_READER::append (const char *line) { int lenline = strlen(line); if (ctxt == NULL){ ctxt = xmlCreatePushParserCtxt(NULL, NULL, line,lenline, "pipe"); }else{ xmlParseChunk(ctxt, line, lenline, 0); } xmlParseChunk (ctxt,"\n",1,0); } PUBLIC xmlDocPtr BOXML_READER::getxmldoc() { return ctxt->myDoc; } /* Forget everything, ready to parse a new xml document */ PUBLIC void BOXML_READER::reset() { if (ctxt != NULL){ xmlFreeParserCtxt(ctxt); ctxt = NULL; } } PUBLIC bool BOXML_READER::reading() const { return ctxt != NULL; } PUBLIC BOXML_READER::~BOXML_READER() { reset(); } static void boxml_app ( const char *&start, const char *&s, const char *enc, SSTRING &d) { d.append (start,(int)(s-start)); d.append (enc); start = ++s; } static void boxml_enc (const char *s, SSTRING &d) { const char *start = s; while (*s != '\0'){ if (*s == '<'){ boxml_app (start,s,"<",d); }else if (*s == '>'){ boxml_app (start,s,">",d); }else if (*s == '"'){ boxml_app (start,s,""",d); }else if (*s == '&'){ boxml_app (start,s,"&",d); }else{ s++; } } d.append (start,(int)(s-start)); } /* Encode a string in XML format, escaping few things. Quotes are placed around the value. (escaping not done yet) */ PUBLIC const char *BOXMLENC::enc (const char *s) { if (s == NULL) s = ""; SSTRING *tmp = new SSTRING ("\""); boxml_enc (s,*tmp); tmp->append ('"'); tb.add (tmp); return tmp->get(); } PUBLIC const char *BOXMLENC::enc (const SSTRING &s) { return enc(s.get()); } PUBLIC const char *BOXMLENC::enc (int val) { char tmp[20]; snprintf (tmp,sizeof(tmp)-1,"%d",val); return enc(tmp); } /* Encode a string in XML format, escaping few things. No quotes around. */ PUBLIC const char *BOXMLENC::encnq (const char *s) { if (s == NULL) s = ""; SSTRING *tmp = new SSTRING; boxml_enc (s,*tmp); tb.add (tmp); return tmp->get(); } PUBLIC const char *BOXMLENC::encnq (const SSTRING &s) { return encnq(s.get()); } /* Produce a unique identifier for nodes */ int bo_makeuuid (char buf[30]) { int ret = -1; buf[0] = '\0'; int fd = open ("/dev/urandom",O_RDONLY); if (fd != -1){ unsigned char data[8]; if (read(fd,data,8)==8){ time_t ti = time(NULL); snprintf (buf,30-1,"%02x%02x%02x%02x%02x%02x%02x%02x%lu" ,data[0],data[1],data[2],data[3] ,data[4],data[5],data[6],data[7] ,ti); ret = 0; } close (fd); } return ret; } int bo_makeuuid (SSTRING &uuid) { char buf[30]; int ret = bo_makeuuid(buf); uuid = buf; return ret; } void bo_getnow(SSTRING &now) { time_t t = time(NULL); now.setfromf ("%lu",t); }