/* WebDownloader for X-Window * Copyright (C) 1999-2002 Koshelev Maxim * This Program is free but not GPL!!! You can't modify it * without agreement with author. You can't distribute modified * program but you can distribute unmodified program. * * 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. */ #include "addr.h" #include "locstr.h" #include "var.h" #include #include #include #include #include #include "dbc.h" #include "xml.h" #include #include #include #include #include #include #include #include void d4xXmlField::print(){ printf("%s=\"%s\"",name.get(),value.get()); }; void d4xXmlObject::print(){ printf("<%s",name.get()); d4xXmlField *fld=(d4xXmlField *)(fields.first()); while(fld){ printf(" "); fld->print(); fld=(d4xXmlField *)(fld->prev); }; printf(">\n%s",value.get()); printf(""); }; void d4xXmlObject::print_rec(int depth){ int i; for (i=0;iprint(); fld=(d4xXmlField *)(fld->prev); }; printf(">\n"); d4xXmlObject *obj=(d4xXmlObject *)objects.first(); while(obj){ obj->print_rec(depth+1); obj=(d4xXmlObject *)(obj->prev); }; printf("%s\n",value.get()); for (i=0;i\n"); }; d4xXmlField *d4xXmlObject::get_attr(const char *name){ d4xXmlField *fld=(d4xXmlField *)fields.first(); while(fld){ if (equal_uncase(name,fld->name.get())) return(fld); fld=(d4xXmlField *)(fld->prev); }; return(NULL); }; d4xXmlObject *d4xXmlObject::find_obj(const char *name){ return(d4x_xml_find_obj(&objects,name)); }; char *xml_replace_entities(const char *a){ char *tmp=str_replace(a,"<","<"); char *rval=str_replace(tmp,">",">"); delete[] tmp; return rval; }; /*************************************************************/ int d4x_xml_skip_for(int fd,char *b){ // printf("d4x_xml_skip_for!\n"); char a=0; int i=1; while(read(fd,&a,sizeof(char))==sizeof(char)){ if (index(b,a)){ i=0; break; }; }; return(i); }; void d4x_xml_read_grow(int fd,tPStr *str,char *b,char *stopchars){ // printf("d4x_xml_read_grow!\n"); char buf[101]; char *cur=buf; *b=0; while(read(fd,cur,1)==1){ if (index(stopchars,*cur)){ *b=*cur; *cur=0; cur=sum_strings(str->get(),buf,NULL); str->set(cur); delete[] cur; return; }; cur++; if (cur-buf>=100){ *cur=0; cur=sum_strings(str->get(),buf,NULL); str->set(cur); delete[] cur; cur=buf; }; }; }; int d4x_xml_read_value(int fd,tPStr *fld){ // printf("d4x_xml_read_value!\n"); unsigned char b[101]; unsigned char *cur=b; if (fld->get()==NULL) fld->set(""); while(read(fd,cur,1)==1){ if (*cur<' ') return(-1); switch(*cur){ case '\\':{ if (read(fd,cur,1)!=1 || *cur<' ') return(-1); switch(*cur){ case 'n': *cur='\n'; break; case 'b': *cur='\b'; break; case 't': *cur='\t'; break; }; break; }; case '\"':{ *cur=0; cur=(unsigned char *)sum_strings(fld->get(),b,NULL); fld->set((char*)cur); delete[] cur; return(0); }; }; cur++; if (cur-b>=100){ *cur=0; cur=(unsigned char*)sum_strings(fld->get(),b,NULL); fld->set((char*)cur); delete[] cur; cur=b; }; }; return(-1); }; int d4x_xml_read_fields(int fd,d4xXmlObject *obj){ // printf("d4x_xml_read_fields <%s>!\n",obj->name.get()); char b[2]={0,0}; while(read(fd,b,1)==1){ if (!isspace(*b)){ if (*b=='/'){ if (read(fd,b,1)==1 && *b=='>') return(1); return(-1); }; if (*b=='>') return(0); d4xXmlField *fld=new d4xXmlField; fld->name.set(b); d4x_xml_read_grow(fd,&(fld->name),b," \n\t\r<>="); if (*b=='>'){ delete(fld); return(0); }; if (*b==0 || *b=='<'){ delete(fld); return(-1); }; while(*b!='='){ if (read(fd,b,1)!=1 || (!isspace(*b) && *b!='=')){ delete(fld); return(-1); }; }; if (read(fd,b,1)!=1){ delete(fld); return(-1); }; while(isspace(*b)){ if (read(fd,b,1)!=1){ delete(fld); return(-1); }; }; if (*b!='\"' || d4x_xml_read_value(fd,&(fld->value))){ delete(fld); return(-1); }; if (fld->value.get()){ char *tmp=xml_replace_entities(fld->value.get()); fld->value.set(tmp); delete[] tmp; }; obj->fields.insert(fld); }; }; return(-1); }; d4xXmlObject *d4x_xml_read_tag(int fd); int d4x_xml_read_obj_body(int fd,d4xXmlObject *obj){ // printf("d4x_xml_read_body! <%s>\n",obj->name.get()); char b[2]={0,0}; obj->value.set(""); do { d4x_xml_read_grow(fd,&(obj->value),b,"<>"); if (obj->value.get()){ char *tmp=xml_replace_entities(obj->value.get()); obj->value.set(tmp); delete[] tmp; }; if (*b=='>' || *b==0) break; if (*b=='<'){ d4xXmlObject *chld=d4x_xml_read_tag(fd); if (chld && *(chld->name.get())=='/'){ delete(chld); return(0); }; if (chld==NULL) return(-1); obj->objects.insert(chld); }; }while(*b!=0); return(-1); }; void d4x_xml_skip_for_str(int fd,char *str){ int len=strlen(str); char *buf=new char[len+1]; buf[len]=0; if (read(fd,buf,len)!=len){ delete[] buf; return; }; while(!equal(str,buf)){ memmove(buf,buf+1,len-1); if (read(fd,buf+len-1,1)!=1) break; }; delete[] buf; }; d4xXmlObject *d4x_xml_read_tag(int fd){ // printf("d4x_xml_read_tag!\n"); char b[2]={0,0}; while(read(fd,b,1)==1){ if (!isspace(*b)) break; *b=0; }; if (*b=='>' || *b==0) return(NULL); d4xXmlObject *obj=new d4xXmlObject; obj->name.set(b); d4x_xml_read_grow(fd,&(obj->name),b," \n\t\r<>/"); if (*b=='<' || *b==0){ delete(obj); return(NULL); }; if (begin_string(obj->name.get(),"!--")){ if (*b!='>' || string_ended("--",obj->name.get())) d4x_xml_skip_for_str(fd,"-->"); delete(obj); if (d4x_xml_skip_for(fd,"<")) return(NULL); return(d4x_xml_read_tag(fd)); }; if (*b=='/'){ if (read(fd,b,1)==1 && *b=='>') return(obj); delete(obj); return(NULL); }; if (*b!='>'){ switch(d4x_xml_read_fields(fd,obj)){ case -1: delete(obj); return(NULL); case 1: return(obj); }; }; if (*(obj->name.get())=='/'){ return(obj); }; if (d4x_xml_read_obj_body(fd,obj)){ delete(obj); return(NULL); }; return(obj); }; tQueue *d4x_xml_parse_fd(int fd){ tQueue *rval=new tQueue; if (rval==NULL) return(NULL); if (d4x_xml_skip_for(fd,"<")){ delete(rval); return(NULL); }; d4xXmlObject *obj=d4x_xml_read_tag(fd); while(obj){ rval->insert(obj); if (d4x_xml_skip_for(fd,"<")) break; obj=d4x_xml_read_tag(fd); }; return(rval); }; tQueue *d4x_xml_parse_file(const char *filename){ int fd=open(filename,O_RDONLY); if (fd<0) return(NULL); tQueue *rval=d4x_xml_parse_fd(fd); close(fd); return(rval); }; void d4x_xml_out(tQueue *q){ d4xXmlObject *obj=(d4xXmlObject *)q->first(); while(obj){ obj->print_rec(0); obj=(d4xXmlObject *)(obj->prev); }; }; d4xXmlObject *d4x_xml_find_obj(tQueue *q,const std::string &name){ if (!q) return(NULL); d4xXmlObject *obj=(d4xXmlObject *)q->first(); std::string::size_type pos=name.find(' '); while(obj){ if (equal_uncase(name.substr(0,pos).c_str(),obj->name.get())){ if (pos!=std::string::npos){ d4xXmlObject *rval=d4x_xml_find_obj(&(obj->objects),name.substr(pos+1).c_str()); return(rval); }; return(obj); }; obj=(d4xXmlObject *)(obj->prev); }; return(0); }; /* path can be specified in next format: "ObjectName SubObjectName SubSubObjectName[>FieldName]" */ char *d4x_xml_find_obj_value(tQueue *q,const std::string &path){ std::string::size_type pos=path.find('>'); if (pos!=std::string::npos){ d4xXmlObject *obj=d4x_xml_find_obj(q,path.substr(0,pos)); d4xXmlField *f=obj?obj->get_attr(path.substr(pos+1).c_str()):NULL; if (f) return(f->value.get()); }else{ d4xXmlObject *obj=d4x_xml_find_obj(q,path); if (obj) return(obj->value.get()); }; return(0); };