902
|
1 /*
|
|
2 * HTTP Helper
|
|
3 * by Bertrand Baudet <bertrand_baudet@yahoo.com>
|
|
4 * (C) 2001, MPlayer team.
|
|
5 */
|
|
6
|
870
|
7 #include <stdio.h>
|
|
8 #include <stdlib.h>
|
|
9 #include <string.h>
|
|
10
|
|
11 #include "http.h"
|
|
12
|
|
13 HTTP_header_t *
|
|
14 http_new_header() {
|
|
15 HTTP_header_t *http_hdr;
|
|
16
|
|
17 http_hdr = (HTTP_header_t*)malloc(sizeof(HTTP_header_t));
|
|
18 if( http_hdr==NULL ) return NULL;
|
|
19 memset( http_hdr, 0, sizeof(HTTP_header_t) );
|
|
20
|
|
21 return http_hdr;
|
|
22 }
|
|
23
|
|
24 void
|
|
25 http_free( HTTP_header_t *http_hdr ) {
|
|
26 int i;
|
|
27 if( http_hdr==NULL ) return;
|
|
28 if( http_hdr->protocol!=NULL ) free( http_hdr->protocol );
|
|
29 if( http_hdr->uri!=NULL ) free( http_hdr->uri );
|
|
30 if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase );
|
|
31 if( http_hdr->body!=NULL ) free( http_hdr->body );
|
|
32 if( http_hdr->field_search!=NULL ) free( http_hdr->field_search );
|
902
|
33 if( http_hdr->method!=NULL ) free( http_hdr->method );
|
|
34 if( http_hdr->buffer!=NULL ) free( http_hdr->buffer );
|
870
|
35 for( i=0 ; i<http_hdr->field_nb ; i++ )
|
|
36 if( http_hdr->fields[i]!=NULL ) free( http_hdr->fields[i] );
|
|
37 free( http_hdr );
|
|
38 }
|
|
39
|
902
|
40 int
|
|
41 http_response_append( HTTP_header_t *http_hdr, char *response, int length ) {
|
|
42 char *ptr = NULL;
|
|
43 if( http_hdr==NULL || response==NULL ) return -1;
|
|
44 ptr = (char*)malloc( http_hdr->buffer_size+length );
|
|
45 if( ptr==NULL ) {
|
|
46 printf("Memory allocation failed\n");
|
|
47 return -1;
|
|
48 }
|
|
49 if( http_hdr->buffer_size==0 ) {
|
|
50 // Buffer empty, copy response into it.
|
|
51 memcpy( ptr, response, length );
|
|
52 http_hdr->buffer_size = length;
|
|
53 } else {
|
|
54 // Buffer not empty, grow buffer, copy and append the response.
|
|
55 memcpy( ptr, http_hdr->buffer, http_hdr->buffer_size );
|
|
56 free( http_hdr->buffer );
|
|
57 memcpy( ptr+http_hdr->buffer_size, response, length );
|
|
58 http_hdr->buffer_size += length;
|
|
59 }
|
|
60 http_hdr->buffer = ptr;
|
|
61 return http_hdr->buffer_size;
|
|
62 }
|
|
63
|
|
64 int
|
|
65 http_is_header_entired( HTTP_header_t *http_hdr ) {
|
|
66 if( http_hdr==NULL ) return -1;
|
|
67
|
|
68 if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL ) return 0;
|
|
69 else return 1;
|
|
70 }
|
|
71
|
|
72 int
|
|
73 http_response_parse( HTTP_header_t *http_hdr ) {
|
870
|
74 char *hdr_ptr, *ptr;
|
|
75 char *field=NULL;
|
|
76 int pos_hdr_sep, len;
|
902
|
77 if( http_hdr==NULL ) return -1;
|
|
78 if( http_hdr->is_parsed ) return 0;
|
870
|
79
|
|
80 // Get the protocol
|
902
|
81 hdr_ptr = strstr( http_hdr->buffer, " " );
|
870
|
82 if( hdr_ptr==NULL ) {
|
902
|
83 printf("Malformed answer. No space separator found.\n");
|
|
84 return -1;
|
870
|
85 }
|
902
|
86 len = hdr_ptr-http_hdr->buffer;
|
870
|
87 http_hdr->protocol = (char*)malloc(len+1);
|
|
88 if( http_hdr->protocol==NULL ) {
|
|
89 printf("Memory allocation failed\n");
|
902
|
90 return -1;
|
870
|
91 }
|
902
|
92 strncpy( http_hdr->protocol, http_hdr->buffer, len );
|
|
93 http_hdr->protocol[len]='\0';
|
870
|
94 if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) {
|
|
95 if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) {
|
902
|
96 printf("Malformed answer. Unable to get HTTP minor version.\n");
|
|
97 return -1;
|
870
|
98 }
|
|
99 }
|
|
100
|
|
101 // Get the status code
|
|
102 if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) {
|
902
|
103 printf("Malformed answer. Unable to get status code.\n");
|
|
104 return -1;
|
870
|
105 }
|
|
106 hdr_ptr += 4;
|
|
107
|
|
108 // Get the reason phrase
|
|
109 ptr = strstr( hdr_ptr, "\r\n" );
|
|
110 if( hdr_ptr==NULL ) {
|
902
|
111 printf("Malformed answer. Unable to get the reason phrase.\n");
|
|
112 return -1;
|
870
|
113 }
|
|
114 len = ptr-hdr_ptr;
|
|
115 http_hdr->reason_phrase = (char*)malloc(len+1);
|
|
116 if( http_hdr->reason_phrase==NULL ) {
|
|
117 printf("Memory allocation failed\n");
|
902
|
118 return -1;
|
870
|
119 }
|
|
120 strncpy( http_hdr->reason_phrase, hdr_ptr, len );
|
|
121 http_hdr->reason_phrase[len]='\0';
|
|
122
|
|
123 // Set the position of the header separator: \r\n\r\n
|
902
|
124 ptr = strstr( http_hdr->buffer, "\r\n\r\n" );
|
870
|
125 if( ptr==NULL ) {
|
902
|
126 printf("Header may be incomplete. No CRLF CRLF found.\n");
|
|
127 return -1;
|
870
|
128 }
|
902
|
129 pos_hdr_sep = ptr-http_hdr->buffer;
|
870
|
130
|
902
|
131 hdr_ptr = strstr( http_hdr->buffer, "\r\n" )+2;
|
870
|
132 do {
|
|
133 ptr = strstr( hdr_ptr, "\r\n");
|
|
134 if( ptr==NULL ) {
|
|
135 printf("No CRLF found\n");
|
902
|
136 return -1;
|
870
|
137 }
|
|
138 len = ptr-hdr_ptr;
|
|
139 field = (char*)realloc(field, len+1);
|
|
140 if( field==NULL ) {
|
|
141 printf("Memory allocation failed\n");
|
902
|
142 return -1;
|
870
|
143 }
|
|
144 strncpy( field, hdr_ptr, len );
|
|
145 field[len]='\0';
|
|
146 http_set_field( http_hdr, field );
|
|
147 hdr_ptr = ptr+2;
|
902
|
148 } while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) );
|
870
|
149
|
|
150 if( field!=NULL ) free( field );
|
|
151
|
902
|
152 if( pos_hdr_sep+4<http_hdr->buffer_size ) {
|
870
|
153 // Response has data!
|
902
|
154 int data_length = http_hdr->buffer_size-(pos_hdr_sep+4);
|
870
|
155 http_hdr->body = (char*)malloc( data_length );
|
|
156 if( http_hdr->body==NULL ) {
|
902
|
157 printf("Memory allocation failed\n");
|
|
158 return -1;
|
870
|
159 }
|
902
|
160 memcpy( http_hdr->body, http_hdr->buffer+pos_hdr_sep+4, data_length );
|
870
|
161 http_hdr->body_size = data_length;
|
|
162 }
|
|
163
|
902
|
164 http_hdr->is_parsed = 1;
|
|
165 return 0;
|
870
|
166 }
|
|
167
|
|
168 char *
|
902
|
169 http_build_request( HTTP_header_t *http_hdr ) {
|
870
|
170 char *ptr;
|
|
171 int i;
|
902
|
172 int len;
|
870
|
173 if( http_hdr==NULL ) return NULL;
|
|
174
|
|
175 if( http_hdr->method==NULL ) http_set_method( http_hdr, "GET");
|
|
176 if( http_hdr->uri==NULL ) http_set_uri( http_hdr, "/");
|
|
177
|
902
|
178 // Compute the request length
|
|
179 len = strlen(http_hdr->method)+strlen(http_hdr->uri)+12; // Method line
|
|
180 for( i=0 ; i<http_hdr->field_nb ; i++ ) // Fields
|
|
181 len += strlen(http_hdr->fields[i])+2;
|
|
182 len += 2; // CRLF
|
|
183 if( http_hdr->body!=NULL ) {
|
|
184 len += http_hdr->body_size;
|
|
185 }
|
|
186 if( http_hdr->buffer!=NULL ) {
|
|
187 free( http_hdr->buffer );
|
|
188 http_hdr->buffer = NULL;
|
|
189 }
|
|
190 http_hdr->buffer = (char*)malloc(len);
|
|
191 if( http_hdr->buffer==NULL ) {
|
|
192 printf("Memory allocation failed\n");
|
|
193 return NULL;
|
|
194 }
|
|
195 http_hdr->buffer_size = len;
|
|
196
|
|
197 ptr = http_hdr->buffer;
|
870
|
198 ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, http_hdr->uri, http_hdr->http_minor_version );
|
|
199 for( i=0 ; i<http_hdr->field_nb ; i++ )
|
|
200 ptr += sprintf( ptr, "%s\r\n", http_hdr->fields[i] );
|
|
201 ptr += sprintf( ptr, "\r\n" );
|
|
202 if( http_hdr->body!=NULL ) {
|
|
203 memcpy( ptr, http_hdr->body, http_hdr->body_size );
|
|
204 }
|
902
|
205 return http_hdr->buffer;
|
870
|
206 }
|
|
207
|
|
208 char *
|
|
209 http_get_field( HTTP_header_t *http_hdr, const char *field_name ) {
|
|
210 if( http_hdr==NULL || field_name==NULL ) return NULL;
|
|
211 http_hdr->search_pos = 0;
|
|
212 if( http_hdr->field_search!=NULL ) free( http_hdr->field_search );
|
|
213 http_hdr->field_search = (char*)malloc(strlen(field_name)+1);
|
|
214 if( http_hdr->field_search==NULL ) {
|
|
215 printf("Memory allocation failed\n");
|
|
216 return NULL;
|
|
217 }
|
|
218 strcpy( http_hdr->field_search, field_name );
|
|
219 return http_get_next_field( http_hdr );
|
|
220 }
|
|
221
|
|
222 char *
|
|
223 http_get_next_field( HTTP_header_t *http_hdr ) {
|
|
224 char *ptr;
|
|
225 int i;
|
|
226 if( http_hdr==NULL ) return NULL;
|
|
227
|
|
228 for( i=http_hdr->search_pos ; i<http_hdr->field_nb ; i++ ) {
|
|
229 ptr = strstr( http_hdr->fields[i], ":" );
|
|
230 if( ptr==NULL ) return NULL;
|
|
231 if( !strncasecmp( http_hdr->fields[i], http_hdr->field_search, ptr-http_hdr->fields[i] ) ) {
|
|
232 ptr++; // Skip the column
|
|
233 while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some
|
|
234 http_hdr->search_pos = i+1;
|
|
235 return ptr; // return the value without the field name
|
|
236 }
|
|
237 }
|
|
238 return NULL;
|
|
239 }
|
|
240
|
|
241 void
|
|
242 http_set_field( HTTP_header_t *http_hdr, const char *field ) {
|
|
243 int pos;
|
|
244 if( http_hdr==NULL || field==NULL ) return;
|
|
245
|
|
246 pos = http_hdr->field_nb;
|
|
247
|
|
248 http_hdr->fields[pos] = (char*)malloc(strlen(field)+1);
|
|
249 if( http_hdr->fields[pos]==NULL ) {
|
|
250 printf("Memory allocation failed\n");
|
|
251 return;
|
|
252 }
|
|
253 http_hdr->field_nb++;
|
|
254 strcpy( http_hdr->fields[pos], field );
|
|
255 }
|
|
256
|
|
257 void
|
|
258 http_set_method( HTTP_header_t *http_hdr, const char *method ) {
|
|
259 if( http_hdr==NULL || method==NULL ) return;
|
|
260
|
|
261 http_hdr->method = (char*)malloc(strlen(method)+1);
|
|
262 if( http_hdr->method==NULL ) {
|
|
263 printf("Memory allocation failed\n");
|
|
264 return;
|
|
265 }
|
|
266 strcpy( http_hdr->method, method );
|
|
267 }
|
|
268
|
|
269 void
|
|
270 http_set_uri( HTTP_header_t *http_hdr, const char *uri ) {
|
|
271 if( http_hdr==NULL || uri==NULL ) return;
|
|
272
|
|
273 http_hdr->uri = (char*)malloc(strlen(uri)+1);
|
|
274 if( http_hdr->uri==NULL ) {
|
|
275 printf("Memory allocation failed\n");
|
|
276 return;
|
|
277 }
|
|
278 strcpy( http_hdr->uri, uri );
|
|
279 }
|
|
280
|
|
281 void
|
|
282 http_debug_hdr( HTTP_header_t *http_hdr ) {
|
|
283 int i;
|
902
|
284 if( http_hdr==NULL ) return;
|
870
|
285
|
|
286 printf("protocol: %s\n", http_hdr->protocol );
|
|
287 printf("http minor version: %d\n", http_hdr->http_minor_version );
|
|
288 printf("uri: %s\n", http_hdr->uri );
|
|
289 printf("method: %s\n", http_hdr->method );
|
|
290 printf("status code: %d\n", http_hdr->status_code );
|
|
291 printf("reason phrase: %s\n", http_hdr->reason_phrase );
|
|
292
|
|
293 printf("Fields:\n");
|
|
294 for( i=0 ; i<http_hdr->field_nb ; i++ )
|
|
295 printf(" %d - %s\n", i, http_hdr->fields[i] );
|
|
296 }
|