diff -urN thttpd-2.21-6/Makefile.in thttpd-2.21-7/Makefile.in --- thttpd-2.21-6/Makefile.in Thu Nov 22 14:43:09 2001 +++ thttpd-2.21-7/Makefile.in Thu Nov 22 14:43:09 2001 @@ -46,7 +46,7 @@ # You shouldn't need to edit anything below here. -CC = @CC@ -Wall +CC = @CC@ -Wall -g CCOPT = @V_CCOPT@ DEFS = @DEFS@ INCLS = -I. @@ -80,6 +80,7 @@ thttpd: $(OBJ) @rm -f $@ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(NETLIBS) + libhttpd.o: mime_encodings.h mime_encodings.h: mime_encodings.txt diff -urN thttpd-2.21-6/config.h thttpd-2.21-7/config.h --- thttpd-2.21-6/config.h Thu Nov 22 14:43:09 2001 +++ thttpd-2.21-7/config.h Thu Nov 22 14:43:09 2001 @@ -218,6 +218,7 @@ */ #define VHOST_MYSQL +#ifdef VHOST_MYSQL /* CONFIGURE: ** Interval for reloading the table from the mysql db @@ -232,6 +233,15 @@ #define ADVCOUNTER +/* CONFIGURE: +** Define custom error 404 file name +*/ +#define ERR404FILENAME "/banners/404.html" +/* CONFIGURE: +** Define redirection based on referer domain +*/ +#define REFERER_REDIR +#endif /* CONFIGURE: Define this if you want to always use a global passwd file, ** without having to give the -P command line flag. You can still disable ** it at runtime with the -noP flag. diff -urN thttpd-2.21-6/libhttpd.c thttpd-2.21-7/libhttpd.c --- thttpd-2.21-6/libhttpd.c Thu Nov 22 14:43:09 2001 +++ thttpd-2.21-7/libhttpd.c Thu Nov 22 14:43:09 2001 @@ -81,7 +81,8 @@ extern struct node *vh_list; extern struct banner *bn_list; -extern int vh_list_len, bn_list_len; +extern struct rfr_rdr *redir_list; +extern int vh_list_len, bn_list_len,rd_list_len; int numreq=0; #endif @@ -235,6 +236,7 @@ + static void child_reaper( ClientData client_data, struct timeval* nowP ) { @@ -731,7 +733,6 @@ "Content-Range: bytes %ld-%ld/%d\r\nContent-Length: %ld\r\n", (long) hc->init_byte_loc, (long) hc->end_byte_loc, length, (long) ( hc->end_byte_loc - hc->init_byte_loc + 1 ) ); - #endif add_response( hc, buf ); } @@ -743,7 +744,6 @@ #else (void) my_snprintf( buf, sizeof(buf), "Content-Length: %d\r\n", length ); - #endif add_response( hc, buf ); } @@ -856,12 +856,81 @@ } +#ifdef REFERER_REDIR +int referer_redirect(httpd_conn *hc) +{ + static char rfr[128]; + char *cp,*cp2; + static char headstr[] = "Location: "; + int i,m=2; + + if (hc->referer==NULL) + return 1; + + memset(rfr,0,sizeof(rfr)); + cp=hc->referer; + if (strncmp(cp,"http://",7)==0) cp+=7; + cp2=strchr(cp,'/'); + if (cp2!=NULL) + { + strncpy(rfr,cp,(size_t) (cp2-cp) ); + rfr[(size_t) (cp2-cp)]=0; + } + else strcpy(rfr,cp); + cp=rfr; + for (i=strlen(cp);i>0;i--) + { + if ( *(cp+i)=='.') + { + m--; if (m==0) break; + }; + } + if (i!=0) + { + cp++; + cp+=i; + } + /* okay,we have the domain, let's try to match it */ + m=rdr_bin_search(redir_list,rd_list_len, cp); + if (m==-1) + { + syslog(LOG_ERR,"Doesnt match\n"); + return 1; + } + else + { + httpd_realloc_str( &header, &maxheader, sizeof(headstr) + strlen( redir_list[m].url ) ); + (void) my_snprintf( header, maxheader, + "%s%s\r\n", headstr, redir_list[m].url ); + send_response( hc, 302, err302title, header, err302form, redir_list[m].url ); + return 0; + } +} + +#endif + + void httpd_send_err( httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg ) - { +{ + #ifdef ERR_DIR + static char filename[1000]; +#endif +#ifdef VHOST_MYSQL +#ifdef ERR404FILENAME + /* + We want our own err404... + */ - char filename[1000]; + if ( (status==404) || (status==400) ) + { + if ( send_err_file( hc, status, title, extraheads, ERR404FILENAME) ) + return; + } +#endif +#endif +#ifdef ERR_DIR /* Try virtual host error page. */ if ( hc->hs->vhost && hc->hostdir[0] != '\0' ) @@ -1193,7 +1262,7 @@ (void) my_snprintf( header, maxheader, "%s%s\r\n", headstr, location ); send_response( hc, 302, err302title, header, err302form, location ); - } +} char* @@ -1450,8 +1519,8 @@ */ /* - Rules: If it ends with / (e.g. dirindex, if exists), .htm or .html, it should have - banners put. + Rules: If it ends with / (e.g. dirindex, if exists), .htm or .html,or doesn't have + any path ( like http://www.xxx.com ) it should have banners put. */ if ( ( hc->origfilename[strlen(hc->origfilename)-1]=='/') || (strcasecmp(ext,"htm")==0) || @@ -3481,6 +3550,13 @@ expnlen = strlen( hc->expnfilename ); +#ifdef REFERER_REDIR + syslog(LOG_ERR,"cheching rfr_rdr\n"); + if ( referer_redirect(hc) == 0 ) + return -1; +#endif + + if ( hc->method != METHOD_GET && hc->method != METHOD_HEAD && hc->method != METHOD_POST ) { @@ -3702,7 +3778,11 @@ ext=rindex(hc->origfilename,'.'); if ( ext==NULL) ext=hc->origfilename; else ext++; - // check if the extension is valid + /* check if the extension is valid */ + /* + XXX this SUX! someone should do it with cfg or mysql stuff + */ + if (! ((strcasecmp(ext,"html")==0) || (strcasecmp(ext,"htm")==0) || (strcasecmp(ext,"js")==0) || @@ -3718,9 +3798,8 @@ (hc->origfilename[strlen(hc->origfilename)-1]=='/')|| (ext[0]==0))) { - //deny the request - httpd_send_err( - hc, 403, err403title, "", + /* deny the request */ + httpd_send_err( hc, 403, err403title, "", ERROR_FORM( err403form, "The requested URL '%.80s' is forbidden.\n" ), hc->encodedurl ); return -1; diff -urN thttpd-2.21-6/thttpd.c thttpd-2.21-7/thttpd.c --- thttpd-2.21-6/thttpd.c Thu Nov 22 14:43:09 2001 +++ thttpd-2.21-7/thttpd.c Thu Nov 22 14:43:09 2001 @@ -62,7 +62,8 @@ #include "vhostconf.h" extern struct node *vh_list; extern struct banner *bn_list; -extern int vh_list_len,bn_list_len; +extern struct rfr_rdr *redir_list; +extern int vh_list_len,bn_list_len,rd_list_len; #endif #ifdef ADVCOUNTER #include @@ -181,7 +182,8 @@ */ struct node *vh_list0; struct banner *bn_list0; - int vh_list_len0,bn_list_len0; + struct rfr_rdr *redir_list0; + int vh_list_len0,bn_list_len0,rd_list_len0; /* we do it transactionally @@ -202,6 +204,15 @@ free_vh_list(vh_list0,vh_list_len0); return; }; +#ifdef REFERER_REDIR + redir_list0=rdr_list_init(&rd_list_len0); + if (redir_list0==NULL) + { + free_vh_list(vh_list0,vh_list_len0); + free_bn_list(bn_list0,bn_list_len0); + return; + } +#endif syslog(LOG_ERR,"Vhosts reloaded\n"); free_vh_list(vh_list,vh_list_len); vh_list=vh_list0; @@ -209,9 +220,19 @@ free_bn_list(bn_list,bn_list_len); bn_list=bn_list0; bn_list_len=bn_list_len0; +#ifdef REFERER_REDIR + free_rdr_list(redir_list,rd_list_len); + redir_list=redir_list0; + rd_list_len=rd_list_len0; +#endif syslog(LOG_ERR,"Switched vhosts/banners\n"); } +void handle_segv(int sig) +{ + logstats(NULL); + exit(2); +} #endif static void @@ -348,6 +369,7 @@ else logfp = (FILE*) 0; #else + no_log = 1 ; logfp = (FILE*) 0; #endif @@ -472,6 +494,9 @@ if (vh_list==NULL) exit(1); bn_list=init_banners_list(&bn_list_len); if (bn_list==NULL) exit(1); +#ifdef REFERER_REDIR + redir_list=rdr_list_init(&rd_list_len); + if (redir_list==NULL) exit(1); #endif #ifdef ADVCOUNTER UDSfd = socket(AF_UNIX,SOCK_DGRAM,0); @@ -491,10 +516,8 @@ { (void) fprintf( stderr, "error connecting to %s, %s\n",UDSPATH,strerror(errno)); } - - #endif - +#endif /* Set up to catch signals. */ (void) signal( SIGTERM, handle_term ); (void) signal( SIGINT, handle_term ); @@ -503,7 +526,9 @@ got_usr1 = 0; (void) signal( SIGUSR1, handle_usr1 ); (void) signal( SIGUSR2, handle_usr2 ); - +#ifdef VHOST_MYSQL + (void) signal( SIGSEGV, handle_segv ); +#endif /* Initialize the timer package. */ tmr_init(); diff -urN thttpd-2.21-6/vhost.c thttpd-2.21-7/vhost.c --- thttpd-2.21-6/vhost.c Thu Nov 22 14:43:09 2001 +++ thttpd-2.21-7/vhost.c Thu Nov 22 14:43:09 2001 @@ -15,7 +15,8 @@ struct node *vh_list; struct banner *bn_list; -int vh_list_len,bn_list_len; +struct rfr_rdr *redir_list; +int vh_list_len,bn_list_len,rd_list_len; /* Allocates memory for *tmp, and loads the vhost map in it. Sets n accordingly. @@ -70,7 +71,6 @@ (*n)++; row=mysql_fetch_row(result); } - (*n)--; mysql_free_result(result); mysql_close(conn); return tmp; @@ -180,13 +180,81 @@ (*n)++; } - (*n)--; mysql_free_result(result); mysql_close(conn); return tmp; } +struct rfr_rdr *rdr_list_init (int *n) +{ + MYSQL *conn; + MYSQL_RES * result; + MYSQL_ROW row; + struct rfr_rdr *tmp; + + + conn=mysql_init(NULL); + if (conn==NULL) + { + syslog(LOG_ERR,"Error initalizing mysql handle"); + return NULL; + } + if (mysql_real_connect(conn,DBHOST,DBUSER,DBPASS,DBNAME,0,NULL,0)==NULL) + { + syslog(LOG_ERR,"Error connecting to the database"); + return NULL; + } + + /* + I use string constant for the query, because I haven't thought of a way to + make it more flexible for the moment. + */ + + + if(mysql_real_query(conn,QUERY_RDR,strlen(QUERY_RDR)+1)!=0) + { + syslog(LOG_ERR,"Error querying the database"); + return NULL; + } + result=mysql_store_result(conn); + /* + Okay, we have the results , let's allocate some memory and parse them + */ + + tmp=(struct rfr_rdr *) malloc(sizeof(struct rfr_rdr) * mysql_num_rows(result)); + + row=mysql_fetch_row(result); + (*n)=0; + while (row!=NULL) + { + tmp[*n].domain=strdup(row[0]); + tmp[*n].url=strdup(row[1]); + (*n)++; + row=mysql_fetch_row(result); + } + mysql_free_result(result); + mysql_close(conn); + return tmp; + +} + + +void free_rdr_list(struct rfr_rdr *tmp, int len) +{ + + int i; + + for (i=0;i +/* + Vhost list struct + */ struct node { - char *vhost; char *path; char *adv; }; + +/* banners stuff */ struct day { char *banner[10]; @@ -36,14 +44,24 @@ /* + Referer redirection struct + */ + +struct rfr_rdr +{ + char *domain; + char *url; +}; - */ /* forward declarations */ struct node *vh_init_struct(int *n); struct banner *init_banners_list(int *n); +struct rfr_rdr *rdr_list_init (int *n); int bin_search(struct node *tbl, int n,char *tosrch); +int rdr_bin_search(struct rfr_rdr *tbl, int n, char *tosrch); void free_vh_list(struct node *tmp, int len); void free_bn_list(struct banner *tmp,int len); +void free_rdr_list(struct rfr_rdr *list, int len);