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
00226 dbg_err_if (h == NULL);
00227 dbg_err_if (line == NULL);
00228
00229 if(!u_string_len(line))
00230 return 0;
00231
00232
00233 dbg_err_if(field_create(NULL, NULL, &f));
00234
00235
00236 dbg_err_if(field_set_from_line(f, u_string_c(line)));
00237
00238
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
00271
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
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
00289 u_strlcpy(buf, e + 5, sizeof buf);
00290
00291 eq = strchr(buf, '=');
00292 if(eq == NULL)
00293 continue;
00294
00295 *eq = 0;
00296
00297
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 };
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
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;
00335
00336 if(u_isblank(ln[0]))
00337 {
00338 dbg_err_if(u_string_append(unfolded, ln, u_string_len(line)));
00339 } else {
00340 if(u_string_len(unfolded))
00341 {
00342
00343 header_process_line(h, unfolded, mode);
00344 u_string_clear(unfolded);
00345 }
00346
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 }