diff -urN thttpd-2.21-0/Makefile.in thttpd-2.21-1/Makefile.in --- thttpd-2.21-0/Makefile.in Thu Mar 29 21:36:21 2001 +++ thttpd-2.21-1/Makefile.in Thu Nov 22 14:43:08 2001 @@ -39,7 +39,7 @@ # CONFIGURE: The group that the web directory belongs to. This is so that # the makeweb program can be installed set-group-id to that group, and make # subdirectories. If you're not going to use makeweb, ignore this. -WEBGROUP = www +WEBGROUP = www-data # CONFIGURE: Directory for CGI executables. CGIBINDIR = $(WEBDIR)/cgi-bin @@ -51,7 +51,7 @@ DEFS = @DEFS@ INCLS = -I. CFLAGS = $(CCOPT) $(DEFS) $(INCLS) -LDFLAGS = @LDFLAGS@ +LDFLAGS = @LDFLAGS@ -lmysqlclient LIBS = @LIBS@ NETLIBS = @V_NETLIBS@ INSTALL = @INSTALL@ @@ -62,7 +62,7 @@ @rm -f $@ $(CC) $(CFLAGS) -c $*.c -SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c +SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c vhost.c OBJ = $(SRC:.c=.o) @LIBOBJS@ @@ -163,11 +163,12 @@ rm -rf $$name ; \ gzip $$name.tar -thttpd.o: config.h version.h libhttpd.h fdwatch.h mmc.h timers.h match.h +thttpd.o: config.h version.h libhttpd.h fdwatch.h mmc.h timers.h match.h vhostconf.h libhttpd.o: config.h version.h libhttpd.h mime_encodings.h mime_types.h \ - mmc.h timers.h match.h tdate_parse.h + mmc.h timers.h match.h tdate_parse.h vhostconf.h fdwatch.o: fdwatch.h mmc.o: mmc.h timers.o: timers.h match.o: match.h tdate_parse.o: tdate_parse.h +vhost.o: vhostconf.h diff -urN thttpd-2.21-0/config.h thttpd-2.21-1/config.h --- thttpd-2.21-0/config.h Tue Apr 10 00:57:36 2001 +++ thttpd-2.21-1/config.h Thu Nov 22 14:43:08 2001 @@ -183,9 +183,7 @@ ** having to give the -v command line flag. You can still disable it at ** runtime with the -nov flag. */ -#ifdef notdef #define ALWAYS_VHOST -#endif /* CONFIGURE: If you're using the vhost feature and you have a LOT of ** virtual hostnames (like, hundreds or thousands), you will want to @@ -214,6 +212,18 @@ #define VHOST_DIRLEVELS 2 #define VHOST_DIRLEVELS 3 #endif +/* CONFIGURE: +** You can use the mapping between vhost and path from a mysql table, just define +** it here: +*/ + +#define VHOST_MYSQL + +/* CONFIGURE: +** Define special logging of requests through unix domain sockets +*/ + +#define ADVCOUNTER /* 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 @@ -227,7 +237,7 @@ ** initializing. If this user (or the one specified by the -u flag) does ** not exist, the program will refuse to run. */ -#define DEFAULT_USER "nobody" +#define DEFAULT_USER "www-data" /* CONFIGURE: When started as root, the program can automatically chdir() ** to the home directory of the user specified by -u or DEFAULT_USER. @@ -316,7 +326,7 @@ /* CONFIGURE: A list of index filenames to check. The files are searched ** for in this order. */ -#define INDEX_NAMES "index.html", "index.htm", "Default.htm", "index.cgi" +#define INDEX_NAMES "index.html", "index.htm" /* CONFIGURE: If this is defined then thttpd will automatically generate ** index pages for directories that don't have an explicit index file. diff -urN thttpd-2.21-0/libhttpd.c thttpd-2.21-1/libhttpd.c --- thttpd-2.21-0/libhttpd.c Sat Apr 21 03:11:32 2001 +++ thttpd-2.21-1/libhttpd.c Thu Nov 22 14:43:08 2001 @@ -76,6 +76,19 @@ # include # endif #endif +#ifdef VHOST_MYSQL +#include "vhostconf.h" +extern struct node *vh_list; +extern struct banner *bn_list; +extern int vh_list_len, bn_list_len; +int numreq=0; +#endif +#ifdef ADVCOUNTER +#include +extern int UDSfd; +long log_errors; +extern struct sockaddr_un UDSaddr; +#endif extern char* crypt( const char* key, const char* setting ); @@ -591,8 +604,13 @@ static void clear_ndelay( httpd_conn* hc ) { - int flags, newflags; - + int flags, newflags; + /* + XXX: wtf to turn off nonblocking??? + there is a bug somewhere, it tries to read from nonblocking socket... + so as a temporary measure, I disable it here - maniax + */ + return; flags = fcntl( hc->conn_fd, F_GETFL, 0 ); if ( flags != -1 ) { @@ -1295,6 +1313,12 @@ int i; char* cp2; #endif /* VHOST_DIRLEVELS */ +#ifdef VHOST_MYSQL + int tmp,j,j0,day; + time_t tm0; + struct tm *stt0; + char *ext; +#endif /* Figure out the virtual hostname. */ if ( hc->reqhost[0] != '\0' ) @@ -1347,9 +1371,74 @@ *cp2++ = '/'; } (void) strcpy( cp2, hc->hostname ); -#else /* VHOST_DIRLEVELS */ +#endif +#ifdef VHOST_MYSQL + tmp=bin_search(vh_list,vh_list_len,hc->hostname); + if (tmp==-1) + { + /* not found , fall back to default method*/ + httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, strlen( hc->hostname ) ); + (void) strcpy( hc->hostdir, hc->hostname ); + + } + else + { + httpd_realloc_str(&hc->hostdir,&maxtempfilename, + strlen(vh_list[tmp].path)); + (void) strcpy (hc->hostdir,vh_list[tmp].path); + maxtempfilename=0; + // shit, check if file is html!!! + ext=rindex(hc->origfilename,'.'); + if ( ext==NULL) ext=hc->origfilename; + else ext++; + // check if the extension is valid + if (! ((strcasecmp(ext,"html")==0) || + (strcasecmp(ext,"htm")==0) || + (strcasecmp(ext,"js")==0) || + (strcasecmp(ext,"jpg")==0) || + (strcasecmp(ext,"jpeg")==0) || + (strcasecmp(ext,"gif")==0) || + (strcasecmp(ext,"css")==0) || + (strcasecmp(ext,"png")==0) || + (strcasecmp(ext,"txt")==0) || + (strcasecmp(ext,"ico")==0) || + (strcasecmp(ext,"xml")==0) || + (strcasecmp(ext,"bmp")==0) )) + { + //deny the request + return 0; + } + + if ( ( hc->origfilename[strlen(hc->origfilename)-1]=='/') || (strcasecmp(ext,"htm")==0) + || (strcasecmp(ext,"html")==0) ) + { + for (j=0;jbanner=bn_list[j].days[stt0->tm_wday].banner[j0]; + hc->banner_under=bn_list[j].days[stt0->tm_wday].banner_under[j0]; + hc->ban=bn_list[j].days[stt0->tm_wday].fsizes[j0]; + hc->ban_u=bn_list[j].days[stt0->tm_wday].fsizes_und[j0]; + break; + } + } + } + + } + /* + XXX FIX!!! stupid ifdefs, etc + */ +#endif +#ifndef VHOST_MYSQL +#ifndef VHOST_DIRLEVELS httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, strlen( hc->hostname ) ); (void) strcpy( hc->hostdir, hc->hostname ); +#endif #endif /* VHOST_DIRLEVELS */ /* Prepend hostdir to the filename. */ @@ -1686,6 +1775,15 @@ hc->keep_alive = 0; hc->should_linger = 0; hc->file_address = (char*) 0; +#ifdef VHOST_MYSQL + hc->banner=(char *) (1) ; + hc->banner_under=(char *) (1); + hc->ban=0; + hc->ban_u=0; + hc->fpos=0; + hc->bpos=0; + hc->bpos_u=0; +#endif return GC_OK; } @@ -3625,10 +3723,10 @@ static void make_log_entry( httpd_conn* hc, struct timeval* nowP ) { +#ifndef ADVCOUNTER char* ru; char url[305]; char bytes[40]; - if ( hc->hs->no_log ) return; @@ -3712,7 +3810,31 @@ "%.80s - %.80s \"%.80s %.200s %.80s\" %d %s \"%.200s\" \"%.80s\"", httpd_ntoa( &hc->client_addr ), ru, httpd_method_str( hc->method ), url, hc->protocol, - hc->status, bytes, hc->referer, hc->useragent ); + hc->status, bytes, hc->referer, hc->useragent ); +#else + + char log_outp[512]; + + /* + generate packet to be sent to the counter + */ + memset(log_outp,0,512); + snprintf(log_outp,512,"%s|%s|%s|%s|",hc->hostname,httpd_ntoa( &hc->client_addr ),hc->origfilename,hc->referer); + if ((write(UDSfd, log_outp,strlen(log_outp)) < 0) && (errno != EAGAIN)) + { + if (connect(UDSfd, (struct sockaddr *) &UDSaddr, sizeof(UDSaddr)) < 0) + { + log_errors++; + if(log_errors==50000) + { + syslog(LOG_ERR,"Reconnection to counter failed, %s",strerror(errno)); + log_errors=0; + } + } + } + + +#endif } diff -urN thttpd-2.21-0/libhttpd.h thttpd-2.21-1/libhttpd.h --- thttpd-2.21-0/libhttpd.h Fri Apr 13 08:37:17 2001 +++ thttpd-2.21-1/libhttpd.h Thu Nov 22 14:43:08 2001 @@ -137,6 +137,10 @@ struct stat sb; int conn_fd; char* file_address; + char* banner, *banner_under; /* MYSQL_VHOST banners */ + off_t ban,ban_u; /* banner sizes... shit... */ + off_t fsize; + off_t fpos,bpos,bpos_u; } httpd_conn; /* Methods. */ diff -urN thttpd-2.21-0/sample.cfg thttpd-2.21-1/sample.cfg --- thttpd-2.21-0/sample.cfg Thu Jan 1 02:00:00 1970 +++ thttpd-2.21-1/sample.cfg Thu Nov 22 14:43:08 2001 @@ -0,0 +1 @@ +urlpat=**.jpg|**.gif|**.jpeg|**.bmp|**.png|**.js diff -urN thttpd-2.21-0/thttpd.c thttpd-2.21-1/thttpd.c --- thttpd-2.21-0/thttpd.c Sun Apr 15 19:09:20 2001 +++ thttpd-2.21-1/thttpd.c Thu Nov 22 14:43:08 2001 @@ -58,7 +58,17 @@ #include "mmc.h" #include "timers.h" #include "match.h" - +#ifdef VHOST_MYSQL +#include "vhostconf.h" +extern struct node *vh_list; +extern struct banner *bn_list; +extern int vh_list_len,bn_list_len; +#endif +#ifdef ADVCOUNTER +#include +int UDSfd; +struct sockaddr_un UDSaddr; +#endif static char* argv0; static int debug; @@ -172,7 +182,7 @@ handle_hup( int sig ) { FILE* logfp; - +#ifndef ADVCOUNTER if ( no_log ) return; @@ -188,6 +198,7 @@ (void) fcntl( fileno( logfp ), F_SETFD, 1 ); httpd_set_logfp( hs, logfp ); } +#endif } @@ -223,6 +234,10 @@ int gotv4, gotv6; struct timeval tv; +#ifdef ADVCOUNTER + long int flg; +#endif + argv0 = argv[0]; cp = strrchr( argv0, '/' ); @@ -262,6 +277,7 @@ if ( throttlefile != (char*) 0 ) read_throttlefile( throttlefile ); +#ifndef ADVCOUNTER /* Log file. */ if ( logfile != (char*) 0 ) { @@ -284,6 +300,7 @@ } else logfp = (FILE*) 0; +#endif /* Figure out uid/gid from user. */ pwd = getpwnam( user ); @@ -401,6 +418,36 @@ } } +#ifdef VHOST_MYSQL + vh_list=vh_init_struct(&vh_list_len); + if (vh_list==NULL) exit(1); + bn_list=init_banners_list(&bn_list_len); + if (bn_list==NULL) exit(1); + +#endif +#ifdef ADVCOUNTER + UDSfd = socket(AF_UNIX,SOCK_DGRAM,0); + if (UDSfd == -1 ) + { + (void) fprintf( stderr, "error creating unix domain socket %s \n",strerror(errno)); + exit( 1 ); + } + bzero( (char *) &UDSaddr, sizeof(UDSaddr)); + strcpy(UDSaddr.sun_path, UDSPATH); + UDSaddr.sun_family=AF_UNIX; + fcntl(UDSfd, F_GETFL, flg); + flg |= O_NONBLOCK; + fcntl(UDSfd, F_SETFL, flg); + + if (connect(UDSfd, (struct sockaddr *) &UDSaddr, sizeof(UDSaddr)) < 0) + { + (void) fprintf( stderr, "error connecting to %s, %s\n",UDSPATH,strerror(errno)); +// exit( 1 ); + } + + +#endif + /* Set up to catch signals. */ (void) signal( SIGTERM, handle_term ); (void) signal( SIGINT, handle_term ); @@ -1382,7 +1429,12 @@ c->bytes_to_send = hc->end_byte_loc + 1; } else - c->bytes_to_send = hc->bytes_to_send; + c->bytes_to_send = hc->bytes_to_send; + +#ifdef VHOST_MYSQL + hc->fsize=c->bytes_to_send; + c->bytes_to_send+= hc->ban+hc->ban_u; +#endif /* Check if it's already handled. */ if ( hc->file_address == (char*) 0 ) @@ -1420,6 +1472,12 @@ } +/* + fucked a lot by maniax + this really sucks ass, should be a bit rewriten and beautyfied + what bit... damn + */ + static void handle_send( connecttab* c, struct timeval* tvP ) { @@ -1429,6 +1487,7 @@ httpd_conn* hc = c->hc; /* Do we need to write the headers first? */ +#ifndef VHOST_MYSQL if ( hc->responselen == 0 ) { /* No, just write the file. */ @@ -1437,10 +1496,19 @@ MIN( c->bytes_to_send - c->bytes_sent, c->limit ) ); } else - { + { +#endif /* Yes. We'll combine headers and file into a single writev(), ** hoping that this generates a single packet. */ + + /* + XXX + kur + po nqkkakuv nachin tuk trqbva da vkaram server-vaneto na bannerite + majko mila..... + */ +#ifndef VHOST_MYSQL struct iovec iv[2]; iv[0].iov_base = hc->response; @@ -1448,8 +1516,28 @@ iv[1].iov_base = &(hc->file_address[c->bytes_sent]); iv[1].iov_len = MIN( c->bytes_to_send - c->bytes_sent, c->limit ); sz = writev( hc->conn_fd, iv, 2 ); - } +#else + struct iovec iv[4]; + iv[0].iov_base = hc->response; + iv[0].iov_len = hc->responselen; + + iv[1].iov_base = &(hc->banner[hc->bpos]); + iv[1].iov_len = hc->ban-hc->bpos; + + iv[2].iov_base = &(hc->file_address[hc->fpos]); + // iv[2].iov_len = MIN( hc->fsize , c->limit ); + iv[2].iov_len = hc->fsize-hc->fpos; + + iv[3].iov_base = &(hc->banner_under[hc->bpos_u]); + iv[3].iov_len = hc->ban_u-hc->bpos_u; + + sz = writev( hc->conn_fd, iv, 4 ); + +#endif +#ifndef VHOST_MYSQL + } +#endif if ( sz == 0 || ( sz < 0 && ( errno == EWOULDBLOCK || errno == EAGAIN ) ) ) { @@ -1519,6 +1607,42 @@ /* And update how much of the file we wrote. */ c->bytes_sent += sz; c->hc->bytes_sent += sz; +#ifdef VHOST_MYSQL + + if ( (sz>=(hc->ban-hc->bpos)) || (hc->bpos==hc->ban)) + { + // first banner served, no fscking with the pos + sz -= (hc->ban-hc->bpos); + hc->bpos=hc->ban; + + } else + { + hc->bpos+=sz; + sz=0; + } + if ( (sz>=(hc->fsize-hc->fpos)) || (hc->fsize==hc->fpos)) // file is served already + { + sz-=(hc->fsize-hc->fpos); + hc->fpos=hc->fsize; + } + else + { + hc->fpos+=sz; + sz=0; + } + if ( (sz>=(hc->ban_u-hc->bpos_u)) || (hc->ban_u==hc->bpos_u)) // file is served already + { + sz-=(hc->ban_u-hc->bpos_u); + hc->bpos_u=hc->ban_u; + } + else + { + hc->ban_u+=sz; + } + + + +#endif /* Are we done? */ if ( c->bytes_sent >= c->bytes_to_send ) diff -urN thttpd-2.21-0/vhost.c thttpd-2.21-1/vhost.c --- thttpd-2.21-0/vhost.c Thu Jan 1 02:00:00 1970 +++ thttpd-2.21-1/vhost.c Thu Nov 22 14:43:08 2001 @@ -0,0 +1,215 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vhostconf.h" + +struct node *vh_list; +struct banner *bn_list; +int vh_list_len,bn_list_len; + +/* + Allocates memory for *tmp, and loads the vhost map in it. Sets n accordingly. + */ + +struct node *vh_init_struct(int *n) +{ + + MYSQL *conn; + MYSQL_RES * result; + MYSQL_ROW row; + struct node *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,strlen(QUERY)+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 node *) malloc(sizeof(struct node) * mysql_num_rows(result)); + + row=mysql_fetch_row(result); + (*n)=0; + while (row!=NULL) + { + tmp[*n].vhost=strdup(row[0]); + tmp[*n].path=strdup(row[1]); + tmp[*n].adv=strdup(row[2]); + (*n)++; + row=mysql_fetch_row(result); + } + (*n)--; + mysql_close(conn); + return tmp; +} + +struct banner *init_banners_list(int *n) +{ + MYSQL *conn; + MYSQL_RES * result; + MYSQL_ROW row; + struct banner *tmp; + int i,j,fd; + struct stat st0; + char fname[255]; + + 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_BAN,strlen(QUERY_BAN)+1)!=0) + { + syslog(LOG_ERR,"Error querying the database %s",QUERY_BAN); + return NULL; + } + result=mysql_store_result(conn); + /* + Okay, we have the results , let's allocate some memory and parse them + */ + + tmp=(struct banner *) malloc(sizeof(struct banner) * mysql_num_rows(result)); + + row=mysql_fetch_row(result); + (*n)=0; + + while (row!=NULL) + { + tmp[*n].name=strdup(row[0]); + tmp[*n].num=atoi(row[1]); + + row=mysql_fetch_row(result); + /* + mmaping the files.... + */ + for (i=0;i0) + { + fstat(fd,&st0); + if (st0.st_size!=0) + { + tmp[*n].days[j].banner[i]=(char *) mmap(NULL,st0.st_size,PROT_READ,MAP_PRIVATE,fd,0); + tmp[*n].days[j].fsizes[i]=st0.st_size; + } + else + { + /* lets' follow the thttpd ideas here - never mmap zero length file */ + tmp[*n].days[j].banner[i]=(char *) (1); + tmp[*n].days[j].fsizes[i]=0; + } + close(fd); + } + snprintf(fname,255,"%s/%s/%d/%dbanner_under.html", BANNER_BASE, tmp[*n].name,j,i+1); + fd=open(fname,O_RDONLY); + if (fd>0) + { + fstat(fd,&st0); + if (st0.st_size!=0) + { + tmp[*n].days[j].banner_under[i]=(char *) mmap(NULL,st0.st_size,PROT_READ,MAP_PRIVATE,fd,0); + tmp[*n].days[j].fsizes_und[i]=st0.st_size; + } + else + { + /* lets' follow the thttpd ideas here - never mmap zero length file */ + tmp[*n].days[j].banner_under[i]=(char *) (1); + tmp[*n].days[j].fsizes_und[i]=0; + } + close(fd); + } + + } + + } + (*n)++; + + } + (*n)--; + mysql_close(conn); + return tmp; + +} + +/* + Searches for vhost position in *table + Uses simple binary search in sorted array, tests proved that it's fast enough + (30 000 searches in 30 000 elements array took about 100 ms , not like the + linear search,that took about 100 s ) + */ + +int bin_search(struct node *tbl, int n, char *tosrch) +{ + int k,i,left,right; + + left=0; + right=n; + while (left!=right) + { + i=(left+right)/2; + k=strcmp(tosrch,tbl[i].vhost); + if (k==0) return i; + if (k<0) right=i; + else + if (left==i) return -1 ; + else left=i; + + } + return -1; +} + diff -urN thttpd-2.21-0/vhostconf.h thttpd-2.21-1/vhostconf.h --- thttpd-2.21-0/vhostconf.h Thu Jan 1 02:00:00 1970 +++ thttpd-2.21-1/vhostconf.h Thu Nov 22 14:43:08 2001 @@ -0,0 +1,54 @@ +#define DBHOST "localhost" +#define DBNAME "test0" +#define DBUSER "root" +#define DBPASS "" +#define UDSPATH "/tmp/testsock" +#define QUERY "select hostname,path,advtype from vhost order by hostname" +#define QUERY_BAN "select advtype,num from numban" +#define BANNER_BASE "/home/banners" +#include + + + +struct node +{ + + char *vhost; + char *path; + char *adv; + +}; +struct day +{ + char *banner[10]; + int fsizes[10]; + char *banner_under[10]; + int fsizes_und[10]; + +}; +struct banner +{ + char *name; + int num; + struct day days[7]; +}; + + +/* + + + + */ + +/* forward declarations */ + +struct node *vh_init_struct(int *n); +struct banner *init_banners_list(int *n); +int bin_search(struct node *tbl, int n,char *tosrch); + + + + + + +