header.c

00001 /*
00002  * Copyright (c) 2005-2012 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.20 2007/10/26 11:21:51 tho Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <u/libu.h>
00013 #include <klone/os.h>
00014 #include <klone/header.h>
00015 #include <klone/utils.h>
00016 
00029 int header_set_field(header_t *h, const char *name, const char *value)
00030 {
00031     field_t* n = NULL, *ex;
00032 
00033     dbg_err_if (h == NULL);
00034     dbg_err_if (name == NULL);
00035     dbg_err_if (value == NULL);
00036 
00037     /* modify existing field if already set */
00038     if((ex = header_get_field(h, name)) == NULL)
00039     {
00040         dbg_err_if(field_create(name, value, &n));
00041         dbg_err_if(header_add_field(h, n));
00042     } else
00043         dbg_err_if(field_set(ex, name, value));
00044 
00045     return 0;
00046 err:
00047     if(n)
00048         field_free(n);
00049     return ~0;
00050 }
00051 
00062 int header_clear(header_t *h)
00063 {
00064     field_t *f;
00065     
00066     dbg_return_if (h == NULL, ~0);
00067     
00068     /* free all items */
00069     while((f = TAILQ_FIRST(&h->fields)) != NULL)
00070     {
00071         header_del_field(h, f);
00072         field_free(f);
00073     }
00074 
00075     return 0;
00076 }
00077 
00088 size_t header_field_count(header_t *h)
00089 {
00090     dbg_return_if (h == NULL, 0);
00091 
00092     return h->nfields;
00093 }
00094 
00106 field_t *header_get_fieldn(header_t *h, size_t idx)
00107 {
00108     field_t *f;
00109     size_t i = 0;
00110 
00111     dbg_goto_if (h == NULL, notfound);
00112     nop_goto_if (idx >= h->nfields, notfound);
00113 
00114     TAILQ_FOREACH(f, &h->fields, np)
00115     {
00116         if(i == idx)
00117             return f;
00118         ++i;
00119     }
00120 
00121 notfound:
00122     return NULL;
00123 }
00124 
00138 field_t *header_get_field(header_t *h, const char *name)
00139 {
00140     field_t *f = NULL;
00141 
00142     dbg_goto_if (h == NULL, notfound);
00143     dbg_goto_if (name == NULL, notfound);
00144 
00145     TAILQ_FOREACH(f, &h->fields, np)
00146         if(strcasecmp(f->name, name) == 0)
00147             return f;
00148 
00149 notfound:
00150     return NULL;
00151 }
00152 
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 
00189 int header_del_field(header_t *h, field_t *f)
00190 {
00191     dbg_return_if (h == NULL, ~0);
00192     dbg_return_if (f == NULL, ~0);
00193 
00194     TAILQ_REMOVE(&h->fields, f, np);
00195     h->nfields--;
00196 
00197     return 0;
00198 }
00199 
00211 int header_add_field(header_t *h, field_t *f)
00212 {
00213     dbg_return_if (h == NULL, ~0);
00214     dbg_return_if (f == NULL, ~0);
00215 
00216     TAILQ_INSERT_TAIL(&h->fields, f, np);
00217     h->nfields++;
00218 
00219     return 0;
00220 }
00221 
00222 static int header_process_line(header_t *h, u_string_t *line, int mode)
00223 {
00224     field_t *ex, *f = NULL;
00225 
00226     dbg_err_if (h == NULL);
00227     dbg_err_if (line == NULL);
00228     
00229     if(!u_string_len(line))
00230         return 0;
00231 
00232     /* alloc a new field */
00233     dbg_err_if(field_create(NULL, NULL, &f));
00234 
00235     /* parse and set name, value and params */
00236     dbg_err_if(field_set_from_line(f, u_string_c(line)));
00237 
00238     /* add to this header */
00239     switch(mode)
00240     {
00241     case HLM_ADD:
00242         dbg_err_if(header_add_field(h, f));
00243         break;
00244     case HLM_OVERRIDE:
00245         if((ex = header_get_field(h, field_get_name(f))) != NULL)
00246         {
00247             header_del_field(h, ex);
00248             field_free(ex); ex = NULL;
00249         }
00250         dbg_err_if(header_add_field(h, f));
00251         break;
00252     case HLM_KEEP:
00253         if((ex = header_get_field(h, field_get_name(f))) == NULL)
00254             dbg_err_if(header_add_field(h, f));
00255         else {
00256             field_free(f); f = NULL;
00257         }
00258         break;
00259     default:
00260         crit_err("unknown header load mode");
00261     }
00262 
00263     return 0;
00264 err:
00265     if(f)
00266         field_free(f);
00267     return ~0;
00268 }
00269 
00270 /* load from environment. change each HTTP_name=value to name=value (replacing
00271    '_' with '-' */
00272 int header_load_from_cgienv(header_t *h)
00273 {
00274     extern char **environ;
00275     enum { BUFSZ = 256 };
00276     int i;
00277     size_t blen, t;
00278     char *e, *eq, buf[BUFSZ];
00279 
00280     /* add HTTP_* to header field list */
00281     for(i = 0; environ[i]; ++i)
00282     {
00283         e = environ[i];
00284         if(strlen(e) > 5 && strncmp("HTTP_", e, 5) == 0)
00285         {
00286             memset(buf, 0, sizeof(buf));
00287 
00288             /* make a copy of e so we can modify it */
00289             u_strlcpy(buf, e + 5, sizeof buf);
00290 
00291             eq = strchr(buf, '=');
00292             if(eq == NULL)
00293                 continue; /* malformed */
00294 
00295             *eq = 0; /* put a \0 between name and value */
00296 
00297             /* subst '_' with '-' */
00298             for(t = 0, blen = strlen(buf); t < blen; ++t)
00299                 if(buf[t] == '_')
00300                     buf[t] = '-';
00301 
00302             dbg_if(header_set_field(h, buf, 1 + eq));
00303         }
00304     }
00305 
00306     return 0;
00307 }
00308 
00309 int header_load_ex(header_t *h , io_t *io, int mode)
00310 {
00311     enum { HEADER_MAX_FIELD_COUNT = 256 }; /* max num of header fields */
00312     u_string_t *line = NULL, *unfolded = NULL;
00313     const char *ln;
00314     size_t len, c;
00315 
00316     dbg_err_if (h == NULL);
00317     dbg_err_if (io == NULL);
00318 
00319     dbg_err_if(u_string_create(NULL, 0, &line));
00320     dbg_err_if(u_string_create(NULL, 0, &unfolded));
00321 
00322     for(c = HEADER_MAX_FIELD_COUNT; u_getline(io, line) == 0; --c)
00323     {
00324         warn_err_ifm(c == 0, "too much header fields");
00325 
00326         ln = u_string_c(line);
00327         len = u_string_len(line);
00328 
00329         /* remove trailing nl(s) */
00330         while(len && u_isnl(ln[len-1]))
00331             u_string_set_length(line, --len);
00332 
00333         if(u_string_len(line) == 0)
00334             break; /* empty line */
00335 
00336         if(u_isblank(ln[0])) 
00337         {   /* this is a chunk of a folded line */
00338             dbg_err_if(u_string_append(unfolded, ln, u_string_len(line)));
00339         } else {
00340             if(u_string_len(unfolded))
00341             {
00342                 /* go process this (already unfolded) line */
00343                 header_process_line(h, unfolded, mode);
00344                 u_string_clear(unfolded);
00345             }
00346             /* this may be the first line of a folded line so wait next lines */
00347             u_string_copy(unfolded, line);
00348         }
00349     }
00350 
00351     if(u_string_len(unfolded))
00352         header_process_line(h, unfolded, mode);
00353 
00354     u_string_free(unfolded);
00355     u_string_free(line);
00356 
00357     return 0;
00358 err:
00359     if(line)
00360         u_string_free(line);
00361     if(unfolded)
00362         u_string_free(unfolded);
00363     return ~0;
00364 }
00365 
00366 int header_load(header_t *h , io_t *io)
00367 {
00368     return header_load_ex(h, io, HLM_ADD);
00369 }
00370 
00371 int header_create(header_t **ph)
00372 {
00373     header_t *h = NULL;
00374 
00375     dbg_err_if (ph == NULL);
00376 
00377     h = u_zalloc(sizeof(header_t));
00378     dbg_err_if(h == NULL);
00379 
00380     TAILQ_INIT(&h->fields);
00381 
00382     *ph = h;
00383 
00384     return 0;
00385 err:
00386     return ~0;
00387 }
00388 
00389 int header_free(header_t *h)
00390 {
00391     if (h)
00392     {
00393         (void) header_clear(h);
00394         U_FREE(h);
00395     }
00396 
00397     return 0;
00398 }

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