]> sjero.net Git - wget/blob - src/headers.c
4f65c2b50e88dd06d195238c5c29b3b4d45ce1c7
[wget] / src / headers.c
1 /* Generic support for headers.
2    Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef HAVE_STRING_H
25 # include <string.h>
26 #else
27 # include <strings.h>
28 #endif
29
30 #include "wget.h"
31 #include "connect.h"
32 #include "rbuf.h"
33 #include "headers.h"
34
35 /* This file contains the generic routines for work with headers.
36    Currently they are used only by HTTP in http.c, but they can be
37    used by anything that cares about RFC822-style headers.
38
39    Header is defined in RFC2068, as quoted below.  Note that this
40    definition is not HTTP-specific -- it is virtually
41    indistinguishable from the one given in RFC822 or RFC1036.
42
43         message-header = field-name ":" [ field-value ] CRLF
44
45         field-name     = token
46         field-value    = *( field-content | LWS )
47
48         field-content  = <the OCTETs making up the field-value
49                          and consisting of either *TEXT or combinations
50                          of token, tspecials, and quoted-string>
51
52    The public functions are header_get() and header_process(), which
53    see.  */
54
55 \f
56 /* Get a header from read-buffer RBUF and return it in *HDR.
57
58    As defined in RFC2068 and elsewhere, a header can be folded into
59    multiple lines if the continuation line begins with a space or
60    horizontal TAB.  Also, this function will accept a header ending
61    with just LF instead of CRLF.
62
63    The header may be of arbitrary length; the function will allocate
64    as much memory as necessary for it to fit.  It need not contain a
65    `:', thus you can use it to retrieve, say, HTTP status line.
66
67    All trailing whitespace is stripped from the header, and it is
68    zero-terminated.  */
69 int
70 header_get (struct rbuf *rbuf, char **hdr, enum header_get_flags flags)
71 {
72   int i;
73   int bufsize = 80;
74
75   *hdr = (char *)xmalloc (bufsize);
76   for (i = 0; 1; i++)
77     {
78       int res;
79       /* #### Use DO_REALLOC?  */
80       if (i > bufsize - 1)
81         *hdr = (char *)xrealloc (*hdr, (bufsize <<= 1));
82       res = RBUF_READCHAR (rbuf, *hdr + i);
83       if (res == 1)
84         {
85           if ((*hdr)[i] == '\n')
86             {
87               if (!((flags & HG_NO_CONTINUATIONS)
88                     || i == 0
89                     || (i == 1 && (*hdr)[0] == '\r')))
90                 {
91                   char next;
92                   /* If the header is non-empty, we need to check if
93                      it continues on to the other line.  We do that by
94                      peeking at the next character.  */
95                   res = rbuf_peek (rbuf, &next);
96                   if (res == 0)
97                     return HG_EOF;
98                   else if (res == -1)
99                     return HG_ERROR;
100                   /*  If the next character is HT or SP, just continue.  */
101                   if (next == '\t' || next == ' ')
102                     continue;
103                 }
104
105               /* Strip trailing whitespace.  (*hdr)[i] is the newline;
106                  decrement I until it points to the last available
107                  whitespace.  */
108               while (i > 0 && ISSPACE ((*hdr)[i - 1]))
109                 --i;
110               (*hdr)[i] = '\0';
111               break;
112             }
113         }
114       else if (res == 0)
115         return HG_EOF;
116       else
117         return HG_ERROR;
118     }
119   DEBUGP (("%s\n", *hdr));
120   return HG_OK;
121 }
122 \f
123 /* Check whether HEADER begins with NAME and, if yes, skip the `:' and
124    the whitespace, and call PROCFUN with the arguments of HEADER's
125    contents (after the `:' and space) and ARG.  Otherwise, return 0.  */
126 int
127 header_process (const char *header, const char *name,
128                 int (*procfun) (const char *, void *),
129                 void *arg)
130 {
131   /* Check whether HEADER matches NAME.  */
132   while (*name && (TOLOWER (*name) == TOLOWER (*header)))
133     ++name, ++header;
134   if (*name || *header++ != ':')
135     return 0;
136
137   header += skip_lws (header);
138
139   return ((*procfun) (header, arg));
140 }
141 \f
142 /* Helper functions for use with header_process().  */
143
144 /* Extract a long integer from HEADER and store it to CLOSURE.  If an
145    error is encountered, return 0, else 1.  */
146 int
147 header_extract_number (const char *header, void *closure)
148 {
149   const char *p = header;
150   long result;
151
152   for (result = 0; ISDIGIT (*p); p++)
153     result = 10 * result + (*p - '0');
154
155   /* Failure if no number present. */
156   if (p == header)
157     return 0;
158
159   /* Skip trailing whitespace. */
160   p += skip_lws (p);
161
162   /* Indicate failure if trailing garbage is present. */
163   if (*p)
164     return 0;
165
166   *(long *)closure = result;
167   return 1;
168 }
169
170 /* Strdup HEADER, and place the pointer to CLOSURE.  */
171 int
172 header_strdup (const char *header, void *closure)
173 {
174   *(char **)closure = xstrdup (header);
175   return 1;
176 }
177
178 /* Write the value 1 into the integer pointed to by CLOSURE.  */
179 int
180 header_exists (const char *header, void *closure)
181 {
182   *(int *)closure = 1;
183   return 1;
184 }
185
186 /* Skip LWS (linear white space), if present.  Returns number of
187    characters to skip.  */
188 int
189 skip_lws (const char *string)
190 {
191   const char *p = string;
192
193   while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
194     ++p;
195   return p - string;
196 }