Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

header.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: header.c,v 1.14 2006/04/06 14:02:22 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <u/libu.h>
00013 #include <klone/klone.h>
00014 #include <klone/header.h>
00015 #include <klone/utils.h>
00016 
00034 int header_set_field(header_t *h, const char *name, const char *value)
00035 {
00036     field_t* n = NULL, *ex;
00037 
00038     dbg_err_if (h == NULL);
00039     dbg_err_if (name == NULL);
00040     dbg_err_if (value == NULL);
00041 
00042     /* modify existing field if already set */
00043     if((ex = header_get_field(h, name)) == NULL)
00044     {
00045         dbg_err_if(field_create(name, value, &n));
00046         dbg_err_if(header_add_field(h, n));
00047     } else
00048         dbg_err_if(field_set(ex, name, value));
00049 
00050     return 0;
00051 err:
00052     if(n)
00053         field_free(n);
00054     return ~0;
00055 }
00056 
00066 int header_clear(header_t *h)
00067 {
00068     field_t *f;
00069     
00070     dbg_return_if (h == NULL, ~0);
00071     
00072     /* free all items */
00073     while((f = TAILQ_FIRST(&h->fields)) != NULL)
00074     {
00075         header_del_field(h, f);
00076         field_free(f);
00077     }
00078 
00079     return 0;
00080 }
00081 
00091 size_t header_field_count(header_t *h)
00092 {
00093     dbg_return_if (h == NULL, 0);
00094 
00095     return h->nfields;
00096 }
00097 
00108 field_t *header_get_fieldn(header_t *h, size_t idx)
00109 {
00110     field_t *f;
00111     size_t i = 0;
00112 
00113     dbg_goto_if (h == NULL, notfound);
00114     nop_goto_if (idx >= h->nfields, notfound);
00115 
00116     TAILQ_FOREACH(f, &h->fields, np)
00117     {
00118         if(i == idx)
00119             return f;
00120         ++i;
00121     }
00122 
00123 notfound:
00124     return NULL;
00125 }
00126 
00139 field_t *header_get_field(header_t *h, const char *name)
00140 {
00141     field_t *f = NULL;
00142 
00143     dbg_goto_if (h == NULL, notfound);
00144     dbg_goto_if (name == NULL, notfound);
00145 
00146     TAILQ_FOREACH(f, &h->fields, np)
00147         if(strcasecmp(f->name, name) == 0)
00148             return f;
00149 
00150 notfound:
00151     return NULL;
00152 }
00153 
00166 const char *header_get_field_value(header_t *h, const char *name)
00167 {
00168     field_t *f;
00169 
00170     dbg_return_if (h == NULL, NULL);
00171     dbg_return_if (name == NULL, NULL);
00172     
00173     f = header_get_field(h, name);
00174 
00175     return f ? field_get_value(f) : NULL;
00176 }
00177 
00188 int header_del_field(header_t *h, field_t *f)
00189 {
00190     dbg_return_if (h == NULL, ~0);
00191     dbg_return_if (f == NULL, ~0);
00192 
00193     TAILQ_REMOVE(&h->fields, f, np);
00194     h->nfields--;
00195 
00196     return 0;
00197 }
00198 
00209 int header_add_field(header_t *h, field_t *f)
00210 {
00211     dbg_return_if (h == NULL, ~0);
00212     dbg_return_if (f == NULL, ~0);
00213 
00214     TAILQ_INSERT_TAIL(&h->fields, f, np);
00215     h->nfields++;
00216 
00217     return 0;
00218 }
00219 
00220 static int header_process_line(header_t *h, u_string_t *line)
00221 {
00222     field_t *f = NULL;
00223     const char *p;
00224 
00225     dbg_err_if (h == NULL);
00226     dbg_err_if (line == NULL);
00227     
00228     if(!u_string_len(line))
00229         return 0;
00230 
00231     /* look for name/value delimiter */
00232     dbg_err_if((p = strchr(u_string_c(line), ':')) == NULL);
00233 
00234     /* alloc a new field */
00235     dbg_err_if(field_create(NULL, NULL, &f));
00236 
00237     /* parse and set name, value and params */
00238     dbg_err_if(field_set_from_line(f, u_string_c(line)));
00239 
00240     /* add to this header */
00241     dbg_err_if(header_add_field(h, f));
00242 
00243     return 0;
00244 err:
00245     if(f)
00246         field_free(f);
00247     return ~0;
00248 }
00249 
00250 /* load from environment. change each HTTP_name=value to name=value (replacing
00251    '_' with '-' */
00252 int header_load_from_cgienv(header_t *h)
00253 {
00254     extern char **environ;
00255     enum { BUFSZ = 256 };
00256     int i;
00257     size_t blen, t;
00258     char *e, *eq, buf[BUFSZ];
00259 
00260     /* add HTTP_* to header field list */
00261     for(i = 0; environ[i]; ++i)
00262     {
00263         e = environ[i];
00264         if(strlen(e) > 5 && strncmp("HTTP_", e, 5) == 0)
00265         {
00266             memset(buf, 0, sizeof(buf));
00267 
00268             /* make a copy of e so we can modify it */
00269             strncpy(buf, e + 5, MIN(BUFSZ, strlen(e + 5)));
00270             buf[BUFSZ-1] = 0;
00271 
00272             eq = strchr(buf, '=');
00273             if(eq == NULL)
00274                 continue; /* malformed */
00275 
00276             *eq = 0; /* put a \0 between name and value */
00277 
00278             /* subst '_' with '-' */
00279             for(t = 0, blen = strlen(buf); t < blen; ++t)
00280                 if(buf[t] == '_')
00281                     buf[t] = '-';
00282 
00283             dbg_if(header_set_field(h, buf, 1 + eq));
00284         }
00285     }
00286 
00287     return 0;
00288 err:
00289     return ~0;
00290 }
00291 
00292 int header_load(header_t *h , io_t *io)
00293 {
00294     enum { HEADER_MAX_FIELD_COUNT = 256 }; /* max num of header fields */
00295     u_string_t *line = NULL, *unfolded = NULL;
00296     const char *ln;
00297     size_t len, c;
00298 
00299     dbg_err_if (h == NULL);
00300     dbg_err_if (io == NULL);
00301 
00302     dbg_err_if(u_string_create(NULL, 0, &line));
00303     dbg_err_if(u_string_create(NULL, 0, &unfolded));
00304 
00305     for(c = HEADER_MAX_FIELD_COUNT; u_getline(io, line) == 0; --c)
00306     {
00307         warn_err_ifm(c == 0, "too much header fields");
00308 
00309         ln = u_string_c(line);
00310         len = u_string_len(line);
00311 
00312         /* remove trailing nl(s) */
00313         while(len && u_isnl(ln[len-1]))
00314             u_string_set_length(line, --len);
00315 
00316         if(u_string_len(line) == 0)
00317             break; /* empty line */
00318 
00319         if(u_isblank(ln[0])) 
00320         {   /* this is a chunk of a folded line */
00321             dbg_err_if(u_string_append(unfolded, ln, u_string_len(line)));
00322         } else {
00323             if(u_string_len(unfolded))
00324             {
00325                 /* go process this (already unfolded) line */
00326                 header_process_line(h, unfolded);
00327                 u_string_clear(unfolded);
00328             }
00329             /* this may be the first line of a folded line so wait next lines */
00330             u_string_copy(unfolded, line);
00331         }
00332     }
00333 
00334     if(u_string_len(unfolded))
00335         header_process_line(h, unfolded);
00336 
00337     u_string_free(unfolded);
00338     u_string_free(line);
00339 
00340     return 0;
00341 err:
00342     if(line)
00343         u_string_free(line);
00344     if(unfolded)
00345         u_string_free(unfolded);
00346     return ~0;
00347 }
00348 
00349 int header_create(header_t **ph)
00350 {
00351     header_t *h = NULL;
00352 
00353     dbg_err_if (ph == NULL);
00354 
00355     h = u_zalloc(sizeof(header_t));
00356     dbg_err_if(h == NULL);
00357 
00358     TAILQ_INIT(&h->fields);
00359 
00360     *ph = h;
00361 
00362     return 0;
00363 err:
00364     return ~0;
00365 }
00366 
00367 int header_free(header_t *h)
00368 {
00369     if (h)
00370     {
00371         (void) header_clear(h);
00372         U_FREE(h);
00373     }
00374 
00375     return 0;
00376 }
00377 

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved