source: mainline/uspace/lib/http/src/headers.c@ b623b68

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b623b68 was b623b68, checked in by Martin Sucha <sucha14@…>, 12 years ago

Split libhttp into include and src directories

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup http
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <str.h>
39#include <macros.h>
40
41#include <http/http.h>
42#include <http/ctype.h>
43
44#define HTTP_HEADER_LINE "%s: %s\r\n"
45
46void http_header_init(http_header_t *header)
47{
48 link_initialize(&header->link);
49 header->name = NULL;
50 header->value = NULL;
51}
52
53http_header_t *http_header_create(const char *name, const char *value)
54{
55 http_header_t *header = malloc(sizeof(http_header_t));
56 if (header == NULL)
57 return NULL;
58 http_header_init(header);
59
60 header->name = str_dup(name);
61 if (header->name == NULL) {
62 free(header);
63 return NULL;
64 }
65
66 header->value = str_dup(value);
67 if (header->value == NULL) {
68 free(header->name);
69 free(header);
70 return NULL;
71 }
72
73 return header;
74}
75
76void http_header_destroy(http_header_t *header)
77{
78 free(header->name);
79 free(header->value);
80 free(header);
81}
82
83ssize_t http_header_encode(http_header_t *header, char *buf, size_t buf_size)
84{
85 /* TODO properly split long header values */
86 if (buf == NULL) {
87 return printf_size(HTTP_HEADER_LINE, header->name, header->value);
88 }
89 else {
90 return snprintf(buf, buf_size,
91 HTTP_HEADER_LINE, header->name, header->value);
92 }
93}
94
95int http_header_receive_name(receive_buffer_t *rb, char **out_name)
96{
97 receive_buffer_mark_t name_start;
98 receive_buffer_mark_t name_end;
99
100 recv_mark(rb, &name_start);
101 recv_mark(rb, &name_end);
102
103 char c = 0;
104 do {
105 recv_mark_update(rb, &name_end);
106
107 int rc = recv_char(rb, &c, true);
108 if (rc != EOK) {
109 recv_unmark(rb, &name_start);
110 recv_unmark(rb, &name_end);
111 return rc;
112 }
113 } while (is_token(c));
114
115 if (c != ':') {
116 recv_unmark(rb, &name_start);
117 recv_unmark(rb, &name_end);
118 return EINVAL;
119 }
120
121 char *name = NULL;
122 int rc = recv_cut_str(rb, &name_start, &name_end, &name);
123 recv_unmark(rb, &name_start);
124 recv_unmark(rb, &name_end);
125 if (rc != EOK)
126 return rc;
127
128 *out_name = name;
129 return EOK;
130}
131
132int http_header_receive_value(receive_buffer_t *rb, char **out_value)
133{
134 int rc = EOK;
135 char c = 0;
136
137 receive_buffer_mark_t value_start;
138 recv_mark(rb, &value_start);
139
140 /* Ignore any inline LWS */
141 while (true) {
142 recv_mark_update(rb, &value_start);
143 rc = recv_char(rb, &c, false);
144 if (rc != EOK)
145 goto error;
146
147 if (c != ' ' && c != '\t')
148 break;
149
150 rc = recv_char(rb, &c, true);
151 if (rc != EOK)
152 goto error;
153 }
154
155 receive_buffer_mark_t value_end;
156 recv_mark(rb, &value_end);
157
158 while (true) {
159 recv_mark_update(rb, &value_end);
160
161 rc = recv_char(rb, &c, true);
162 if (rc != EOK)
163 goto error_end;
164
165 if (c != '\r' && c != '\n')
166 continue;
167
168 rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
169 if (rc < 0)
170 goto error_end;
171
172 rc = recv_char(rb, &c, false);
173 if (rc != EOK)
174 goto error_end;
175
176 if (c != ' ' && c != '\t')
177 break;
178
179 /* Ignore the char */
180 rc = recv_char(rb, &c, true);
181 if (rc != EOK)
182 goto error_end;
183 }
184
185 char *value = NULL;
186 rc = recv_cut_str(rb, &value_start, &value_end, &value);
187 recv_unmark(rb, &value_start);
188 recv_unmark(rb, &value_end);
189 if (rc != EOK)
190 return rc;
191
192 *out_value = value;
193 return EOK;
194error_end:
195 recv_unmark(rb, &value_end);
196error:
197 recv_unmark(rb, &value_start);
198 return rc;
199}
200
201int http_header_receive(receive_buffer_t *rb, http_header_t *header)
202{
203 char *name = NULL;
204 int rc = http_header_receive_name(rb, &name);
205 if (rc != EOK) {
206 printf("Failed receiving header name\n");
207 return rc;
208 }
209
210 char *value = NULL;
211 rc = http_header_receive_value(rb, &value);
212 if (rc != EOK) {
213 free(name);
214 return rc;
215 }
216
217 header->name = name;
218 header->value = value;
219 return EOK;
220}
221
222/** Normalize HTTP header value
223 *
224 * @see RFC2616 section 4.2
225 */
226void http_header_normalize_value(char *value)
227{
228 size_t read_index = 0;
229 size_t write_index = 0;
230
231 while (is_lws(value[read_index])) read_index++;
232
233 while (value[read_index] != 0) {
234 if (is_lws(value[read_index])) {
235 while (is_lws(value[read_index])) read_index++;
236
237 if (value[read_index] != 0)
238 value[write_index++] = ' ';
239
240 continue;
241 }
242
243 value[write_index++] = value[read_index++];
244 }
245
246 value[write_index] = 0;
247}
248
249/** @}
250 */
Note: See TracBrowser for help on using the repository browser.