xref: /aosp_15_r20/external/curl/lib/headers.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
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