00001
00002
00003
00004
00005
00006
00007
00008
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
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
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 const char *p;
00226
00227 dbg_err_if (h == NULL);
00228 dbg_err_if (line == NULL);
00229
00230 if(!u_string_len(line))
00231 return 0;
00232
00233
00234 dbg_err_if(field_create(NULL, NULL, &f));
00235
00236
00237 dbg_err_if(field_set_from_line(f, u_string_c(line)));
00238
00239
00240 switch(mode)
00241 {
00242 case HLM_ADD:
00243 dbg_err_if(header_add_field(h, f));
00244 break;
00245 case HLM_OVERRIDE:
00246 if((ex = header_get_field(h, field_get_name(f))) != NULL)
00247 {
00248 header_del_field(h, ex);
00249 field_free(ex); ex = NULL;
00250 }
00251 dbg_err_if(header_add_field(h, f));
00252 break;
00253 case HLM_KEEP:
00254 if((ex = header_get_field(h, field_get_name(f))) == NULL)
00255 dbg_err_if(header_add_field(h, f));
00256 else {
00257 field_free(f); f = NULL;
00258 }
00259 break;
00260 default:
00261 crit_err("unknown header load mode");
00262 }
00263
00264 return 0;
00265 err:
00266 if(f)
00267 field_free(f);
00268 return ~0;
00269 }
00270
00271
00272
00273 int header_load_from_cgienv(header_t *h)
00274 {
00275 extern char **environ;
00276 enum { BUFSZ = 256 };
00277 int i;
00278 size_t blen, t;
00279 char *e, *eq, buf[BUFSZ];
00280
00281
00282 for(i = 0; environ[i]; ++i)
00283 {
00284 e = environ[i];
00285 if(strlen(e) > 5 && strncmp("HTTP_", e, 5) == 0)
00286 {
00287 memset(buf, 0, sizeof(buf));
00288
00289
00290 strncpy(buf, e + 5, MIN(BUFSZ, strlen(e + 5)));
00291 buf[BUFSZ-1] = 0;
00292
00293 eq = strchr(buf, '=');
00294 if(eq == NULL)
00295 continue;
00296
00297 *eq = 0;
00298
00299
00300 for(t = 0, blen = strlen(buf); t < blen; ++t)
00301 if(buf[t] == '_')
00302 buf[t] = '-';
00303
00304 dbg_if(header_set_field(h, buf, 1 + eq));
00305 }
00306 }
00307
00308 return 0;
00309 err:
00310 return ~0;
00311 }
00312
00313 int header_load_ex(header_t *h , io_t *io, int mode)
00314 {
00315 enum { HEADER_MAX_FIELD_COUNT = 256 };
00316 u_string_t *line = NULL, *unfolded = NULL;
00317 const char *ln;
00318 size_t len, c;
00319
00320 dbg_err_if (h == NULL);
00321 dbg_err_if (io == NULL);
00322
00323 dbg_err_if(u_string_create(NULL, 0, &line));
00324 dbg_err_if(u_string_create(NULL, 0, &unfolded));
00325
00326 for(c = HEADER_MAX_FIELD_COUNT; u_getline(io, line) == 0; --c)
00327 {
00328 warn_err_ifm(c == 0, "too much header fields");
00329
00330 ln = u_string_c(line);
00331 len = u_string_len(line);
00332
00333
00334 while(len && u_isnl(ln[len-1]))
00335 u_string_set_length(line, --len);
00336
00337 if(u_string_len(line) == 0)
00338 break;
00339
00340 if(u_isblank(ln[0]))
00341 {
00342 dbg_err_if(u_string_append(unfolded, ln, u_string_len(line)));
00343 } else {
00344 if(u_string_len(unfolded))
00345 {
00346
00347 header_process_line(h, unfolded, mode);
00348 u_string_clear(unfolded);
00349 }
00350
00351 u_string_copy(unfolded, line);
00352 }
00353 }
00354
00355 if(u_string_len(unfolded))
00356 header_process_line(h, unfolded, mode);
00357
00358 u_string_free(unfolded);
00359 u_string_free(line);
00360
00361 return 0;
00362 err:
00363 if(line)
00364 u_string_free(line);
00365 if(unfolded)
00366 u_string_free(unfolded);
00367 return ~0;
00368 }
00369
00370 int header_load(header_t *h , io_t *io)
00371 {
00372 return header_load_ex(h, io, HLM_ADD);
00373 }
00374
00375 int header_create(header_t **ph)
00376 {
00377 header_t *h = NULL;
00378
00379 dbg_err_if (ph == NULL);
00380
00381 h = u_zalloc(sizeof(header_t));
00382 dbg_err_if(h == NULL);
00383
00384 TAILQ_INIT(&h->fields);
00385
00386 *ph = h;
00387
00388 return 0;
00389 err:
00390 return ~0;
00391 }
00392
00393 int header_free(header_t *h)
00394 {
00395 if (h)
00396 {
00397 (void) header_clear(h);
00398 U_FREE(h);
00399 }
00400
00401 return 0;
00402 }