static HttpHdrExtField * httpHdrExtFieldDoCreate(const char *name, int name_len, const char *value, int value_len) { HttpHdrExtField *f = xcalloc(1, sizeof(HttpHdrExtField)); stringLimitInit(&f->name, name, name_len); stringLimitInit(&f->value, value, value_len); return f; }
/* parses and inits header entry, returns new entry on success */ static HttpHeaderEntry * httpHeaderEntryParseCreate(const char *field_start, const char *field_end) { HttpHeaderEntry *e; int id; /* note: name_start == field_start */ const char *name_end = strchr(field_start, ':'); const int name_len = name_end ? name_end - field_start : 0; const char *value_start = field_start + name_len + 1; /* skip ':' */ /* note: value_end == field_end */ HeaderEntryParsedCount++; /* do we have a valid field name within this field? */ if (!name_len || name_end > field_end) return NULL; if (name_len > 65536) { /* String has a 64K limit */ debug(55, 1) ("WARNING: ignoring header name of %d bytes\n", name_len); return NULL; } /* now we know we can parse it */ e = memAllocate(MEM_HTTP_HDR_ENTRY); debug(55, 9) ("creating entry %p: near '%s'\n", e, getStringPrefix(field_start, field_end)); /* is it a "known" field? */ id = httpHeaderIdByName(field_start, name_len, Headers, HDR_ENUM_END); if (id < 0) id = HDR_OTHER; assert_eid(id); e->id = id; /* set field name */ if (id == HDR_OTHER) stringLimitInit(&e->name, field_start, name_len); else e->name = Headers[id].name; /* trim field value */ while (value_start < field_end && xisspace(*value_start)) value_start++; if (field_end - value_start > 65536) { /* String has a 64K limit */ debug(55, 1) ("WARNING: ignoring '%s' header of %d bytes\n", strBuf(e->name), (int) (field_end - value_start)); if (e->id == HDR_OTHER) stringClean(&e->name); memFree(e, MEM_HTTP_HDR_ENTRY); return NULL; } /* set field value */ stringLimitInit(&e->value, value_start, field_end - value_start); Headers[id].stat.seenCount++; Headers[id].stat.aliveCount++; debug(55, 9) ("created entry %p: '%s: %s'\n", e, strBuf(e->name), strBuf(e->value)); return e; }
/** * Parses a quoted-string field (RFC 2616 section 2.2), complains if * something went wrong, returns non-zero on success. * start should point at the first double-quote. * RC TODO: This is too looose. We should honour the BNF and exclude CTL's */ int httpHeaderParseQuotedString(const char *start, String * val) { const char *end, *pos; stringClean(val); if (*start != '"') { debug(66, 2) ("failed to parse a quoted-string header field near '%s'\n", start); return 0; } pos = start + 1; while (*pos != '"') { int quoted = (*pos == '\\'); if (quoted) pos++; if (!*pos) { debug(66, 2) ("failed to parse a quoted-string header field near '%s'\n", start); stringClean(val); return 0; } end = pos + strcspn(pos + quoted, "\"\\") + quoted; stringAppend(val, pos, end - pos); pos = end; } /* Make sure it's defined even if empty "" */ if (!val->buf) stringLimitInit(val, "", 0); return 1; }
static HttpHeaderEntry * httpHeaderEntryCreate2(http_hdr_type id, String name, String value) { HttpHeaderEntry *e; assert_eid(id); e = memAllocate(MEM_HTTP_HDR_ENTRY); e->id = id; if (id != HDR_OTHER) e->name = Headers[id].name; else stringLimitInit(&e->name, strBuf(name), strLen(name)); stringLimitInit(&e->value, strBuf(value), strLen(value)); Headers[id].stat.aliveCount++; debug(55, 9) ("created entry %p: '%s: %s'\n", e, strBuf(e->name), strBuf(e->value)); return e; }
/* return a string or list of entries with the same id separated by ',' and ws */ String httpHeaderGetStrOrList(const HttpHeader * hdr, http_hdr_type id) { HttpHeaderEntry *e; if (CBIT_TEST(ListHeadersMask, id)) return httpHeaderGetList(hdr, id); if ((e = httpHeaderFindEntry(hdr, id))) { String s; stringLimitInit(&s, strBuf(e->value), strLen(e->value)); return s; } return StringNull; }
/* sync this routine when you update HttpReply struct */ static void httpReplyHdrCacheInit(HttpReply * rep) { const HttpHeader *hdr = &rep->header; const char *str; rep->content_length = httpHeaderGetSize(hdr, HDR_CONTENT_LENGTH); rep->date = httpHeaderGetTime(hdr, HDR_DATE); rep->last_modified = httpHeaderGetTime(hdr, HDR_LAST_MODIFIED); str = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE); if (str) stringLimitInit(&rep->content_type, str, strcspn(str, ";\t ")); else rep->content_type = StringNull; rep->cache_control = httpHeaderGetCc(hdr); rep->content_range = httpHeaderGetContRange(hdr); rep->keep_alive = httpMsgIsPersistent(rep->sline.version, &rep->header); /* be sure to set expires after date and cache-control */ rep->expires = httpReplyHdrExpirationTime(rep); }
/* parses and inits header entry, returns new entry on success */ static HttpHeaderEntry * httpHeaderEntryParseCreate(const char *field_start, const char *field_end) { HttpHeaderEntry *e; int id; /* note: name_start == field_start */ const char *name_end = memchr(field_start, ':', field_end - field_start); int name_len = name_end ? name_end - field_start : 0; const char *value_start = field_start + name_len + 1; /* skip ':' */ /* note: value_end == field_end */ HeaderEntryParsedCount++; /* do we have a valid field name within this field? */ if (!name_len || name_end > field_end) return NULL; if (name_len > 65534) { /* String must be LESS THAN 64K and it adds a terminating NULL */ debug(55, 1) ("WARNING: ignoring header name of %d bytes\n", name_len); return NULL; } if (Config.onoff.relaxed_header_parser && xisspace(field_start[name_len - 1])) { debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("NOTICE: Whitespace after header name in '%s'\n", getStringPrefix(field_start, field_end)); while (name_len > 0 && xisspace(field_start[name_len - 1])) name_len--; if (!name_len) return NULL; } /* now we know we can parse it */ e = memAllocate(MEM_HTTP_HDR_ENTRY); debug(55, 9) ("creating entry %p: near '%s'\n", e, getStringPrefix(field_start, field_end)); /* is it a "known" field? */ id = httpHeaderIdByName(field_start, name_len, Headers, HDR_ENUM_END); if (id < 0) id = HDR_OTHER; assert_eid(id); e->id = id; /* set field name */ if (id == HDR_OTHER) stringLimitInit(&e->name, field_start, name_len); else e->name = Headers[id].name; /* trim field value */ while (value_start < field_end && xisspace(*value_start)) value_start++; while (value_start < field_end && xisspace(field_end[-1])) field_end--; if (field_end - value_start > 65534) { /* String must be LESS THAN 64K and it adds a terminating NULL */ debug(55, 1) ("WARNING: ignoring '%s' header of %d bytes\n", strBuf(e->name), (int) (field_end - value_start)); if (e->id == HDR_OTHER) stringClean(&e->name); memFree(e, MEM_HTTP_HDR_ENTRY); return NULL; } /* set field value */ stringLimitInit(&e->value, value_start, field_end - value_start); Headers[id].stat.seenCount++; Headers[id].stat.aliveCount++; debug(55, 9) ("created entry %p: '%s: %s'\n", e, strBuf(e->name), strBuf(e->value)); return e; }