00001
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00067
00068
00069
00070
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
00146
00147
00148
00149
00150
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);
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
00181
00182
00183
00184
00185
00186
00187
00188 u_char *cf_cgi_url_encode(const u_char *str,size_t len) {
00189 long nlen = 3 * len + 1;
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
00216
00217
00218
00219
00220
00221
00222
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
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
00259
00260
00261
00262
00263
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
00312
00313
00314
00315
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
00333
00334
00335
00336
00337
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
00380
00381
00382
00383
00384
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
00392
00393
00394
00395
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