00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
00232 dbg_err_if((p = strchr(u_string_c(line), ':')) == NULL);
00233
00234
00235 dbg_err_if(field_create(NULL, NULL, &f));
00236
00237
00238 dbg_err_if(field_set_from_line(f, u_string_c(line)));
00239
00240
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
00251
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
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
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;
00275
00276 *eq = 0;
00277
00278
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 };
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
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;
00318
00319 if(u_isblank(ln[0]))
00320 {
00321 dbg_err_if(u_string_append(unfolded, ln, u_string_len(line)));
00322 } else {
00323 if(u_string_len(unfolded))
00324 {
00325
00326 header_process_line(h, unfolded);
00327 u_string_clear(unfolded);
00328 }
00329
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