1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker
27*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
28*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
29*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
30*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
31*6236dae4SAndroid Build Coastguard Worker #include "headers.h"
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
34*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
35*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
36*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
37*6236dae4SAndroid Build Coastguard Worker
38*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
39*6236dae4SAndroid Build Coastguard Worker
40*6236dae4SAndroid Build Coastguard Worker /* Generate the curl_header struct for the user. This function MUST assign all
41*6236dae4SAndroid Build Coastguard Worker struct fields in the output struct. */
copy_header_external(struct Curl_header_store * hs,size_t index,size_t amount,struct Curl_llist_node * e,struct curl_header * hout)42*6236dae4SAndroid Build Coastguard Worker static void copy_header_external(struct Curl_header_store *hs,
43*6236dae4SAndroid Build Coastguard Worker size_t index,
44*6236dae4SAndroid Build Coastguard Worker size_t amount,
45*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e,
46*6236dae4SAndroid Build Coastguard Worker struct curl_header *hout)
47*6236dae4SAndroid Build Coastguard Worker {
48*6236dae4SAndroid Build Coastguard Worker struct curl_header *h = hout;
49*6236dae4SAndroid Build Coastguard Worker h->name = hs->name;
50*6236dae4SAndroid Build Coastguard Worker h->value = hs->value;
51*6236dae4SAndroid Build Coastguard Worker h->amount = amount;
52*6236dae4SAndroid Build Coastguard Worker h->index = index;
53*6236dae4SAndroid Build Coastguard Worker /* this will randomly OR a reserved bit for the sole purpose of making it
54*6236dae4SAndroid Build Coastguard Worker impossible for applications to do == comparisons, as that would otherwise
55*6236dae4SAndroid Build Coastguard Worker be very tempting and then lead to the reserved bits not being reserved
56*6236dae4SAndroid Build Coastguard Worker anymore. */
57*6236dae4SAndroid Build Coastguard Worker h->origin = (unsigned int)(hs->type | (1 << 27));
58*6236dae4SAndroid Build Coastguard Worker h->anchor = e;
59*6236dae4SAndroid Build Coastguard Worker }
60*6236dae4SAndroid Build Coastguard Worker
61*6236dae4SAndroid Build Coastguard Worker /* public API */
curl_easy_header(CURL * easy,const char * name,size_t nameindex,unsigned int type,int request,struct curl_header ** hout)62*6236dae4SAndroid Build Coastguard Worker CURLHcode curl_easy_header(CURL *easy,
63*6236dae4SAndroid Build Coastguard Worker const char *name,
64*6236dae4SAndroid Build Coastguard Worker size_t nameindex,
65*6236dae4SAndroid Build Coastguard Worker unsigned int type,
66*6236dae4SAndroid Build Coastguard Worker int request,
67*6236dae4SAndroid Build Coastguard Worker struct curl_header **hout)
68*6236dae4SAndroid Build Coastguard Worker {
69*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
70*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e_pick = NULL;
71*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = easy;
72*6236dae4SAndroid Build Coastguard Worker size_t match = 0;
73*6236dae4SAndroid Build Coastguard Worker size_t amount = 0;
74*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *hs = NULL;
75*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *pick = NULL;
76*6236dae4SAndroid Build Coastguard Worker if(!name || !hout || !data ||
77*6236dae4SAndroid Build Coastguard Worker (type > (CURLH_HEADER|CURLH_TRAILER|CURLH_CONNECT|CURLH_1XX|
78*6236dae4SAndroid Build Coastguard Worker CURLH_PSEUDO)) || !type || (request < -1))
79*6236dae4SAndroid Build Coastguard Worker return CURLHE_BAD_ARGUMENT;
80*6236dae4SAndroid Build Coastguard Worker if(!Curl_llist_count(&data->state.httphdrs))
81*6236dae4SAndroid Build Coastguard Worker return CURLHE_NOHEADERS; /* no headers available */
82*6236dae4SAndroid Build Coastguard Worker if(request > data->state.requests)
83*6236dae4SAndroid Build Coastguard Worker return CURLHE_NOREQUEST;
84*6236dae4SAndroid Build Coastguard Worker if(request == -1)
85*6236dae4SAndroid Build Coastguard Worker request = data->state.requests;
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard Worker /* we need a first round to count amount of this header */
88*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
89*6236dae4SAndroid Build Coastguard Worker hs = Curl_node_elem(e);
90*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(hs->name, name) &&
91*6236dae4SAndroid Build Coastguard Worker (hs->type & type) &&
92*6236dae4SAndroid Build Coastguard Worker (hs->request == request)) {
93*6236dae4SAndroid Build Coastguard Worker amount++;
94*6236dae4SAndroid Build Coastguard Worker pick = hs;
95*6236dae4SAndroid Build Coastguard Worker e_pick = e;
96*6236dae4SAndroid Build Coastguard Worker }
97*6236dae4SAndroid Build Coastguard Worker }
98*6236dae4SAndroid Build Coastguard Worker if(!amount)
99*6236dae4SAndroid Build Coastguard Worker return CURLHE_MISSING;
100*6236dae4SAndroid Build Coastguard Worker else if(nameindex >= amount)
101*6236dae4SAndroid Build Coastguard Worker return CURLHE_BADINDEX;
102*6236dae4SAndroid Build Coastguard Worker
103*6236dae4SAndroid Build Coastguard Worker if(nameindex == amount - 1)
104*6236dae4SAndroid Build Coastguard Worker /* if the last or only occurrence is what's asked for, then we know it */
105*6236dae4SAndroid Build Coastguard Worker hs = pick;
106*6236dae4SAndroid Build Coastguard Worker else {
107*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
108*6236dae4SAndroid Build Coastguard Worker hs = Curl_node_elem(e);
109*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(hs->name, name) &&
110*6236dae4SAndroid Build Coastguard Worker (hs->type & type) &&
111*6236dae4SAndroid Build Coastguard Worker (hs->request == request) &&
112*6236dae4SAndroid Build Coastguard Worker (match++ == nameindex)) {
113*6236dae4SAndroid Build Coastguard Worker e_pick = e;
114*6236dae4SAndroid Build Coastguard Worker break;
115*6236dae4SAndroid Build Coastguard Worker }
116*6236dae4SAndroid Build Coastguard Worker }
117*6236dae4SAndroid Build Coastguard Worker if(!e) /* this should not happen */
118*6236dae4SAndroid Build Coastguard Worker return CURLHE_MISSING;
119*6236dae4SAndroid Build Coastguard Worker }
120*6236dae4SAndroid Build Coastguard Worker /* this is the name we want */
121*6236dae4SAndroid Build Coastguard Worker copy_header_external(hs, nameindex, amount, e_pick,
122*6236dae4SAndroid Build Coastguard Worker &data->state.headerout[0]);
123*6236dae4SAndroid Build Coastguard Worker *hout = &data->state.headerout[0];
124*6236dae4SAndroid Build Coastguard Worker return CURLHE_OK;
125*6236dae4SAndroid Build Coastguard Worker }
126*6236dae4SAndroid Build Coastguard Worker
127*6236dae4SAndroid Build Coastguard Worker /* public API */
curl_easy_nextheader(CURL * easy,unsigned int type,int request,struct curl_header * prev)128*6236dae4SAndroid Build Coastguard Worker struct curl_header *curl_easy_nextheader(CURL *easy,
129*6236dae4SAndroid Build Coastguard Worker unsigned int type,
130*6236dae4SAndroid Build Coastguard Worker int request,
131*6236dae4SAndroid Build Coastguard Worker struct curl_header *prev)
132*6236dae4SAndroid Build Coastguard Worker {
133*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = easy;
134*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *pick;
135*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
136*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *hs;
137*6236dae4SAndroid Build Coastguard Worker size_t amount = 0;
138*6236dae4SAndroid Build Coastguard Worker size_t index = 0;
139*6236dae4SAndroid Build Coastguard Worker
140*6236dae4SAndroid Build Coastguard Worker if(request > data->state.requests)
141*6236dae4SAndroid Build Coastguard Worker return NULL;
142*6236dae4SAndroid Build Coastguard Worker if(request == -1)
143*6236dae4SAndroid Build Coastguard Worker request = data->state.requests;
144*6236dae4SAndroid Build Coastguard Worker
145*6236dae4SAndroid Build Coastguard Worker if(prev) {
146*6236dae4SAndroid Build Coastguard Worker pick = prev->anchor;
147*6236dae4SAndroid Build Coastguard Worker if(!pick)
148*6236dae4SAndroid Build Coastguard Worker /* something is wrong */
149*6236dae4SAndroid Build Coastguard Worker return NULL;
150*6236dae4SAndroid Build Coastguard Worker pick = Curl_node_next(pick);
151*6236dae4SAndroid Build Coastguard Worker }
152*6236dae4SAndroid Build Coastguard Worker else
153*6236dae4SAndroid Build Coastguard Worker pick = Curl_llist_head(&data->state.httphdrs);
154*6236dae4SAndroid Build Coastguard Worker
155*6236dae4SAndroid Build Coastguard Worker if(pick) {
156*6236dae4SAndroid Build Coastguard Worker /* make sure it is the next header of the desired type */
157*6236dae4SAndroid Build Coastguard Worker do {
158*6236dae4SAndroid Build Coastguard Worker hs = Curl_node_elem(pick);
159*6236dae4SAndroid Build Coastguard Worker if((hs->type & type) && (hs->request == request))
160*6236dae4SAndroid Build Coastguard Worker break;
161*6236dae4SAndroid Build Coastguard Worker pick = Curl_node_next(pick);
162*6236dae4SAndroid Build Coastguard Worker } while(pick);
163*6236dae4SAndroid Build Coastguard Worker }
164*6236dae4SAndroid Build Coastguard Worker
165*6236dae4SAndroid Build Coastguard Worker if(!pick)
166*6236dae4SAndroid Build Coastguard Worker /* no more headers available */
167*6236dae4SAndroid Build Coastguard Worker return NULL;
168*6236dae4SAndroid Build Coastguard Worker
169*6236dae4SAndroid Build Coastguard Worker hs = Curl_node_elem(pick);
170*6236dae4SAndroid Build Coastguard Worker
171*6236dae4SAndroid Build Coastguard Worker /* count number of occurrences of this name within the mask and figure out
172*6236dae4SAndroid Build Coastguard Worker the index for the currently selected entry */
173*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
174*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *check = Curl_node_elem(e);
175*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(hs->name, check->name) &&
176*6236dae4SAndroid Build Coastguard Worker (check->request == request) &&
177*6236dae4SAndroid Build Coastguard Worker (check->type & type))
178*6236dae4SAndroid Build Coastguard Worker amount++;
179*6236dae4SAndroid Build Coastguard Worker if(e == pick)
180*6236dae4SAndroid Build Coastguard Worker index = amount - 1;
181*6236dae4SAndroid Build Coastguard Worker }
182*6236dae4SAndroid Build Coastguard Worker
183*6236dae4SAndroid Build Coastguard Worker copy_header_external(hs, index, amount, pick,
184*6236dae4SAndroid Build Coastguard Worker &data->state.headerout[1]);
185*6236dae4SAndroid Build Coastguard Worker return &data->state.headerout[1];
186*6236dae4SAndroid Build Coastguard Worker }
187*6236dae4SAndroid Build Coastguard Worker
namevalue(char * header,size_t hlen,unsigned int type,char ** name,char ** value)188*6236dae4SAndroid Build Coastguard Worker static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
189*6236dae4SAndroid Build Coastguard Worker char **name, char **value)
190*6236dae4SAndroid Build Coastguard Worker {
191*6236dae4SAndroid Build Coastguard Worker char *end = header + hlen - 1; /* point to the last byte */
192*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(hlen);
193*6236dae4SAndroid Build Coastguard Worker *name = header;
194*6236dae4SAndroid Build Coastguard Worker
195*6236dae4SAndroid Build Coastguard Worker if(type == CURLH_PSEUDO) {
196*6236dae4SAndroid Build Coastguard Worker if(*header != ':')
197*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
198*6236dae4SAndroid Build Coastguard Worker header++;
199*6236dae4SAndroid Build Coastguard Worker }
200*6236dae4SAndroid Build Coastguard Worker
201*6236dae4SAndroid Build Coastguard Worker /* Find the end of the header name */
202*6236dae4SAndroid Build Coastguard Worker while(*header && (*header != ':'))
203*6236dae4SAndroid Build Coastguard Worker ++header;
204*6236dae4SAndroid Build Coastguard Worker
205*6236dae4SAndroid Build Coastguard Worker if(*header)
206*6236dae4SAndroid Build Coastguard Worker /* Skip over colon, null it */
207*6236dae4SAndroid Build Coastguard Worker *header++ = 0;
208*6236dae4SAndroid Build Coastguard Worker else
209*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
210*6236dae4SAndroid Build Coastguard Worker
211*6236dae4SAndroid Build Coastguard Worker /* skip all leading space letters */
212*6236dae4SAndroid Build Coastguard Worker while(*header && ISBLANK(*header))
213*6236dae4SAndroid Build Coastguard Worker header++;
214*6236dae4SAndroid Build Coastguard Worker
215*6236dae4SAndroid Build Coastguard Worker *value = header;
216*6236dae4SAndroid Build Coastguard Worker
217*6236dae4SAndroid Build Coastguard Worker /* skip all trailing space letters */
218*6236dae4SAndroid Build Coastguard Worker while((end > header) && ISSPACE(*end))
219*6236dae4SAndroid Build Coastguard Worker *end-- = 0; /* nul terminate */
220*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
221*6236dae4SAndroid Build Coastguard Worker }
222*6236dae4SAndroid Build Coastguard Worker
unfold_value(struct Curl_easy * data,const char * value,size_t vlen)223*6236dae4SAndroid Build Coastguard Worker static CURLcode unfold_value(struct Curl_easy *data, const char *value,
224*6236dae4SAndroid Build Coastguard Worker size_t vlen) /* length of the incoming header */
225*6236dae4SAndroid Build Coastguard Worker {
226*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *hs;
227*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *newhs;
228*6236dae4SAndroid Build Coastguard Worker size_t olen; /* length of the old value */
229*6236dae4SAndroid Build Coastguard Worker size_t oalloc; /* length of the old name + value + separator */
230*6236dae4SAndroid Build Coastguard Worker size_t offset;
231*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->state.prevhead);
232*6236dae4SAndroid Build Coastguard Worker hs = data->state.prevhead;
233*6236dae4SAndroid Build Coastguard Worker olen = strlen(hs->value);
234*6236dae4SAndroid Build Coastguard Worker offset = hs->value - hs->buffer;
235*6236dae4SAndroid Build Coastguard Worker oalloc = olen + offset + 1;
236*6236dae4SAndroid Build Coastguard Worker
237*6236dae4SAndroid Build Coastguard Worker /* skip all trailing space letters */
238*6236dae4SAndroid Build Coastguard Worker while(vlen && ISSPACE(value[vlen - 1]))
239*6236dae4SAndroid Build Coastguard Worker vlen--;
240*6236dae4SAndroid Build Coastguard Worker
241*6236dae4SAndroid Build Coastguard Worker /* save only one leading space */
242*6236dae4SAndroid Build Coastguard Worker while((vlen > 1) && ISBLANK(value[0]) && ISBLANK(value[1])) {
243*6236dae4SAndroid Build Coastguard Worker vlen--;
244*6236dae4SAndroid Build Coastguard Worker value++;
245*6236dae4SAndroid Build Coastguard Worker }
246*6236dae4SAndroid Build Coastguard Worker
247*6236dae4SAndroid Build Coastguard Worker /* since this header block might move in the realloc below, it needs to
248*6236dae4SAndroid Build Coastguard Worker first be unlinked from the list and then re-added again after the
249*6236dae4SAndroid Build Coastguard Worker realloc */
250*6236dae4SAndroid Build Coastguard Worker Curl_node_remove(&hs->node);
251*6236dae4SAndroid Build Coastguard Worker
252*6236dae4SAndroid Build Coastguard Worker /* new size = struct + new value length + old name+value length */
253*6236dae4SAndroid Build Coastguard Worker newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + oalloc + 1);
254*6236dae4SAndroid Build Coastguard Worker if(!newhs)
255*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
256*6236dae4SAndroid Build Coastguard Worker /* ->name and ->value point into ->buffer (to keep the header allocation
257*6236dae4SAndroid Build Coastguard Worker in a single memory block), which now potentially have moved. Adjust
258*6236dae4SAndroid Build Coastguard Worker them. */
259*6236dae4SAndroid Build Coastguard Worker newhs->name = newhs->buffer;
260*6236dae4SAndroid Build Coastguard Worker newhs->value = &newhs->buffer[offset];
261*6236dae4SAndroid Build Coastguard Worker
262*6236dae4SAndroid Build Coastguard Worker /* put the data at the end of the previous data, not the newline */
263*6236dae4SAndroid Build Coastguard Worker memcpy(&newhs->value[olen], value, vlen);
264*6236dae4SAndroid Build Coastguard Worker newhs->value[olen + vlen] = 0; /* null-terminate at newline */
265*6236dae4SAndroid Build Coastguard Worker
266*6236dae4SAndroid Build Coastguard Worker /* insert this node into the list of headers */
267*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&data->state.httphdrs, newhs, &newhs->node);
268*6236dae4SAndroid Build Coastguard Worker data->state.prevhead = newhs;
269*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
270*6236dae4SAndroid Build Coastguard Worker }
271*6236dae4SAndroid Build Coastguard Worker
272*6236dae4SAndroid Build Coastguard Worker
273*6236dae4SAndroid Build Coastguard Worker /*
274*6236dae4SAndroid Build Coastguard Worker * Curl_headers_push() gets passed a full HTTP header to store. It gets called
275*6236dae4SAndroid Build Coastguard Worker * immediately before the header callback. The header is CRLF terminated.
276*6236dae4SAndroid Build Coastguard Worker */
Curl_headers_push(struct Curl_easy * data,const char * header,unsigned char type)277*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
278*6236dae4SAndroid Build Coastguard Worker unsigned char type)
279*6236dae4SAndroid Build Coastguard Worker {
280*6236dae4SAndroid Build Coastguard Worker char *value = NULL;
281*6236dae4SAndroid Build Coastguard Worker char *name = NULL;
282*6236dae4SAndroid Build Coastguard Worker char *end;
283*6236dae4SAndroid Build Coastguard Worker size_t hlen; /* length of the incoming header */
284*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *hs;
285*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OUT_OF_MEMORY;
286*6236dae4SAndroid Build Coastguard Worker
287*6236dae4SAndroid Build Coastguard Worker if((header[0] == '\r') || (header[0] == '\n'))
288*6236dae4SAndroid Build Coastguard Worker /* ignore the body separator */
289*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
290*6236dae4SAndroid Build Coastguard Worker
291*6236dae4SAndroid Build Coastguard Worker end = strchr(header, '\r');
292*6236dae4SAndroid Build Coastguard Worker if(!end) {
293*6236dae4SAndroid Build Coastguard Worker end = strchr(header, '\n');
294*6236dae4SAndroid Build Coastguard Worker if(!end)
295*6236dae4SAndroid Build Coastguard Worker /* neither CR nor LF as terminator is not a valid header */
296*6236dae4SAndroid Build Coastguard Worker return CURLE_WEIRD_SERVER_REPLY;
297*6236dae4SAndroid Build Coastguard Worker }
298*6236dae4SAndroid Build Coastguard Worker hlen = end - header;
299*6236dae4SAndroid Build Coastguard Worker
300*6236dae4SAndroid Build Coastguard Worker if((header[0] == ' ') || (header[0] == '\t')) {
301*6236dae4SAndroid Build Coastguard Worker if(data->state.prevhead)
302*6236dae4SAndroid Build Coastguard Worker /* line folding, append value to the previous header's value */
303*6236dae4SAndroid Build Coastguard Worker return unfold_value(data, header, hlen);
304*6236dae4SAndroid Build Coastguard Worker else {
305*6236dae4SAndroid Build Coastguard Worker /* cannot unfold without a previous header. Instead of erroring, just
306*6236dae4SAndroid Build Coastguard Worker pass the leading blanks. */
307*6236dae4SAndroid Build Coastguard Worker while(hlen && ISBLANK(*header)) {
308*6236dae4SAndroid Build Coastguard Worker header++;
309*6236dae4SAndroid Build Coastguard Worker hlen--;
310*6236dae4SAndroid Build Coastguard Worker }
311*6236dae4SAndroid Build Coastguard Worker if(!hlen)
312*6236dae4SAndroid Build Coastguard Worker return CURLE_WEIRD_SERVER_REPLY;
313*6236dae4SAndroid Build Coastguard Worker }
314*6236dae4SAndroid Build Coastguard Worker }
315*6236dae4SAndroid Build Coastguard Worker
316*6236dae4SAndroid Build Coastguard Worker hs = calloc(1, sizeof(*hs) + hlen);
317*6236dae4SAndroid Build Coastguard Worker if(!hs)
318*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
319*6236dae4SAndroid Build Coastguard Worker memcpy(hs->buffer, header, hlen);
320*6236dae4SAndroid Build Coastguard Worker hs->buffer[hlen] = 0; /* nul terminate */
321*6236dae4SAndroid Build Coastguard Worker
322*6236dae4SAndroid Build Coastguard Worker result = namevalue(hs->buffer, hlen, type, &name, &value);
323*6236dae4SAndroid Build Coastguard Worker if(!result) {
324*6236dae4SAndroid Build Coastguard Worker hs->name = name;
325*6236dae4SAndroid Build Coastguard Worker hs->value = value;
326*6236dae4SAndroid Build Coastguard Worker hs->type = type;
327*6236dae4SAndroid Build Coastguard Worker hs->request = data->state.requests;
328*6236dae4SAndroid Build Coastguard Worker
329*6236dae4SAndroid Build Coastguard Worker /* insert this node into the list of headers */
330*6236dae4SAndroid Build Coastguard Worker Curl_llist_append(&data->state.httphdrs, hs, &hs->node);
331*6236dae4SAndroid Build Coastguard Worker data->state.prevhead = hs;
332*6236dae4SAndroid Build Coastguard Worker }
333*6236dae4SAndroid Build Coastguard Worker else
334*6236dae4SAndroid Build Coastguard Worker free(hs);
335*6236dae4SAndroid Build Coastguard Worker return result;
336*6236dae4SAndroid Build Coastguard Worker }
337*6236dae4SAndroid Build Coastguard Worker
338*6236dae4SAndroid Build Coastguard Worker /*
339*6236dae4SAndroid Build Coastguard Worker * Curl_headers_reset(). Reset the headers subsystem.
340*6236dae4SAndroid Build Coastguard Worker */
headers_reset(struct Curl_easy * data)341*6236dae4SAndroid Build Coastguard Worker static void headers_reset(struct Curl_easy *data)
342*6236dae4SAndroid Build Coastguard Worker {
343*6236dae4SAndroid Build Coastguard Worker Curl_llist_init(&data->state.httphdrs, NULL);
344*6236dae4SAndroid Build Coastguard Worker data->state.prevhead = NULL;
345*6236dae4SAndroid Build Coastguard Worker }
346*6236dae4SAndroid Build Coastguard Worker
347*6236dae4SAndroid Build Coastguard Worker struct hds_cw_collect_ctx {
348*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter super;
349*6236dae4SAndroid Build Coastguard Worker };
350*6236dae4SAndroid Build Coastguard Worker
hds_cw_collect_write(struct Curl_easy * data,struct Curl_cwriter * writer,int type,const char * buf,size_t blen)351*6236dae4SAndroid Build Coastguard Worker static CURLcode hds_cw_collect_write(struct Curl_easy *data,
352*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer, int type,
353*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t blen)
354*6236dae4SAndroid Build Coastguard Worker {
355*6236dae4SAndroid Build Coastguard Worker if((type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS)) {
356*6236dae4SAndroid Build Coastguard Worker unsigned char htype = (unsigned char)
357*6236dae4SAndroid Build Coastguard Worker (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
358*6236dae4SAndroid Build Coastguard Worker (type & CLIENTWRITE_1XX ? CURLH_1XX :
359*6236dae4SAndroid Build Coastguard Worker (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
360*6236dae4SAndroid Build Coastguard Worker CURLH_HEADER)));
361*6236dae4SAndroid Build Coastguard Worker CURLcode result = Curl_headers_push(data, buf, htype);
362*6236dae4SAndroid Build Coastguard Worker CURL_TRC_WRITE(data, "header_collect pushed(type=%x, len=%zu) -> %d",
363*6236dae4SAndroid Build Coastguard Worker htype, blen, result);
364*6236dae4SAndroid Build Coastguard Worker if(result)
365*6236dae4SAndroid Build Coastguard Worker return result;
366*6236dae4SAndroid Build Coastguard Worker }
367*6236dae4SAndroid Build Coastguard Worker return Curl_cwriter_write(data, writer->next, type, buf, blen);
368*6236dae4SAndroid Build Coastguard Worker }
369*6236dae4SAndroid Build Coastguard Worker
370*6236dae4SAndroid Build Coastguard Worker static const struct Curl_cwtype hds_cw_collect = {
371*6236dae4SAndroid Build Coastguard Worker "hds-collect",
372*6236dae4SAndroid Build Coastguard Worker NULL,
373*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_def_init,
374*6236dae4SAndroid Build Coastguard Worker hds_cw_collect_write,
375*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_def_close,
376*6236dae4SAndroid Build Coastguard Worker sizeof(struct hds_cw_collect_ctx)
377*6236dae4SAndroid Build Coastguard Worker };
378*6236dae4SAndroid Build Coastguard Worker
Curl_headers_init(struct Curl_easy * data)379*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_headers_init(struct Curl_easy *data)
380*6236dae4SAndroid Build Coastguard Worker {
381*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer;
382*6236dae4SAndroid Build Coastguard Worker CURLcode result;
383*6236dae4SAndroid Build Coastguard Worker
384*6236dae4SAndroid Build Coastguard Worker if(data->conn && (data->conn->handler->protocol & PROTO_FAMILY_HTTP)) {
385*6236dae4SAndroid Build Coastguard Worker /* avoid installing it twice */
386*6236dae4SAndroid Build Coastguard Worker if(Curl_cwriter_get_by_name(data, hds_cw_collect.name))
387*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
388*6236dae4SAndroid Build Coastguard Worker
389*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_create(&writer, data, &hds_cw_collect,
390*6236dae4SAndroid Build Coastguard Worker CURL_CW_PROTOCOL);
391*6236dae4SAndroid Build Coastguard Worker if(result)
392*6236dae4SAndroid Build Coastguard Worker return result;
393*6236dae4SAndroid Build Coastguard Worker
394*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_add(data, writer);
395*6236dae4SAndroid Build Coastguard Worker if(result) {
396*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_free(data, writer);
397*6236dae4SAndroid Build Coastguard Worker return result;
398*6236dae4SAndroid Build Coastguard Worker }
399*6236dae4SAndroid Build Coastguard Worker }
400*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
401*6236dae4SAndroid Build Coastguard Worker }
402*6236dae4SAndroid Build Coastguard Worker
403*6236dae4SAndroid Build Coastguard Worker /*
404*6236dae4SAndroid Build Coastguard Worker * Curl_headers_cleanup(). Free all stored headers and associated memory.
405*6236dae4SAndroid Build Coastguard Worker */
Curl_headers_cleanup(struct Curl_easy * data)406*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_headers_cleanup(struct Curl_easy *data)
407*6236dae4SAndroid Build Coastguard Worker {
408*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *e;
409*6236dae4SAndroid Build Coastguard Worker struct Curl_llist_node *n;
410*6236dae4SAndroid Build Coastguard Worker
411*6236dae4SAndroid Build Coastguard Worker for(e = Curl_llist_head(&data->state.httphdrs); e; e = n) {
412*6236dae4SAndroid Build Coastguard Worker struct Curl_header_store *hs = Curl_node_elem(e);
413*6236dae4SAndroid Build Coastguard Worker n = Curl_node_next(e);
414*6236dae4SAndroid Build Coastguard Worker free(hs);
415*6236dae4SAndroid Build Coastguard Worker }
416*6236dae4SAndroid Build Coastguard Worker headers_reset(data);
417*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
418*6236dae4SAndroid Build Coastguard Worker }
419*6236dae4SAndroid Build Coastguard Worker
420*6236dae4SAndroid Build Coastguard Worker #else /* HTTP-disabled builds below */
421*6236dae4SAndroid Build Coastguard Worker
curl_easy_header(CURL * easy,const char * name,size_t index,unsigned int origin,int request,struct curl_header ** hout)422*6236dae4SAndroid Build Coastguard Worker CURLHcode curl_easy_header(CURL *easy,
423*6236dae4SAndroid Build Coastguard Worker const char *name,
424*6236dae4SAndroid Build Coastguard Worker size_t index,
425*6236dae4SAndroid Build Coastguard Worker unsigned int origin,
426*6236dae4SAndroid Build Coastguard Worker int request,
427*6236dae4SAndroid Build Coastguard Worker struct curl_header **hout)
428*6236dae4SAndroid Build Coastguard Worker {
429*6236dae4SAndroid Build Coastguard Worker (void)easy;
430*6236dae4SAndroid Build Coastguard Worker (void)name;
431*6236dae4SAndroid Build Coastguard Worker (void)index;
432*6236dae4SAndroid Build Coastguard Worker (void)origin;
433*6236dae4SAndroid Build Coastguard Worker (void)request;
434*6236dae4SAndroid Build Coastguard Worker (void)hout;
435*6236dae4SAndroid Build Coastguard Worker return CURLHE_NOT_BUILT_IN;
436*6236dae4SAndroid Build Coastguard Worker }
437*6236dae4SAndroid Build Coastguard Worker
curl_easy_nextheader(CURL * easy,unsigned int type,int request,struct curl_header * prev)438*6236dae4SAndroid Build Coastguard Worker struct curl_header *curl_easy_nextheader(CURL *easy,
439*6236dae4SAndroid Build Coastguard Worker unsigned int type,
440*6236dae4SAndroid Build Coastguard Worker int request,
441*6236dae4SAndroid Build Coastguard Worker struct curl_header *prev)
442*6236dae4SAndroid Build Coastguard Worker {
443*6236dae4SAndroid Build Coastguard Worker (void)easy;
444*6236dae4SAndroid Build Coastguard Worker (void)type;
445*6236dae4SAndroid Build Coastguard Worker (void)request;
446*6236dae4SAndroid Build Coastguard Worker (void)prev;
447*6236dae4SAndroid Build Coastguard Worker return NULL;
448*6236dae4SAndroid Build Coastguard Worker }
449*6236dae4SAndroid Build Coastguard Worker #endif
450