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

cfcgi.c

Go to the documentation of this file.
00001 
00010 /* {{{ Initial headers */
00011 /*
00012  * $LastChangedDate: 2004-04-01 18:34:17 +0200 (Thu, 01 Apr 2004) $
00013  * $LastChangedRevision: 50 $
00014  * $LastChangedBy: ckruse $
00015  *
00016  */
00017 /* }}} */
00018 
00019 /* {{{ Includes */
00020 #include "config.h"
00021 #include "defines.h"
00022 
00023 #include <sys/types.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 
00028 #include "hashlib.h"
00029 #include "utils.h"
00030 #include "cfcgi.h"
00031 /* }}} */
00032 
00036 /*\@{*/
00037 
00044 int _cf_cgi_parse_params(t_cf_hash *hash,u_char *data);
00045 
00055 int _cf_cgi_save_param(t_cf_hash *hash,u_char *name,int namlen,u_char *value);
00056 
00062 void cf_cgi_destroy_entry(void *data);
00063 /*\@}*/
00064 
00065 /*
00066  * Returns: t_cf_hash *    a hash with the cgi values in it
00067  * Parameters:
00068  *
00069  * this function parses the CGI paramters and returns a
00070  * hash with the entries in it.
00071  *
00072  */
00073 t_cf_hash *cf_cgi_new() {
00074   u_char *clen = getenv("CONTENT_LENGTH"),*rqmeth = getenv("REQUEST_METHOD"),*data;
00075   t_cf_hash *hash;
00076   long len  = 0;
00077   int trash = 0;
00078 
00079   if(!rqmeth) return NULL;
00080   if(clen) len = strtol(clen,NULL,10);
00081 
00082   hash = cf_hash_new(cf_cgi_destroy_entry);
00083 
00084   if(strcmp(rqmeth,"GET") == 0) {
00085     data = getenv("QUERY_STRING");
00086   }
00087   else {
00088     if(!len) {
00089       cf_hash_destroy(hash);
00090       return NULL;
00091     }
00092 
00093     trash = 1;
00094     data  = fo_alloc(NULL,len + 1,1,FO_ALLOC_MALLOC);
00095 
00096     fread(data,1,len,stdin);
00097     data[len] = '\0';
00098   }
00099 
00100   if(data && *data) {
00101     if(!_cf_cgi_parse_params(hash,data)) {
00102       cf_hash_destroy(hash);
00103       if(trash) free(data);
00104       return NULL;
00105     }
00106 
00107     return hash;
00108   }
00109   else {
00110     cf_hash_destroy(hash);
00111   }
00112 
00113   return NULL;
00114 }
00115 
00116 void cf_cgi_parse_path_info(t_array *ary) {
00117   u_char *data = getenv("PATH_INFO");
00118   register u_char *ptr = (u_char *)data+1;
00119   u_char *start = data,*name = NULL;
00120 
00121   array_init(ary,sizeof(char **),NULL);
00122 
00123   if(!data) return;
00124 
00125   if(*ptr) {
00126     for(;*ptr;ptr++) {
00127       if(*ptr == '/') {
00128         if(start) {
00129           name = strndup(start+1,ptr-start);
00130           array_push(ary,&name);
00131           start = ptr;
00132         }
00133         else {
00134           start = ptr;
00135         }
00136       }
00137     }
00138 
00139     name = strdup(start+1);
00140     array_push(ary,&name);
00141   }
00142 }
00143 
00144 /*
00145  * Returns: u_char *         the url decoded string
00146  * Parameters:
00147  *   - const u_char *str     the string to decode
00148  *   - long len            the length of the string
00149  *
00150  * This function decodes a url-encoded string
00151  *
00152  */
00153 u_char *cf_cgi_url_decode(const u_char *str,size_t len) {
00154   u_char *ret = fo_alloc(NULL,len + 1,1,FO_ALLOC_MALLOC); /* the new string can be as long as the old (but not longer) */
00155   register u_char *ptr1,*ptr2;
00156   u_char ptr3[2];
00157 
00158   if(!ret) return NULL;
00159 
00160   for(ptr1=ret,ptr2=(u_char *)str;*ptr2;ptr2++,ptr1++) {
00161     switch(*ptr2) {
00162       case '+':
00163         *ptr1 = ' ';
00164         break;
00165       case '%':
00166         memcpy(ptr3,ptr2+1,2);
00167         *ptr1 = strtol(ptr3,NULL,16);
00168         ptr2 += 2;
00169         break;
00170       default:
00171         *ptr1 = *ptr2;
00172     }
00173   }
00174 
00175   *ptr1 = '\0';
00176   return ret;
00177 }
00178 
00179 /*
00180  * Returns: u_char *         the url-encoded string
00181  * Parameters:
00182  *   - const u_char *str     the string to encode
00183  *   - long len            the length of the string
00184  *
00185  * This function url-encodes a string
00186  *
00187  */
00188 u_char *cf_cgi_url_encode(const u_char *str,size_t len) {
00189   long nlen = 3 * len + 1; /* new string can max 3x longer than old string (plus 0-byte) */
00190   u_char *nstr = fo_alloc(NULL,nlen,1,FO_ALLOC_MALLOC);
00191   register u_char *ptr1,*ptr2;
00192 
00193   for(ptr1=(u_char *)str,ptr2=nstr;*ptr1;ptr2++,ptr1++) {
00194     if((*ptr1 >= 48 && *ptr1 <= 122) || (*ptr1 == '_' || *ptr1 == '.' || *ptr1 == '-')) {
00195       *ptr2 = *ptr1;
00196     }
00197     else {
00198       if(*ptr1 == ' ') {
00199         *ptr2 = '+';
00200       }
00201       else {
00202         sprintf(ptr2,"%%%02X",(int)*ptr1);
00203         ptr2 += 2;
00204       }
00205     }
00206   }
00207 
00208   *ptr2 = '\0';
00209   nstr  = fo_alloc(nstr,ptr2-nstr,1,FO_ALLOC_REALLOC);
00210 
00211   return nstr;
00212 }
00213 
00214 /*
00215  * Returns: int            0 on failure, 1 on success
00216  * Parameters:
00217  *   - t_cf_hash *hash     the cgi-hash
00218  *   - u_char *name         the name of the field
00219  *   - int namlen          the length of the name-field
00220  *   - u_char *value        the value of the field
00221  *
00222  * This function saves a cgi-parameter to the hash
00223  *
00224  */
00225 int _cf_cgi_save_param(t_cf_hash *hash,u_char *name,int namlen,u_char *value) {
00226   t_cf_cgi_param *ent,*ent1;
00227 
00228   ent = cf_hash_get(hash,name,namlen);
00229   if(!ent) {
00230     ent        = fo_alloc(NULL,1,sizeof(t_cf_cgi_param),FO_ALLOC_CALLOC);
00231 
00232     ent->name  = name;
00233     ent->value = value;
00234 
00235     cf_hash_set(hash,name,namlen,ent,sizeof(t_cf_cgi_param));
00236 
00237     /* we make a copy, so we do not need it again */
00238     free(ent);
00239   }
00240   else {
00241     ent1            = fo_alloc(NULL,1,sizeof(t_cf_cgi_param),FO_ALLOC_CALLOC);
00242 
00243     ent1->name  = name;
00244     ent1->value = value;
00245 
00246     if(ent->last)
00247       ent->last->next = ent1;
00248     else
00249       ent->next       = ent1;
00250 
00251     ent->last         = ent1;
00252   }
00253 
00254   return 1;
00255 }
00256 
00257 /*
00258  * Returns: int            0 on failure, 1 on success
00259  * Parameters:
00260  *   - t_cf_hash *hash     the cgi-hash
00261  *   - u_char *data         the url-encoded data-string
00262  *
00263  * This function parses an url-encoded data-string
00264  *
00265  */
00266 int _cf_cgi_parse_params(t_cf_hash *hash,u_char *data) {
00267   u_char  *pos = data,*pos1 = data;
00268   u_char *name = NULL,*value = NULL;
00269   int len = 0,namlen = 0,vallen = 0;
00270 
00271   while((pos = strstr(pos1,"=")) != NULL) {
00272     namlen = pos - pos1;
00273     *pos   = 0;
00274     name   = cf_cgi_url_decode(pos1,namlen);
00275     *pos   = '=';
00276 
00277     pos1 = strstr(pos,"&");
00278     if(!pos1) break;
00279 
00280     vallen  = pos1 - pos;
00281     *pos1   = 0;
00282     value   = cf_cgi_url_decode(pos+1,vallen);
00283     *pos1++ = '&';
00284 
00285     if(!_cf_cgi_save_param(hash,name,namlen,value)) {
00286       free(name);
00287       free(value);
00288 
00289       fprintf(stderr,"%s[%d]: out of memory!\n",__FILE__,__LINE__);
00290       return 0;
00291     }
00292   }
00293 
00294   if(pos && *pos) {
00295     len   = strlen(pos+1);
00296     value = cf_cgi_url_decode(pos+1,len);
00297 
00298     if(!_cf_cgi_save_param(hash,name,namlen,value)) {
00299       free(name);
00300       free(value);
00301 
00302       fprintf(stderr,"%s[%d]: out of memory!\n",__FILE__,__LINE__);
00303       return 0;
00304     }
00305   }
00306 
00307   return 1;
00308 }
00309 
00310 /*
00311  * Returns:                nothing
00312  * Parameters:
00313  *   - void *data          the hash-entry
00314  *
00315  * This function destroys a hash-entry
00316  *
00317  */
00318 void cf_cgi_destroy_entry(void *data) {
00319   t_cf_cgi_param *ent = (t_cf_cgi_param *)data,*ent1;
00320 
00321   for(;ent;ent=ent1) {
00322     free(ent->name);
00323     free(ent->value);
00324 
00325     ent1 = ent->next;
00326 
00327     if(ent != data) free(ent);
00328   }
00329 }
00330 
00331 /*
00332  * Returns:                the value of the field
00333  * Parameters:
00334  *   - t_cf_hash *hash     the cgi-hash
00335  *   - const u_char *name   the name of the field
00336  *
00337  * this function gets a single value
00338  *
00339  */
00340 u_char *cf_cgi_get(t_cf_hash *hash,u_char *name) {
00341   t_cf_cgi_param *p = cf_hash_get(hash,name,strlen(name));
00342 
00343   if(p) {
00344     return p->value;
00345   }
00346 
00347   return NULL;
00348 }
00349 
00350 void cf_cgi_set(t_cf_hash *hash,const u_char *name,const u_char *value) {
00351   size_t nlen = strlen(name);
00352   t_cf_cgi_param *p = cf_hash_get(hash,(u_char *)name,nlen),*p1,*p2;
00353   t_cf_cgi_param par;
00354 
00355   if(p) {
00356     if(p->next) {
00357       for(p1=p->next;p1;p1=p2) {
00358         free(p1->name);
00359         free(p1->value);
00360         p2 = p1->next;
00361         free(p1);
00362       }
00363     }
00364 
00365     free(p->value);
00366     p->value = strdup(value);
00367   }
00368   else {
00369     par.name  = strdup(name);
00370     par.value = strdup(value);
00371     par.next  = NULL;
00372     par.last  = NULL;
00373 
00374     cf_hash_set(hash,(u_char *)name,nlen,&par,sizeof(par));
00375   }
00376 }
00377 
00378 /*
00379  * Returns:                 the value of the field
00380  * Parameters:
00381  *   - t_cf_hash *hash      the CGI hash
00382  *   - const u_char *param   the name of the parameter
00383  *
00384  * this function returns a multiple value list
00385  */
00386 t_cf_cgi_param *cf_cgi_get_multiple(t_cf_hash *hash,u_char *param) {
00387   return (t_cf_cgi_param *)cf_hash_get(hash,param,strlen(param));
00388 }
00389 
00390 /*
00391  * Returns:                 nothing
00392  * Parameters:
00393  *   - t_cf_hash *hash      the CGI hash
00394  *
00395  * this function destroys a CGI hash
00396  */
00397 void cf_cgi_destroy(t_cf_hash *hash) {
00398   cf_hash_destroy(hash);
00399 }
00400 
00404 u_int32_t path_info_parsed(u_char ***infos) {
00405   u_char *path = getenv("PATH_INFO"),*prev,**list = NULL;
00406   register u_char *ptr;
00407   int len = 0;
00408 
00409   if(path) {
00410     for(prev=ptr=path+1;*ptr;ptr++) {
00411       if(*ptr == '/') {
00412         *ptr        = '\0';
00413         list        = fo_alloc(list,++len,sizeof(char **),FO_ALLOC_REALLOC);
00414         list[len-1] = cf_cgi_url_decode(prev,ptr-prev);
00415         prev        = ptr+1;
00416         *ptr        = '/';
00417       }
00418     }
00419   }
00420 
00421   *infos = list;
00422   return len;
00423 }
00424 
00425 /* eof */

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