Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

flt_http.c

Go to the documentation of this file.
00001 
00008 /* {{{ Initial comments */
00009 /*
00010  * $LastChangedDate: 2004-04-01 18:34:17 +0200 (Thu, 01 Apr 2004) $
00011  * $LastChangedRevision: 50 $
00012  * $LastChangedBy: ckruse $
00013  *
00014  */
00015 /* }}} */
00016 
00017 /* {{{ Includes */
00018 #include "config.h"
00019 #include "defines.h"
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <time.h>
00026 
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 #include <sys/time.h>
00030 
00031 #include "hashlib.h"
00032 #include "readline.h"
00033 #include "utils.h"
00034 #include "configparser.h"
00035 #include "cfcgi.h"
00036 #include "template.h"
00037 #include "clientlib.h"
00038 
00039 /* }}} */
00040 
00041 struct {
00042   int send_last_modified;
00043   long send_expires;
00044   int expires_set;
00045   int handle_last_modified_since;
00046 } http_config = { 0, 0, 0, 0 };
00047 
00048 time_t flt_http_gmt_diff(void) {
00049     struct timeval now;
00050     time_t t1, t2;
00051     struct tm t;
00052 
00053     gettimeofday(&now, NULL);
00054     t1 = now.tv_sec;
00055     t2 = 0;
00056 
00057     t = *gmtime(&t1);
00058 
00059     t.tm_isdst = 0; /* we know this GMT time isn't daylight-savings */
00060     t2 = mktime(&t);
00061     return (time_t)difftime(t1, t2);
00062 }
00063 
00064 int flt_http_get_month(const u_char *m) {
00065   if(cf_strncmp(m,"Jan",3) == 0) {
00066     return 0;
00067   }
00068   else if(cf_strncmp(m,"Feb",3) == 0) {
00069     return 1;
00070   }
00071   else if(cf_strncmp(m,"Mar",3) == 0) {
00072     return 2;
00073   }
00074   else if(cf_strncmp(m,"Apr",3) == 0) {
00075     return 3;
00076   }
00077   else if(cf_strncmp(m,"May",3) == 0) {
00078     return 4;
00079   }
00080   else if(cf_strncmp(m,"Jun",3) == 0) {
00081     return 5;
00082   }
00083   else if(cf_strncmp(m,"Jul",3) == 0) {
00084     return 6;
00085   }
00086   else if(cf_strncmp(m,"Aug",3) == 0) {
00087     return 7;
00088   }
00089   else if(cf_strncmp(m,"Sep",3) == 0) {
00090     return 8;
00091   }
00092   else if(cf_strncmp(m,"Oct",3) == 0) {
00093     return 9;
00094   }
00095   else if(cf_strncmp(m,"Nov",3) == 0) {
00096     return 10;
00097   }
00098   else if(cf_strncmp(m,"Dec",3) == 0) {
00099     return 11;
00100   }
00101 
00102   return -1;
00103 }
00104 
00105 long flt_http_get_lm(int sock) {
00106   #ifndef CF_SHARED_MEM
00107   rline_t tsd;
00108   u_char *line;
00109   long ret = 0;
00110 
00111   if(writen(sock,"GET LASTMODIFIED 0\n",19) > 0) {
00112     memset(&tsd,0,sizeof(rline_t));
00113 
00114     if((line = readline(sock,&tsd)) != NULL) {
00115       ret = strtol(line,NULL,0);
00116       free(line);
00117     }
00118   }
00119 
00120   return ret;
00121   #else
00122   return *((time_t *)sock);
00123   #endif
00124 }
00125 
00126 int flt_http_validate_cache(t_cf_hash *head,t_configuration *dc,t_configuration *vc,time_t lm,int sock) {
00127   t_module *mod;
00128   t_cache_revalidator fkt;
00129   size_t i;
00130   int ret = FLT_DECLINE;
00131 
00132   if(Modules[0].elements) {
00133     for(i=0;i<Modules[0].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
00134       mod = array_element_at(&Modules[0],i);
00135 
00136       if(mod->cfg->revalidator) {
00137         fkt     = (t_cache_revalidator)mod->cfg->revalidator;
00138         ret     = fkt(head,dc,vc,lm,sock);
00139       }
00140     }
00141   }
00142 
00143   return ret;
00144 }
00145 
00146 int flt_http_header_callbacks(t_cf_hash *head,t_cf_hash *header_table,t_configuration *dc,t_configuration *vc,int sock) {
00147   t_module *mod;
00148   t_header_hook fkt;
00149   size_t i;
00150   int ret = FLT_DECLINE;
00151   int retret = FLT_OK;
00152 
00153   if(Modules[0].elements) {
00154     for(i=0;i<Modules[0].elements;i++) {
00155       mod = array_element_at(&Modules[0],i);
00156       if(mod->cfg->header_hook) {
00157         fkt = (t_header_hook)mod->cfg->header_hook;
00158         ret = fkt(head,header_table,dc,vc,sock);
00159 
00160         if(ret == FLT_EXIT) retret = FLT_EXIT;
00161       }
00162     }
00163   }
00164 
00165   return retret;
00166 }
00167 
00168 time_t flt_http_lm_callbacks(t_cf_hash *head,t_configuration *dc,t_configuration *vc,int sock,time_t t1) {
00169   t_module *mod;
00170   t_last_modified fkt;
00171   size_t i;
00172   time_t ret;
00173 
00174   if(Modules[0].elements) {
00175     for(i=0;i<Modules[0].elements;i++) {
00176       mod = array_element_at(&Modules[0],i);
00177       if(mod->cfg->header_hook) {
00178         fkt = (t_last_modified)mod->cfg->last_modified;
00179         ret = fkt(head,dc,vc,sock);
00180 
00181         if(ret == (time_t)-1) continue;
00182         if(ret > t1) t1 = ret;
00183       }
00184     }
00185   }
00186 
00187   return t1;
00188 }
00189 
00190 int flt_http_execute(t_cf_hash *head,t_configuration *dc,t_configuration *vc,int sock) {
00191   u_char buff[100];
00192   time_t t,t1;
00193   struct tm *tm;
00194   struct tm tm_lm;
00195   u_char *lm;
00196   int ret;
00197   t_cf_hash *header_table = cf_hash_new(NULL);
00198   ub4 elems = hashsize(header_table->tablesize);
00199   ub4 i;
00200   t_cf_hash_entry *ent;
00201   time_t diff = flt_http_gmt_diff();
00202 
00203   /* {{{ http header management */
00204   ret = flt_http_header_callbacks(head,header_table,dc,vc,sock);
00205 
00206   cf_hash_entry_delete(header_table,"Last-Modified",13);
00207 
00208   for(i=0;i<elems;i++) {
00209     if(header_table->table[i]) {
00210       for(ent=header_table->table[i];ent;ent=ent->next) {
00211         printf("%s: %s\015\012",ent->key,(char *)ent->data);
00212       }
00213     }
00214   }
00215 
00216   cf_hash_destroy(header_table);
00217 
00218   if(ret == FLT_EXIT) return FLT_EXIT;
00219   /* }}} */
00220 
00221   if(http_config.handle_last_modified_since || http_config.send_last_modified) {
00222     t1 = flt_http_get_lm(sock);
00223     t1 = flt_http_lm_callbacks(head,dc,vc,sock,t1);
00224     tm = gmtime(&t1);
00225 
00226     if(http_config.send_last_modified) {
00227       strftime(buff,100,"%a, %d %b %Y %H:%M:%S GMT",tm);
00228       printf("Last-Modified: %s\015\012",buff);
00229     }
00230 
00231     if(http_config.handle_last_modified_since) {
00232       if((lm = getenv("HTTP_IF_MODIFIED_SINCE")) != NULL && *lm != '\0') {
00233         tm_lm.tm_mday  = atoi(lm+5);
00234         tm_lm.tm_mon   = flt_http_get_month(lm+8);
00235         tm_lm.tm_year  = atoi(lm+12) - 1900;
00236         tm_lm.tm_wday  = 0;
00237         tm_lm.tm_hour  = atoi(lm+17);
00238         tm_lm.tm_min   = atoi(lm+20);
00239         tm_lm.tm_sec   = atoi(lm+23);
00240 
00241         tm_lm.tm_yday  = 0;
00242         tm_lm.tm_isdst = 0;
00243 
00244         if((t = timegm(&tm_lm)) >= 0) {
00245           if(t >= t1) {
00246             ret = flt_http_validate_cache(head,dc,vc,t+diff,sock);
00247 
00248             if(ret != FLT_EXIT) {
00249               printf("Status: 304 Not Modified\015\012\015\012");
00250               return FLT_EXIT;
00251             }
00252           }
00253         }
00254       }
00255     }
00256   }
00257 
00258   return FLT_DECLINE;
00259 }
00260 
00261 int flt_http_handle_command(t_configfile *cfile,t_conf_opt *opt,u_char **args,int argnum) {
00262   u_char *ptr = NULL;
00263 
00264   if(argnum == 1) {
00265     if(cf_strcmp(opt->name,"SendLastModified") == 0) {
00266       http_config.send_last_modified = cf_strcasecmp(args[0],"yes") == 0;
00267     }
00268     else if(cf_strcmp(opt->name,"SendExpires") == 0) {
00269       http_config.expires_set  = 1;
00270       http_config.send_expires = strtol(args[0],(char **)&ptr,10);
00271 
00272       if(ptr) {
00273         if(toupper(*ptr) == 'M') {
00274           http_config.send_expires *= 60L;
00275         }
00276         else if(toupper(*ptr) == 'H') {
00277           http_config.send_expires *= 60L * 60L;
00278         }
00279       }
00280 
00281     }
00282     else if(cf_strcmp(opt->name,"HandleLastModifiedSince") == 0) {
00283       if(cf_strcmp(args[0],"yes") == 0) {
00284         http_config.handle_last_modified_since = 1;
00285       }
00286     }
00287   }
00288   else {
00289     fprintf(stderr,"Expecting one argument for directive %s!\n",opt->name);
00290     return 1;
00291   }
00292 
00293   return 0;
00294 }
00295 
00296 int flt_http_set_headers(t_cf_hash *cgi,t_cf_hash *header_table,t_configuration *dc,t_configuration *vc,int sock) {
00297   char buff[BUFSIZ];
00298   size_t len;
00299   time_t t;
00300   struct tm *tm;
00301 
00302   if(http_config.expires_set) {
00303     t  = time(NULL) + http_config.send_expires;
00304     tm = gmtime(&t);
00305 
00306     if(tm) {
00307       len = snprintf(buff,BUFSIZ,"public, max-age=%ld",http_config.send_expires);
00308       cf_hash_set(header_table,"Cache-Control",14,buff,len+1);
00309 
00310       if((len = strftime(buff,BUFSIZ,"%a, %d %b %Y %H:%M:%S GMT",tm))) {
00311         cf_hash_set(header_table,"Expires",8,buff,len+1);
00312       }
00313     }
00314   }
00315 
00316   return FLT_OK;
00317 }
00318 
00319 int flt_http_validate(t_cf_hash *head,t_configuration *dc,t_configuration *vc,time_t last_modified,int sock) {
00320   u_char *uname = cf_hash_get(GlobalValues,"UserName",8);
00321   u_char *uconffile = NULL;
00322   struct stat st;
00323   int ret = FLT_DECLINE;
00324 
00325   if(uname) {
00326     uconffile = get_uconf_name(uname);
00327 
00328     if(uconffile) {
00329       if(stat(uconffile,&st) != -1) {
00330         if(st.st_mtime <= last_modified) ret = FLT_OK;
00331       }
00332 
00333       free(uconffile);
00334     }
00335   }
00336 
00337   return ret;
00338 }
00339 
00340 time_t flt_http_lm(t_cf_hash *head,t_configuration *dc,t_configuration *vc,int sock) {
00341   u_char *uname = cf_hash_get(GlobalValues,"UserName",8);
00342   u_char *uconffile = NULL;
00343   struct stat st;
00344   time_t ret = -1;
00345 
00346   if(uname) {
00347     uconffile = get_uconf_name(uname);
00348 
00349     if(uconffile) {
00350       if(stat(uconffile,&st) != -1) {
00351         ret = st.st_mtime;
00352       }
00353 
00354       free(uconffile);
00355     }
00356   }
00357 
00358   return ret;
00359 }
00360 
00361 t_conf_opt flt_http_config[] = {
00362   { "SendLastModified",        flt_http_handle_command, NULL },
00363   { "SendExpires",             flt_http_handle_command, NULL },
00364   { "HandleLastModifiedSince", flt_http_handle_command, NULL },
00365   { NULL, NULL, NULL }
00366 };
00367 
00368 t_handler_config flt_http_handlers[] = {
00369   { CONNECT_INIT_HANDLER, flt_http_execute },
00370   { 0, NULL }
00371 };
00372 
00373 t_module_config flt_http = {
00374   flt_http_config,
00375   flt_http_handlers,
00376   flt_http_validate,
00377   flt_http_lm,
00378   flt_http_set_headers,
00379   NULL
00380 };
00381 
00382 /* eof */

Generated on Sun Apr 25 16:37:38 2004 for Classic Forum by doxygen 1.3.5