void http_Merge(const struct http *fm, struct http *to, int not_ce) { unsigned u, v; const char *p; to->status = fm->status; http_linkh(to, fm, HTTP_HDR_PROTO); http_linkh(to, fm, HTTP_HDR_STATUS); http_linkh(to, fm, HTTP_HDR_REASON); for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) fm->hdf[u] |= HDF_MARKER; if (not_ce) { u = http_findhdr(fm, H_Content_Encoding[0] - 1, H_Content_Encoding + 1); if (u > 0) fm->hdf[u] &= ~HDF_MARKER; } for (v = HTTP_HDR_FIRST; v < to->nhd; v++) { p = strchr(to->hd[v].b, ':'); AN(p); u = http_findhdr(fm, p - to->hd[v].b, to->hd[v].b); if (u) fm->hdf[u] &= ~HDF_MARKER; } for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) if (fm->hdf[u] & HDF_MARKER) http_SetHeader(to, fm->hd[u].b); }
enum sess_close http_DoConnection(const struct http *hp) { char *p, *q; enum sess_close ret; unsigned u; if (!http_GetHdr(hp, H_Connection, &p)) { if (hp->protover < 11) return (SC_REQ_HTTP10); return (SC_NULL); } ret = SC_NULL; AN(p); for (; *p; p++) { if (vct_issp(*p)) continue; if (*p == ',') continue; for (q = p + 1; *q; q++) if (*q == ',' || vct_issp(*q)) break; u = pdiff(p, q); if (u == 5 && !strncasecmp(p, "close", u)) ret = SC_REQ_CLOSE; u = http_findhdr(hp, u, p); if (u != 0) hp->hdf[u] |= HDF_FILTER; if (!*q) break; p = q; } return (ret); }
int http_GetHdr(const struct http *hp, const char *hdr, char **ptr) { unsigned u, l; char *p; l = hdr[0]; assert(l == strlen(hdr + 1)); assert(hdr[l] == ':'); hdr++; u = http_findhdr(hp, l - 1, hdr); if (u == 0) { if (ptr != NULL) *ptr = NULL; return (0); } if (ptr != NULL) { p = hp->hd[u].b + l; while (vct_issp(*p)) p++; *ptr = p; } return (1); }
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); }