/* * FTP/HTTP daemon * util.cc Copyright (C) 1995, 96 Alex Belits * * This source/code is public free; you can distribute it and/or modify * it under terms of the GNU General Public License (published by the * Free Software Foundation) either version two of this License, or any * later version. * */ #include "fhttpd.h" char *strupr(char *s){ char *s1=s; while(*s1){ if(*s1>='a'&&*s1<='z') *s1&=0xdf; s1++; } return s; } int swrite(int h,char *s){ return write(h,s,strlen(s)); } signed char char64value(signed char c){ if(c>='A'&&c<='Z') return c-'A'; if(c>='a'&&c<='z') return c-'a'+26; if(c>='0'&&c<='9') return c-'0'+52; switch(c){ case '+': return 62; case '/': return 63; case 0: case '=': return -2; } return -1; } /* |------|-------|-------|------| 543210 54 3210 5432 10 543210 765432 10 7654 3210 76 543210 |---------|---------|---------| */ unsigned long un64(char *s){ signed char *rptr,*wptr,*endptr; signed char c0,c1,c2,c3; int l; rptr=(signed char*)s; wptr=(signed char*)s; while(*rptr){ if((*wptr=char64value(*rptr))!=-1){ wptr++; } rptr++; } *wptr=-2; rptr=(signed char*)s; wptr=(signed char*)s; do{ c0=*rptr; if(c0!=-2) c1=rptr[1]; else c1=-2; if(c1!=-2) c2=rptr[2]; else c2=-2; if(c2!=-2) c3=rptr[3]; else c3=-2; if(c0==-2) l=0; else if(c1==-2) l=1; else if(c2==-2) l=2; else if(c3==-2) l=3; else l=4; if(l>1){ *wptr=(c0<<2)|((c1&0x30)>>4); if(l>2){ wptr[1]=((c1&0x0f)<<4)|((c2&0x3c)>>2); if(l>3){ wptr[2]=((c2&0x03)<<6)|c3; wptr[3]=0; endptr=wptr+3; }else{ wptr[2]=0; endptr=wptr+2; } }else{ wptr[1]=0; endptr=wptr+1; } }else{ *wptr=0; endptr=wptr; } rptr+=l; wptr+=3; }while(*rptr!=-2); return endptr-(signed char*)s; } void unescape(char *s){ int j; unsigned char *p; for(j=0;s[j];j++){ p=(unsigned char*)s+j; switch(*p){ case '+': *p=' '; break; case '%': if(p[1]>='0'&&p[1]<='9'||(p[1]&0xdf)>='A'&&(p[1]&0xdf)<='F'){ if(p[2]>='0'&&p[2]<='9'||(p[2]&0xdf)>='A'&&(p[2]&0xdf)<='F'){ if(p[1]>='a'&&p[1]<='f') *p=(p[1]-'a'+0xa)<<4; else if(p[1]>='A'&&p[1]<='F') *p=(p[1]-'A'+0xa)<<4; else *p=(p[1]-'0')<<4; if(p[2]>='a'&&p[2]<='f') *p|=p[2]-'a'+0xa; else if(p[2]>='A'&&p[2]<='F') *p|=p[2]-'A'+0xa; else *p|=p[2]-'0'; while(p[3]){ p++; *p=p[2]; } p++; *p=0; } } } } } /* Weekday, DD-Mon-YY[YY] HH:MM:SS TIMEZONE *p1*p3 *p4 *p5 *p2 */ char *monthnames[12]={"Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec"}; char *weekdaynames[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}; char *linefromtime(char *s,time_t t){ struct tm *ttm; ttm=gmtime(&t); if(ttm){ sprintf(s,"%s, %02u-%s-%02u %02u:%02u:%02u GMT",weekdaynames[ttm->tm_wday%7],ttm->tm_mday, monthnames[ttm->tm_mon%12],ttm->tm_year%100,ttm->tm_hour,ttm->tm_min,ttm->tm_sec); }else *s=0; return s; } time_t timefromline(char *s){ time_t t; int i; char tmpstr[80]; char *ptmp,*p1=NULL,*p2=NULL,*p3=NULL,*p4=NULL,*p5=NULL; struct tm ttm; memset((char*)&ttm,0,sizeof(ttm)); strncpy(tmpstr,s,80); tmpstr[79]=0; ptmp=strchr(tmpstr,';'); if(ptmp) *ptmp=0; p1=strchr(tmpstr,','); if(p1){ *p1=0; p1++; while(*p1==' ') p1++; p2=strrchr(p1,' '); if(p2){ *p2=0; p2++; } p3=strchr(p1,'-'); ptmp=strchr(p1,' '); if(ptmp&&(!p3||p3>ptmp)) p3=ptmp; if(p3){ *p3=0; p3++; p4=strchr(p3,'-'); ptmp=strchr(p3,' '); if(ptmp&&(!p4||p4>ptmp)) p4=ptmp; if(p4){ *p4=0; p4++; p5=strchr(p4,' '); if(p5){ *p5=0; p5++; } } } } if(p1&&p2&&p3&&p4&&p5){ if(sscanf(p1,"%u",&ttm.tm_mday)){ if(sscanf(p4,"%u",&ttm.tm_year)){ if(ttm.tm_year<70) ttm.tm_year+=100; /* FIX in 2070!!!*/ else{ if(ttm.tm_year>=100) ttm.tm_year-=1900; } if(sscanf(p5,"%u:%u:%u",&ttm.tm_hour,&ttm.tm_min,&ttm.tm_sec)==3){ for(i=0;i<12;i++){ if(!strcasecmp(monthnames[i],p3)){ ttm.tm_mon=i; i=12; } } if(i==13){ ttm.tm_isdst=-1; t=mktime(&ttm); #ifdef GLOBAL_TIMEZONE t-=timezone; #else #ifdef TM_GMTOFF_PRESENT t+=localtime(&t)->tm_gmtoff; #endif #endif return t; } } } } } return (time_t)0; } int filenamecmp(char *s1,char *s2,int *noslashflag){ int noslashvar,*noslash=&noslashvar; char *s11=s1,*s22=s2; int n; if(noslashflag) noslash=noslashflag; while(*s11==*s22&&*s11){ s11++; s22++; } if(!*s11&&!*s22) return 0; if(*s11!='/'&&*s22!='/'){ if(s11==s1) return 1; s11--; s22--; } n=((*s11=='/')<<1)|(*s22=='/'); switch(n){ case 0: return 1; case 1: // *s22=='/' && *s11!='/' if(*s11) return 1; if(!s22[1]){ *noslash=1; return 0; } if(!strcmp(s22,"/file_index.html")){ *noslash=1; return 0; } if(!strcmp(s22,"/index.html")){ *noslash=1; return 0; } return 1; case 2: // *s11=='/' && *s22!='/' if(*s22) return 1; if(!s11[1]){ *noslash=1; return 0; } if(!strcmp(s11,"/file_index.html")){ *noslash=1; return 0; } if(!strcmp(s11,"/index.html")){ *noslash=1; return 0; } return 1; default: // *s11=='/' && *s22=='/' if(s22[1]) if(strcmp(s22,"/file_index.html")) if(strcmp(s22,"/index.html")) return 1; if(!s11[1]) return 0; if(!strcmp(s11,"/file_index.html")) return 0; if(!strcmp(s11,"/index.html")) return 0; return 1; } } int hastrailingslash(char *s1){ int r=0; char *s111,*s11; s111=strchr(s1,'?'); if(s111) *s111=0; s11=strrchr(s1,'/'); if(s11) r=(s11[1]==0); if(s111) *s111='?'; return r; } int trailingslashcmp(char *s1,char *s2){ char *s111,*s222; char *s11,*s22; int n1,n2; s111=strchr(s1,'?'); s222=strchr(s2,'?'); if(s111) *s111=0; if(s222) *s222=0; s11=strrchr(s1,'/'); s22=strrchr(s2,'/'); if(s111) *s111='?'; if(s222) *s222='?'; if(!s11||!s22){ if(s11==s22) return 0; else return 1; } n2=1; n1=1; if(s22[1]&&s22[1]!='?') if(strcmp(s22,"/file_index.html")) if(strcmp(s22,"/index.html")) n2=0; if(s11[1]&&s11[1]!='?') if(strcmp(s11,"/file_index.html")) if(strcmp(s11,"/index.html")) n1=0; return n2!=n1; } int mycompar0(const void *a,const void *b){ int i; char* namebegin_a=(*(char**)a)+(*((int*)(*(char**)a))+2*sizeof(int)); char* namebegin_b=(*(char**)b)+(*((int*)(*(char**)b))+2*sizeof(int)); char* nameend_a=(*(char**)a)+(*((int*)((*(char**)a)+sizeof(int)))+2*sizeof(int)); char* nameend_b=(*(char**)b)+(*((int*)((*(char**)b)+sizeof(int)))+2*sizeof(int)); char *dot_a=nameend_a-1; char *dot_b=nameend_b-1; i=(namebegin_bnamebegin_a&&(*dot_a!='.')){ if(*dot_a<'0'||*dot_a>'9') nonnum_a=1; dot_a--; } if(nonnum_a){ while(dot_b>namebegin_b&&(*dot_b!='.')){ if(*dot_b<'0'||*dot_b>'9') nonnum_b=1; dot_b--; } if(nonnum_b){ i=(*dot_b=='.')-(*dot_a=='.'); if(i) return i; while(dot_a': memcpy(dst,">",4); dst+=4; break; case '&': memcpy(dst,"&",5); dst+=5; break; default: *dst=*src; dst++; } src++; } *dst=0; return dst-origdst; } int urlencode(char *dst,const char *src,char except){//may increase the size up to 3 times! if(!dst) return 0; if(!src){ *dst=0; return 0; } char *origdst=dst; while(*src){ if((((*src&&*src>='@'&&*src<'~') ||(*src>='0'&&*src<='9') ||*src=='*'||*src=='-'||*src=='.') &&*src!='{'&&*src!='}'&&*src!='['&&*src!=']') ||(*src=='/')||(*src==except&&except)){ *dst=*src; dst++; }else{ *dst='%'; dst[1]=(char)((*src&0xf0)>>4); dst[2]=(char)(*src&0x0f); if(dst[1]<=9) dst[1]+='0';else dst[1]+='A'-10; if(dst[2]<=9) dst[2]+='0';else dst[2]+='A'-10; dst+=3; } src++; } *dst=0; return dst-origdst; }