From 98d0faa2eeddfe260bd337c69b00734b7cff2375 Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Sat, 26 Nov 2011 15:54:11 +0000 Subject: added mBot git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@217 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- mBot/src/utils/cXmldoc.cpp | 899 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 899 insertions(+) create mode 100644 mBot/src/utils/cXmldoc.cpp (limited to 'mBot/src/utils/cXmldoc.cpp') diff --git a/mBot/src/utils/cXmldoc.cpp b/mBot/src/utils/cXmldoc.cpp new file mode 100644 index 0000000..808f4a0 --- /dev/null +++ b/mBot/src/utils/cXmldoc.cpp @@ -0,0 +1,899 @@ +/* + +Miranda Scripting Plugin for Miranda-IM +Copyright 2004-2006 Piotr Pawluczuk (www.pawluczuk.info) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "includes.h" +#include "cUtils.h" +#include "cXmlDoc.h" + +/*utils*/ +char* xml_strstrx (const char * str1,const char * str2) +{ + char *cp = (char*)str1; + char *s1, *s2; + long in = 0; + char term = '\"'; + + if (!*str2)return((char*)str1); + + while(*cp) + { + if(in && *cp == term) + { + in = 0; + } + else + { + if(*cp == '\'' || *cp == '"') + { + term = *cp; + in = 1; + } + else + { + s1 = cp; + s2 = (char*) str2; + + while (*s1 && *s2 && !(*s1-*s2)) + { + s1++, s2++; + } + + if (!*s2) + { + return(cp); + } + } + } + cp++; + } + return(NULL); +} + +char* xml_strnws(const char* str) +{ + while(*str) + { + if(*str != ' ' && *str != '\r' && *str != '\n' && *str != '\t') + { + return (char*)str; + } + else + { + str++; + } + } + return (NULL); +} + +char* xml_strrnws(const char* s_str) +{ + const char* str = s_str + strlen(s_str) - 1; + + if(*str != ' ' && *str != '\r' && *str != '\n' && *str != '\t') + { + return (char*)str; + } + + while(str != s_str) + { + if(*str != ' ' && *str != '\r' && *str != '\n' && *str != '\t') + { + break; + } + else + { + str--; + } + } + return (char*)str; +} + +char* xml_strfnalnum(const char* str) +{ + if(!str)return NULL; + + if(!isalpha(*str) && *str!='_')return (char*)str; + + str++; + + while(*str) + { + if(!isalnum(*str) && *str != '_' && *str != '.' && *str != '-' && *str != ':')return (char*)str; + str ++; + } + return (NULL); +} +char* xml_strndup(const char* str,unsigned int n) +{ + char* tmp = NULL; + n = xmlmin(strlen(str),n); + + tmp = (char*)malloc(n + 1); + if(tmp) + { + memcpy(tmp,str,n); + tmp[n] = '\0'; + } + return tmp; +} + +char* xml_parsendup(char* str,unsigned int n,long fast) +{ + long true_length = 0; + char* out = NULL; + char* o = NULL; + const char* x = 0; + char ctmp = str[n]; + str[n] = '\0'; + + if(!fast)//calc the real length + { + for(const char* c=str;*c;) + { + const char* x = c + 1; + + if(*c=='&') + { + for(x=c+1;*x && *x!=';';x++); + if(!(*x) || (x - c) < 3){ + true_length++; + c++; + continue; + } + //&><  + if(*((DWORD*)c) == 'pma&'){ + true_length++; + c+=5; + }else if(*((DWORD*)c) == ';tg&' || *((DWORD*)c) == ';tl&'){ + true_length++; + c+=4; + }else if(strcmp(c," ")==0){ + true_length++; + c+=6; + }else if(*(c+1)=='#' && (x-c)==4){//&#XX; + true_length++; + c+=5; + }else{ + true_length++; + c++; + continue; + } + } + else + { + c++; + true_length++; + } + }//for + true_length++; + }else{ + true_length = strlen(str) + 1; + } + //now do the encoding + o = out = (char*)malloc(true_length); + if(!out){ + str[n] = ctmp; + return NULL; + } + + for(const char* c=str;*c;) + { + if(*c=='&') + { + for(x=c+1;*x && *x!=';';x++); + if(!(*x) || (x - c) < 3){ + *o++ = *c++; + continue; + } + //&><  + if(*((DWORD*)c) == 'pma&'){ + *o++ = '&'; + c+=5; + }else if(*((DWORD*)c) == ';tg&'){ + *o++ = '>'; + c+=4; + }else if(*((DWORD*)c) == ';tl&'){ + *o++ = '<'; + c+=4; + }else if(strcmp(c," ")==0){ + *o++ = ' '; + c+=6; + }else if(*(c+1)=='#' && (x-c)==4){ + *o = (char)(strtoul((c+2),NULL,16) & 0xFF); + if(!*o)*o='?'; + o++; + c+=5; + }else{ + *o++ = *c++; + } + } + else{ + *o++ = *c++; + } + } + *o++ = '\0'; + str[n] = ctmp; + return out; +} + +void xml_put_tabs(FILE* out,long level) +{ + while(level > 0){ + fputc('\t',out); + level--; + } +} + +void xml_write_value(FILE* out,const char* val,long length) +{ + if(!length){ + length = strlen(val); + } + + for(int i=0;i' || *val=='<' || *val=='&'){ + fprintf(out,"&#%.2x;",*val); + }else{ + fputc(*val,out); + } + } +} + +cXmlDoc::cXmlDoc() +{ + memset(&m_root,0,sizeof(m_root)); + m_parse_flags = m_flags = m_level = 0; +} + +cXmlDoc::~cXmlDoc() +{ + m_root.Free(); + m_parse_flags = m_flags = m_level = 0; +} + +long cXmlDoc::ParseProperties(char* start,sXmlNode* node) +{ + char* s = start; + char* ids = NULL; + char* ide = NULL; + char* vs = NULL; + char* ve = NULL; + char et = '\0'; + sXmlProperty prop; + + while((s = xml_strnws(s)) && *s!='\0' && *s!='/') // id = [',"] .... [',"] + { + ids = s; + if(!isalpha(*s)) + { + return (m_parse_flags & cXmlDoc::PARSE_IGNORE_BAD_PROPERTIES)!=0; + } + s++; + while(isalnum(*s) || *s=='_' || *s=='.' || *s=='-' || *s == ':') + { + s++; + } + if(*s == '\0') + { + return (m_parse_flags & cXmlDoc::PARSE_IGNORE_BAD_PROPERTIES)!=0; + } + ide = s; + + s = xml_strnws(s); + if(!s || *s != '=') + { + return (m_parse_flags & cXmlDoc::PARSE_IGNORE_BAD_PROPERTIES)!=0; + } + s++; + + s = xml_strnws(s); + if(!s || (*s!='\'' && *s != '\"')) + { + return (m_parse_flags & cXmlDoc::PARSE_IGNORE_BAD_PROPERTIES)!=0; + } + et = *s; + vs = ++s; + ve = strchr(vs,et); + if(!ve) + { + return (m_parse_flags & cXmlDoc::PARSE_IGNORE_BAD_PROPERTIES)!=0; + } + + prop.name = xml_strndup(ids,ide - ids); + prop.value = xml_parsendup(vs,ve - vs,0);//xml_strndup(vs,ve - vs); + if(!AddProperty(&prop,node))return 0; + memset(&prop,0,sizeof(prop)); + + s = ve + 1; + } + return 1; +} + +long cXmlDoc::AddProperty(sXmlProperty* prop,sXmlNode* node) +{ + sXmlProperty* tmp = (sXmlProperty*)malloc(sizeof(sXmlProperty)); + + if(!tmp){ + return 0; + } + memcpy(tmp,prop,sizeof(sXmlProperty)); + + if(node->f_prop == NULL) + { + node->f_prop = node->l_prop = tmp; + } + else + { + node->l_prop->next = tmp; + node->l_prop = tmp; + } + return 1; +} + +long cXmlDoc::AddBinProperty(sXmlBinProperty* prop,sXmlNode* node) +{ + sXmlBinProperty* tmp = (sXmlBinProperty*)malloc(sizeof(sXmlBinProperty)); + if(!tmp)return 0; + memcpy(tmp,prop,sizeof(sXmlBinProperty)); + + if(node->f_prop == NULL) + { + node->f_prop = node->l_prop = tmp; + } + else + { + node->l_prop->next = tmp; + node->l_prop = tmp; + } + return 1; +} + +long cXmlDoc::AddNewBinProperty(sXmlNode* node,const char* name,void* value) +{ + sXmlBinProperty* tmp = (sXmlBinProperty*)malloc(sizeof(sXmlBinProperty)); + if(!tmp)return 0; + + tmp->name = _strdup(name); + tmp->value = (const char*)value; + + if(node->f_prop == NULL) + { + node->f_prop = node->l_prop = tmp; + } + else + { + node->l_prop->next = tmp; + node->l_prop = tmp; + } + return 1; +} + +long cXmlDoc::SetBinPropertyValue(sXmlNode* node,const char* name,void* value) +{ + sXmlProperty* p = node->f_prop; + while(p) + { + if(p->type() == 1 && strcmp(p->name,name)==0){ + p->value = (const char*)value; + return 1; + } + p = p->next; + } + return 0; +} + +void* cXmlDoc::GetBinPropertyValue(sXmlNode* node,const char* name,long* success) +{ + sXmlProperty* p = node->f_prop; + while(p) + { + if(p->type() == 1 && strcmp(p->name,name)==0){ + *success = TRUE; + return (void*)p->value; + } + p = p->next; + } + *success = FALSE; + return NULL; +} + +long cXmlDoc::JoinParent(sXmlNode* parent,sXmlNode* tmp) +{ + tmp->parent = parent; + parent->num_children ++; + + if(parent->value){ + free((void*)parent->value); + parent->value = NULL; + } + parent->type = NODE_PARENT; + + if(parent->f_child == NULL) + { + parent->f_child = parent->l_child = tmp; + return 1; + } + else + { + parent->l_child->next = tmp; + parent->l_child = tmp; + return 1; + } +} +char* cXmlDoc::ParseNode(char* start,sXmlNode* parent) +{ + char* c = xml_strnws(start); + char* t = NULL; + char* e = NULL; + char* x = NULL; + sXmlNode* node = (sXmlNode*)malloc(sizeof(sXmlNode)); + if(!node)return NULL; + memset(node,0,sizeof(sXmlNode)); + + // comment + // + //< ... > v /> + if(!c || *c != '<') + { + goto Error; + } + c++; + //node type.. + if(*c == '!' && strncmp(c,"!--",3)==0)/*comment*/ + { + c += 3; + e = strstr(c,"-->"); + if(!e) + { + goto Error; + } + else + { + if(m_parse_flags & cXmlDoc::PARSE_COMMENTS) + { + node->type = cXmlDoc::NODE_COMMENT; + node->value = xml_strndup(c,e - c); + JoinParent(parent,node); + } + else + { + free(node); + } + return e + 3; + } + } + else if(*c == '!')/*special command */ + { + c ++; + e = xml_strstrx(c,">"); + if(!e) + { + goto Error; + } + + if(m_parse_flags & cXmlDoc::PARSE_SPECIAL) + { + node->type = cXmlDoc::NODE_SPECIAL; + node->value = xml_strndup(c,e - c); + JoinParent(parent,node); + } + else + { + free(node); + } + return e + 1; + } + else if(*c == '?')/**/ + { + c++; + e = xml_strstrx(c,"?>"); + if(!e) + { + goto Error; + } + if(m_parse_flags & cXmlDoc::PARSE_COMMANDS) + { + node->type = cXmlDoc::NODE_COMMAND; + node->value = xml_strndup(c,e - c); + JoinParent(parent,node); + } + else + { + free(node); + } + return c + 2; + } + else/*normal node*/ + { + if(!isalnum(*c)) + { + goto Error;//improper.. too bad :-) + } + t = xml_strfnalnum(c); + if(!t || (*t != ' ' && *t != '>' && *t != '/' && !isspace(*t))) + { + goto Error; + } + + node->name = xml_strndup(c,t - c); + + e = xml_strstrx(c,">"); + if(!e) + { + goto Error; + } + *e = '\0';//terminate ;-) cool, isn't it? + if(!ParseProperties(t,node)) + { + goto Error; + } + *e = '>';// + x = e + 1; + + if(*(e - 1) == '/') + { + node->type = cXmlDoc::NODE_DATA; + JoinParent(parent,node); + return e + 1;/**/ + } + c = e + 1; +Next: + e = strchr(c,'<'); + if(!e) + { + goto Error;//error? + } + else + { + //end tag, or child + if(*(e + 1) == '/')//end tag.. possibly + { + if(strncmp(e + 2,node->name,strlen(node->name))!=0) + { + goto Error; // too bad :-) + } + c = xml_strnws(e + 2 + strlen(node->name)); + if(!c || *c != '>') + { + goto Error; + } + t = strchr(t,'>'); + if(!t) + { + goto Error; + } + /*append as a child, etc...*/ + + if(node->f_child == NULL)//no children.. then data is interesting ;-) + { + t = xml_strnws(x); + if(!t) + { + goto Error; + } + *e = '\0'; // '<'; + x = xml_strrnws(t); + if(!x) + { + goto Error; + } + x++; + node->type = cXmlDoc::NODE_DATA; + node->value = xml_parsendup(t,x - t,0);//xml_strndup(t,x - t); + } + else + { + node->type = node->type = cXmlDoc::NODE_PARENT; + } + JoinParent(parent,node); + return c + 1; + } + else + { + c = ParseNode(e,node); + if(!c) + { + goto Error; + } + else + { + goto Next; + } + } + } + } +Error: + if(node) + { + node->Free(); + free(node); + } + return NULL; +} + +long cXmlDoc::SaveNode(FILE* f,sXmlNode* node) +{ + while(node) + { + switch(node->type) + { + case cXmlDoc::NODE_COMMAND: + xml_put_tabs(f,m_level); + fprintf(f,"\r\n",node->value); + break; + case cXmlDoc::NODE_SPECIAL: + xml_put_tabs(f,m_level); + fprintf(f,"\r\n",node->value); + break; + case cXmlDoc::NODE_COMMENT: + xml_put_tabs(f,m_level); + fprintf(f,"\r\n",node->value); + break; + case cXmlDoc::NODE_PARENT: + xml_put_tabs(f,m_level); + + if(node->f_prop) + { + fprintf(f,"<%s",node->name); + sXmlProperty* p = node->f_prop; + while(p) + { + fprintf(f," %s=\"%s\"",p->name,p->value); + p = p->next; + } + fprintf(f,">\r\n"); + } + else + { + fprintf(f,"<%s>\r\n",node->name); + } + + m_level ++; + SaveNode(f,node->f_child); + m_level --; + xml_put_tabs(f,m_level); + fprintf(f,"\r\n",node->name); + break; + case cXmlDoc::NODE_DATA: + xml_put_tabs(f,m_level); + + if(node->f_prop) + { + fprintf(f,"<%s",node->name); + sXmlProperty* p = node->f_prop; + while(p) + { + fprintf(f," %s=\"",p->name); + xml_write_value(f,p->value,0); + fputc('\"',f); + p = p->next; + } + } + else + { + fprintf(f,"<%s",node->name); + } + + if(node->value) + { + fputc('>',f); + xml_write_value(f,node->value,0); + fprintf(f,"\r\n",node->name); + } + else + { + fprintf(f,"/>\r\n"); + } + break; + } + node = node->next; + } + return 1; +} + +long cXmlDoc::SaveToFile(const char* file) +{ + FILE* f = fopen(file,"wb"); + m_level = 0; + if(f) + { + fprintf(f,"\r\n"); + SaveNode(f,m_root.f_child); + fclose(f); + return 1; + } + else + { + return 0; + } +} +void cXmlDoc::Free() +{ + m_root.Free(); +} + +const char* cXmlDoc::GetProperty(sXmlNode* node,const char* name) +{ + sXmlProperty* prop; + if(!node || !name)return NULL; + + prop = node->f_prop; + while(prop){ + if(strcmp(prop->name,name)==0){ + return (const char*)prop->value; + } + prop = prop->next; + } + return NULL; +} + +long cXmlDoc::SetValue(sXmlNode* node,const char* value) +{ + if(!node || !node->value || !value)return 0; + + char* tmp = _strdup(value); + if(!tmp)return 0; + free((void*)node->value); + node->value = tmp; + return 1; +} + +sXmlNode* cXmlDoc::GetNode(const char* path,sXmlNode* parent) +{ + sXmlNode* n = NULL; + char* c = NULL; + char* sc = (char*)path; + + if(!path || !strlen(path)) + { + return NULL; + } + if(!parent) + { + parent = &m_root; + } +Next: + c = strchr(sc,'/'); + if(!c) + { + c = sc + strlen(sc); + } + if(c == sc) + { + return NULL; + } + + n = parent->f_child; + while(n) + { + if(n->name && strncmp(n->name,sc,c - sc) == 0) + { + if(*c == '\0') + { + return n; + } + else + { + sc = c + 1; + parent = n; + goto Next; + } + } + n = n->next; + } + return NULL; +} + +sXmlNode* cXmlDoc::AddNewNode(const char* name,const char* value,sXmlNode* parent) +{ + sXmlNode* tmp; + + if(!parent){parent = &m_root;} + + if(!parent || !name || !value){ + return NULL; + } + + if((tmp = GetNode(name,parent)) && tmp->value && strcmp(tmp->value,value)==0){ + return tmp; + }else{ + tmp = NULL; + } + + tmp = (sXmlNode*)malloc(sizeof(sXmlNode)); + if(!tmp){ + return NULL; + } + memset(tmp,0,sizeof(sXmlNode)); + + tmp->name = _strdup(name); + tmp->value = _strdup(value); + tmp->parent = parent; + tmp->type = NODE_DATA; + JoinParent(parent,tmp); + return tmp; +} + +long cXmlDoc::ParseString(char* buffer, long flags) +{ + char* c = NULL; + char* s = NULL; + long level = 0; + + m_root.Free(); + + /*initializing processor*/ + s = c = buffer; + /*processing*/ + c = xml_strnws(c); + if(!c){ + goto End;//empty? + } + + if(strncmp(c,""); + if(!c) + { + goto Error; + } + c += 2; + } + m_parse_flags = flags; +GoOn: + c = ParseNode(c,&m_root); + if(!c) + { + goto Error; + } + else if(*c != '\0' && ((m_parse_flags & cXmlDoc::PARSE_MULTIPLE_ROOTS) || m_root.l_child == NULL + || (m_root.l_child->type != cXmlDoc::NODE_PARENT && m_root.l_child->type != cXmlDoc::NODE_DATA))) + { + goto GoOn; + } + +End: + return 1; +Error: + m_root.Free(); + return 0; +} + +long cXmlDoc::ParseFile(const char* file,long flags) +{ + cutMemf mf; + + if(!mf.load(mb2u(file), 0)){ + return 0; + } + + if(ParseString((char*)mf.getdata(),flags)){ + mf.close(); + return 1; + }else{ + mf.close(); + return 0; + } +} \ No newline at end of file -- cgit v1.2.3