void http_CollectHdr(struct http *hp, const char *hdr) { unsigned u, v, ml, f = 0, x; char *b = NULL, *e = NULL; for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { while (u < hp->nhd && http_IsHdr(&hp->hd[u], hdr)) { Tcheck(hp->hd[u]); if (f == 0) { /* Found first header, just record the fact */ f = u; break; } if (b == NULL) { /* Found second header, start our collection */ ml = WS_Reserve(hp->ws, 0); b = hp->ws->f; e = b + ml; x = Tlen(hp->hd[f]); if (b + x < e) { memcpy(b, hp->hd[f].b, x); b += x; } else b = e; } AN(b); AN(e); /* Append the Nth header we found */ if (b < e) *b++ = ','; x = Tlen(hp->hd[u]) - *hdr; if (b + x < e) { memcpy(b, hp->hd[u].b + *hdr, x); b += x; } else b = e; /* Shift remaining headers up one slot */ for (v = u; v < hp->nhd - 1; v++) hp->hd[v] = hp->hd[v + 1]; hp->nhd--; } } if (b == NULL) return; AN(e); if (b >= e) { WS_Release(hp->ws, 0); return; } *b = '\0'; hp->hd[f].b = hp->ws->f; hp->hd[f].e = b; WS_ReleaseP(hp->ws, b + 1); }
void http_Unset(struct http *hp, const char *hdr) { uint16_t u, v; for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) { if (hp->hd[u].b == NULL) continue; if (http_IsHdr(&hp->hd[u], hdr)) continue; if (v != u) { memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd); memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf); } v++; } hp->nhd = v; }
static uint16_t htc_request_check_host_hdr(const struct http *hp) { int u; int seen_host = 0; for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { if (hp->hd[u].b == NULL) continue; AN(hp->hd[u].b); AN(hp->hd[u].e); if (http_IsHdr(&hp->hd[u], H_Host)) { if (seen_host) { VSLb(hp->vsl, SLT_Error, "Duplicated Host header"); return (400); } seen_host = 1; } } return (0); }
void http_CollectHdr(struct http *hp, const char *hdr) { unsigned u, l, ml, f, x, d; char *b = NULL, *e = NULL; CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); if (WS_Overflowed(hp->ws)) return; l = hdr[0]; assert(l == strlen(hdr + 1)); assert(hdr[l] == ':'); f = http_findhdr(hp, l - 1, hdr + 1); if (f == 0) return; for (d = u = f + 1; u < hp->nhd; u++) { Tcheck(hp->hd[u]); if (!http_IsHdr(&hp->hd[u], hdr)) { if (d != u) { hp->hd[d] = hp->hd[u]; hp->hdf[d] = hp->hdf[u]; } d++; continue; } if (b == NULL) { /* Found second header, start our collection */ ml = WS_Reserve(hp->ws, 0); b = hp->ws->f; e = b + ml; x = Tlen(hp->hd[f]); if (b + x >= e) { http_fail(hp); VSLb(hp->vsl, SLT_LostHeader, "%s", hdr + 1); WS_Release(hp->ws, 0); return; } memcpy(b, hp->hd[f].b, x); b += x; } AN(b); AN(e); /* Append the Nth header we found */ if (b < e) *b++ = ','; x = Tlen(hp->hd[u]) - l; if (b + x >= e) { http_fail(hp); VSLb(hp->vsl, SLT_LostHeader, "%s", hdr + 1); WS_Release(hp->ws, 0); return; } memcpy(b, hp->hd[u].b + *hdr, x); b += x; } if (b == NULL) return; hp->nhd = (uint16_t)d; AN(e); *b = '\0'; hp->hd[f].b = hp->ws->f; hp->hd[f].e = b; WS_ReleaseP(hp->ws, b + 1); }