📄 httpheader.c
字号:
httpHeaderReset(HttpHeader * hdr){ http_hdr_owner_type ho = hdr->owner; assert(hdr); ho = hdr->owner; httpHeaderClean(hdr); httpHeaderInit(hdr, ho); return 0;}inthttpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_end){ const char *field_start = header_start; HttpHeaderEntry *e; assert(hdr); assert(header_start && header_end); debug(55, 7) ("parsing hdr: (%p)\n%s\n", hdr, getStringPrefix(header_start, header_end)); HttpHeaderStats[hdr->owner].parsedCount++; /* commonn format headers are "<name>:[ws]<value>" lines delimited by <CRLF> */ while (field_start < header_end) { const char *field_end = field_start + strcspn(field_start, "\r\n"); if (!*field_end || field_end > header_end) return httpHeaderReset(hdr); /* missing <CRLF> */ e = httpHeaderEntryParseCreate(field_start, field_end); if (e != NULL) httpHeaderAddEntry(hdr, e); else debug(55, 2) ("warning: ignoring unparseable http header field near '%s'\n", getStringPrefix(field_start, field_end)); field_start = field_end; /* skip CRLF */ if (*field_start == '\r') field_start++; if (*field_start == '\n') field_start++; } return 1; /* even if no fields where found, it is a valid header */}/* packs all the entries using supplied packer */voidhttpHeaderPackInto(const HttpHeader * hdr, Packer * p){ HttpHeaderPos pos = HttpHeaderInitPos; const HttpHeaderEntry *e; assert(hdr && p); debug(55, 7) ("packing hdr: (%p)\n", hdr); /* pack all entries one by one */ while ((e = httpHeaderGetEntry(hdr, &pos))) httpHeaderEntryPackInto(e, p);}/* returns next valid entry */HttpHeaderEntry *httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos){ assert(hdr && pos); assert(*pos >= HttpHeaderInitPos && *pos < hdr->entries.count); for ((*pos)++; *pos < hdr->entries.count; (*pos)++) { if (hdr->entries.items[*pos]) return hdr->entries.items[*pos]; } return NULL;}/* * returns a pointer to a specified entry if any * note that we return one entry so it does not make much sense to ask for * "list" headers */HttpHeaderEntry *httpHeaderFindEntry(const HttpHeader * hdr, http_hdr_type id){ HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; assert(hdr); assert_eid(id); assert(!CBIT_TEST(ListHeadersMask, id)); /* check mask first */ if (!CBIT_TEST(hdr->mask, id)) return NULL; /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) return e; } /* hm.. we thought it was there, but it was not found */ assert(0); return NULL; /* not reached */}/* * same as httpHeaderFindEntry */static HttpHeaderEntry *httpHeaderFindLastEntry(const HttpHeader * hdr, http_hdr_type id){ HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; HttpHeaderEntry *result = NULL; assert(hdr); assert_eid(id); assert(!CBIT_TEST(ListHeadersMask, id)); /* check mask first */ if (!CBIT_TEST(hdr->mask, id)) return NULL; /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) result = e; } assert(result); /* must be there! */ return result;}/* * deletes all fields with a given name if any, returns #fields deleted; */inthttpHeaderDelByName(HttpHeader * hdr, const char *name){ int count = 0; HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; httpHeaderMaskInit(&hdr->mask, 0); /* temporal inconsistency */ debug(55, 7) ("deleting '%s' fields in hdr %p\n", name, hdr); while ((e = httpHeaderGetEntry(hdr, &pos))) { if (!strCaseCmp(e->name, name)) { httpHeaderDelAt(hdr, pos); count++; } else CBIT_SET(hdr->mask, e->id); } return count;}/* deletes all entries with a given id, returns the #entries deleted */inthttpHeaderDelById(HttpHeader * hdr, http_hdr_type id){ int count = 0; HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; debug(55, 8) ("%p del-by-id %d\n", hdr, id); assert(hdr); assert_eid(id); assert_eid(id != HDR_OTHER); /* does not make sense */ if (!CBIT_TEST(hdr->mask, id)) return 0; while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) { httpHeaderDelAt(hdr, pos); count++; } } CBIT_CLR(hdr->mask, id); assert(count); return count;}/* * deletes an entry at pos and leaves a gap; leaving a gap makes it * possible to iterate(search) and delete fields at the same time */voidhttpHeaderDelAt(HttpHeader * hdr, HttpHeaderPos pos){ HttpHeaderEntry *e; assert(pos >= HttpHeaderInitPos && pos < hdr->entries.count); e = hdr->entries.items[pos]; hdr->entries.items[pos] = NULL; /* decrement header length, allow for ": " and crlf */ hdr->len -= strLen(e->name) + 2 + strLen(e->value) + 2; assert(hdr->len >= 0); httpHeaderEntryDestroy(e);}/* appends an entry; * does not call httpHeaderEntryClone() so one should not reuse "*e" */voidhttpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e){ assert(hdr && e); assert_eid(e->id); debug(55, 7) ("%p adding entry: %d at %d\n", hdr, e->id, hdr->entries.count); if (CBIT_TEST(hdr->mask, e->id)) Headers[e->id].stat.repCount++; else CBIT_SET(hdr->mask, e->id); arrayAppend(&hdr->entries, e); /* increment header length, allow for ": " and crlf */ hdr->len += strLen(e->name) + 2 + strLen(e->value) + 2;}/* return a list of entries with the same id separated by ',' and ws */StringhttpHeaderGetList(const HttpHeader * hdr, http_hdr_type id){ String s = StringNull; HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; debug(55, 6) ("%p: joining for id %d\n", hdr, id); /* only fields from ListHeaders array can be "listed" */ assert(CBIT_TEST(ListHeadersMask, id)); if (!CBIT_TEST(hdr->mask, id)) return s; while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) strListAdd(&s, strBuf(e->value), ','); } /* * note: we might get an empty (len==0) string if there was an "empty" * header; we must not get a NULL string though. */ assert(strBuf(s)); /* temporary warning: remove it! @?@ @?@ @?@ */ if (!strLen(s)) debug(55, 3) ("empty list header: %s (%d)\n", strBuf(Headers[id].name), id); debug(55, 6) ("%p: joined for id %d: %s\n", hdr, id, strBuf(s)); return s;}/* test if a field is present */inthttpHeaderHas(const HttpHeader * hdr, http_hdr_type id){ assert(hdr); assert_eid(id); assert(id != HDR_OTHER); debug(55, 7) ("%p lookup for %d\n", hdr, id); return CBIT_TEST(hdr->mask, id);}voidhttpHeaderPutInt(HttpHeader * hdr, http_hdr_type id, int number){ assert_eid(id); assert(Headers[id].type == ftInt); /* must be of an appropriate type */ assert(number >= 0); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, xitoa(number)));}voidhttpHeaderPutTime(HttpHeader * hdr, http_hdr_type id, time_t time){ assert_eid(id); assert(Headers[id].type == ftDate_1123); /* must be of an appropriate type */ assert(time >= 0); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, mkrfc1123(time)));}voidhttpHeaderPutStr(HttpHeader * hdr, http_hdr_type id, const char *str){ assert_eid(id); assert(Headers[id].type == ftStr); /* must be of an appropriate type */ assert(str); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, str));}voidhttpHeaderPutAuth(HttpHeader * hdr, const char *authScheme, const char *realm){ assert(hdr && authScheme && realm); httpHeaderPutStrf(hdr, HDR_WWW_AUTHENTICATE, "%s realm=\"%s\"", authScheme, realm);}voidhttpHeaderPutCc(HttpHeader * hdr, const HttpHdrCc * cc){ MemBuf mb; Packer p; assert(hdr && cc); /* remove old directives if any */ httpHeaderDelById(hdr, HDR_CACHE_CONTROL); /* pack into mb */ memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHdrCcPackInto(cc, &p); /* put */ httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CACHE_CONTROL, NULL, mb.buf)); /* cleanup */ packerClean(&p); memBufClean(&mb);}voidhttpHeaderPutContRange(HttpHeader * hdr, const HttpHdrContRange * cr){ MemBuf mb; Packer p; assert(hdr && cr); /* remove old directives if any */ httpHeaderDelById(hdr, HDR_CONTENT_RANGE); /* pack into mb */ memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHdrContRangePackInto(cr, &p); /* put */ httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CONTENT_RANGE, NULL, mb.buf)); /* cleanup */ packerClean(&p); memBufClean(&mb);}voidhttpHeaderPutRange(HttpHeader * hdr, const HttpHdrRange * range){ MemBuf mb; Packer p; assert(hdr && range); /* remove old directives if any */ httpHeaderDelById(hdr, HDR_RANGE); /* pack into mb */ memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHdrRangePackInto(range, &p); /* put */ httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_RANGE, NULL, mb.buf)); /* cleanup */ packerClean(&p); memBufClean(&mb);}/* add extension header (these fields are not parsed/analyzed/joined, etc.) */voidhttpHeaderPutExt(HttpHeader * hdr, const char *name, const char *value){ assert(name && value); debug(55, 8) ("%p adds ext entry '%s: %s'\n", hdr, name, value); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_OTHER, name, value));}inthttpHeaderGetInt(const HttpHeader * hdr, http_hdr_type id){ HttpHeaderEntry *e; int value = -1; int ok; assert_eid(id); assert(Headers[id].type == ftInt); /* must be of an appropriate type */ if ((e = httpHeaderFindEntry(hdr, id))) { ok = httpHeaderParseInt(strBuf(e->value), &value); httpHeaderNoteParsedEntry(e->id, e->value, !ok); } return value;}time_thttpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id){ HttpHeaderEntry *e; time_t value = -1; assert_eid(id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -