Mercurial > mplayer.hg
annotate libmpdemux/http.c @ 9278:caea8ed36b48
The reason why mplayer crashes (in some cases) when using x11
output and -wid (>0) parameter is this:
Mplayer by default creates a colormap using DirectColor visual. If the
window given to mplayer uses TrueColor visual there will be an error
when mplayer sets the colormap for the window. This patch
modifies mplayer to use TrueColor visual if the window given to mplayer
uses TrueColor. Another solution is to make sure that the window given to
mplayer is created using DirectColor visual if it is supported by the
display.
Jouni Tulkki <jitulkki@cc.hut.fi>
author | arpi |
---|---|
date | Tue, 04 Feb 2003 18:31:44 +0000 |
parents | 63a5e03f4346 |
children | 9aabf1beeb4f |
rev | line source |
---|---|
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" | |
4816
f1dea39a50bb
Fixed the http response parser when the http header only has the HTTP
bertrand
parents:
4311
diff
changeset
|
12 #include "url.h" |
5915 | 13 #include "mp_msg.h" |
870 | 14 |
15 HTTP_header_t * | |
16 http_new_header() { | |
17 HTTP_header_t *http_hdr; | |
18 | |
19 http_hdr = (HTTP_header_t*)malloc(sizeof(HTTP_header_t)); | |
20 if( http_hdr==NULL ) return NULL; | |
21 memset( http_hdr, 0, sizeof(HTTP_header_t) ); | |
22 | |
23 return http_hdr; | |
24 } | |
25 | |
26 void | |
27 http_free( HTTP_header_t *http_hdr ) { | |
3039 | 28 HTTP_field_t *field, *field2free; |
870 | 29 if( http_hdr==NULL ) return; |
30 if( http_hdr->protocol!=NULL ) free( http_hdr->protocol ); | |
31 if( http_hdr->uri!=NULL ) free( http_hdr->uri ); | |
32 if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase ); | |
33 if( http_hdr->field_search!=NULL ) free( http_hdr->field_search ); | |
902 | 34 if( http_hdr->method!=NULL ) free( http_hdr->method ); |
35 if( http_hdr->buffer!=NULL ) free( http_hdr->buffer ); | |
3039 | 36 field = http_hdr->first_field; |
37 while( field!=NULL ) { | |
38 field2free = field; | |
39 field = field->next; | |
40 free( field2free ); | |
41 } | |
870 | 42 free( http_hdr ); |
3039 | 43 http_hdr = NULL; |
870 | 44 } |
45 | |
902 | 46 int |
47 http_response_append( HTTP_header_t *http_hdr, char *response, int length ) { | |
1027 | 48 if( http_hdr==NULL || response==NULL || length<0 ) return -1; |
7304
7da2c2a68547
Check if realloc failed on http_hdr->buffer instead of ptr in http_response_append,
bertrand
parents:
7293
diff
changeset
|
49 |
7293 | 50 http_hdr->buffer = (char*)realloc( http_hdr->buffer, http_hdr->buffer_size+length+1 ); |
7304
7da2c2a68547
Check if realloc failed on http_hdr->buffer instead of ptr in http_response_append,
bertrand
parents:
7293
diff
changeset
|
51 if( http_hdr->buffer==NULL ) { |
7293 | 52 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory (re)allocation failed\n"); |
902 | 53 return -1; |
54 } | |
7293 | 55 memcpy( http_hdr->buffer+http_hdr->buffer_size, response, length ); |
56 http_hdr->buffer_size += length; | |
57 http_hdr->buffer[http_hdr->buffer_size]=0; // close the string! | |
902 | 58 return http_hdr->buffer_size; |
59 } | |
60 | |
61 int | |
2489
0ecc1b4f7cf8
Added ASF http server streaming (Not mms streaming).
bertrand
parents:
2310
diff
changeset
|
62 http_is_header_entire( HTTP_header_t *http_hdr ) { |
902 | 63 if( http_hdr==NULL ) return -1; |
7293 | 64 if( http_hdr->buffer==NULL ) return 0; // empty |
65 | |
3784 | 66 if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL && |
67 strstr(http_hdr->buffer, "\n\n")==NULL ) return 0; | |
68 return 1; | |
902 | 69 } |
70 | |
71 int | |
72 http_response_parse( HTTP_header_t *http_hdr ) { | |
870 | 73 char *hdr_ptr, *ptr; |
74 char *field=NULL; | |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
75 int pos_hdr_sep, hdr_sep_len, len; |
902 | 76 if( http_hdr==NULL ) return -1; |
77 if( http_hdr->is_parsed ) return 0; | |
870 | 78 |
79 // Get the protocol | |
902 | 80 hdr_ptr = strstr( http_hdr->buffer, " " ); |
870 | 81 if( hdr_ptr==NULL ) { |
5915 | 82 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. No space separator found.\n"); |
902 | 83 return -1; |
870 | 84 } |
902 | 85 len = hdr_ptr-http_hdr->buffer; |
870 | 86 http_hdr->protocol = (char*)malloc(len+1); |
87 if( http_hdr->protocol==NULL ) { | |
5915 | 88 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
902 | 89 return -1; |
870 | 90 } |
902 | 91 strncpy( http_hdr->protocol, http_hdr->buffer, len ); |
92 http_hdr->protocol[len]='\0'; | |
870 | 93 if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) { |
94 if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) { | |
5915 | 95 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get HTTP minor version.\n"); |
902 | 96 return -1; |
870 | 97 } |
98 } | |
99 | |
100 // Get the status code | |
101 if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) { | |
5915 | 102 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get status code.\n"); |
902 | 103 return -1; |
870 | 104 } |
105 hdr_ptr += 4; | |
106 | |
107 // Get the reason phrase | |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
108 ptr = strstr( hdr_ptr, "\n" ); |
870 | 109 if( hdr_ptr==NULL ) { |
5915 | 110 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get the reason phrase.\n"); |
902 | 111 return -1; |
870 | 112 } |
113 len = ptr-hdr_ptr; | |
114 http_hdr->reason_phrase = (char*)malloc(len+1); | |
115 if( http_hdr->reason_phrase==NULL ) { | |
5915 | 116 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
902 | 117 return -1; |
870 | 118 } |
119 strncpy( http_hdr->reason_phrase, hdr_ptr, len ); | |
4311 | 120 if( http_hdr->reason_phrase[len-1]=='\r' ) { |
121 len--; | |
122 } | |
870 | 123 http_hdr->reason_phrase[len]='\0'; |
124 | |
125 // Set the position of the header separator: \r\n\r\n | |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
126 hdr_sep_len = 4; |
902 | 127 ptr = strstr( http_hdr->buffer, "\r\n\r\n" ); |
870 | 128 if( ptr==NULL ) { |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
129 ptr = strstr( http_hdr->buffer, "\n\n" ); |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
130 if( ptr==NULL ) { |
5915 | 131 mp_msg(MSGT_NETWORK,MSGL_ERR,"Header may be incomplete. No CRLF CRLF found.\n"); |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
132 return -1; |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
133 } |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
134 hdr_sep_len = 2; |
870 | 135 } |
902 | 136 pos_hdr_sep = ptr-http_hdr->buffer; |
870 | 137 |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
138 // Point to the first line after the method line. |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
139 hdr_ptr = strstr( http_hdr->buffer, "\n" )+1; |
870 | 140 do { |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
141 ptr = hdr_ptr; |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
142 while( *ptr!='\r' && *ptr!='\n' ) ptr++; |
870 | 143 len = ptr-hdr_ptr; |
4816
f1dea39a50bb
Fixed the http response parser when the http header only has the HTTP
bertrand
parents:
4311
diff
changeset
|
144 if( len==0 ) break; |
870 | 145 field = (char*)realloc(field, len+1); |
146 if( field==NULL ) { | |
5915 | 147 mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n"); |
902 | 148 return -1; |
870 | 149 } |
150 strncpy( field, hdr_ptr, len ); | |
151 field[len]='\0'; | |
152 http_set_field( http_hdr, field ); | |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
153 hdr_ptr = ptr+((*ptr=='\r')?2:1); |
902 | 154 } while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) ); |
870 | 155 |
156 if( field!=NULL ) free( field ); | |
157 | |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
158 if( pos_hdr_sep+hdr_sep_len<http_hdr->buffer_size ) { |
870 | 159 // Response has data! |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
160 http_hdr->body = http_hdr->buffer+pos_hdr_sep+hdr_sep_len; |
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
161 http_hdr->body_size = http_hdr->buffer_size-(pos_hdr_sep+hdr_sep_len); |
870 | 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 ) { |
3497 | 170 char *ptr, *uri=NULL; |
902 | 171 int len; |
3039 | 172 HTTP_field_t *field; |
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, "/"); | |
3497 | 177 else { |
178 uri = (char*)malloc(strlen(http_hdr->uri)*2); | |
179 if( uri==NULL ) { | |
5915 | 180 mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n"); |
3497 | 181 return NULL; |
182 } | |
183 url_escape_string( uri, http_hdr->uri ); | |
184 } | |
870 | 185 |
3497 | 186 //**** Compute the request length |
187 // Add the Method line | |
188 len = strlen(http_hdr->method)+strlen(uri)+12; | |
189 // Add the fields | |
190 field = http_hdr->first_field; | |
3039 | 191 while( field!=NULL ) { |
192 len += strlen(field->field_name)+2; | |
193 field = field->next; | |
194 } | |
3497 | 195 // Add the CRLF |
196 len += 2; | |
197 // Add the body | |
902 | 198 if( http_hdr->body!=NULL ) { |
199 len += http_hdr->body_size; | |
200 } | |
3497 | 201 // Free the buffer if it was previously used |
902 | 202 if( http_hdr->buffer!=NULL ) { |
203 free( http_hdr->buffer ); | |
204 http_hdr->buffer = NULL; | |
205 } | |
3497 | 206 http_hdr->buffer = (char*)malloc(len+1); |
902 | 207 if( http_hdr->buffer==NULL ) { |
5915 | 208 mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n"); |
902 | 209 return NULL; |
210 } | |
211 http_hdr->buffer_size = len; | |
212 | |
3497 | 213 //*** Building the request |
902 | 214 ptr = http_hdr->buffer; |
3497 | 215 // Add the method line |
216 ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, uri, http_hdr->http_minor_version ); | |
3039 | 217 field = http_hdr->first_field; |
3497 | 218 // Add the field |
3039 | 219 while( field!=NULL ) { |
220 ptr += sprintf( ptr, "%s\r\n", field->field_name ); | |
221 field = field->next; | |
222 } | |
870 | 223 ptr += sprintf( ptr, "\r\n" ); |
3497 | 224 // Add the body |
870 | 225 if( http_hdr->body!=NULL ) { |
226 memcpy( ptr, http_hdr->body, http_hdr->body_size ); | |
227 } | |
3497 | 228 |
229 if( uri ) free( uri ); | |
902 | 230 return http_hdr->buffer; |
870 | 231 } |
232 | |
233 char * | |
234 http_get_field( HTTP_header_t *http_hdr, const char *field_name ) { | |
235 if( http_hdr==NULL || field_name==NULL ) return NULL; | |
3039 | 236 http_hdr->field_search_pos = http_hdr->first_field; |
237 http_hdr->field_search = (char*)realloc( http_hdr->field_search, strlen(field_name)+1 ); | |
870 | 238 if( http_hdr->field_search==NULL ) { |
5915 | 239 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 240 return NULL; |
241 } | |
242 strcpy( http_hdr->field_search, field_name ); | |
243 return http_get_next_field( http_hdr ); | |
244 } | |
245 | |
246 char * | |
247 http_get_next_field( HTTP_header_t *http_hdr ) { | |
248 char *ptr; | |
3039 | 249 HTTP_field_t *field; |
870 | 250 if( http_hdr==NULL ) return NULL; |
251 | |
3039 | 252 field = http_hdr->field_search_pos; |
253 while( field!=NULL ) { | |
254 ptr = strstr( field->field_name, ":" ); | |
870 | 255 if( ptr==NULL ) return NULL; |
3039 | 256 if( !strncasecmp( field->field_name, http_hdr->field_search, ptr-(field->field_name) ) ) { |
870 | 257 ptr++; // Skip the column |
258 while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some | |
3039 | 259 http_hdr->field_search_pos = field->next; |
870 | 260 return ptr; // return the value without the field name |
261 } | |
3039 | 262 field = field->next; |
870 | 263 } |
264 return NULL; | |
265 } | |
266 | |
267 void | |
3039 | 268 http_set_field( HTTP_header_t *http_hdr, const char *field_name ) { |
269 HTTP_field_t *new_field; | |
270 if( http_hdr==NULL || field_name==NULL ) return; | |
870 | 271 |
3039 | 272 new_field = (HTTP_field_t*)malloc(sizeof(HTTP_field_t)); |
273 if( new_field==NULL ) { | |
5915 | 274 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 275 return; |
276 } | |
3039 | 277 new_field->next = NULL; |
278 new_field->field_name = (char*)malloc(strlen(field_name)+1); | |
279 if( new_field->field_name==NULL ) { | |
5915 | 280 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
3039 | 281 return; |
282 } | |
283 strcpy( new_field->field_name, field_name ); | |
284 | |
285 if( http_hdr->last_field==NULL ) { | |
286 http_hdr->first_field = new_field; | |
287 } else { | |
288 http_hdr->last_field->next = new_field; | |
289 } | |
290 http_hdr->last_field = new_field; | |
870 | 291 http_hdr->field_nb++; |
292 } | |
293 | |
294 void | |
295 http_set_method( HTTP_header_t *http_hdr, const char *method ) { | |
296 if( http_hdr==NULL || method==NULL ) return; | |
297 | |
298 http_hdr->method = (char*)malloc(strlen(method)+1); | |
299 if( http_hdr->method==NULL ) { | |
5915 | 300 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 301 return; |
302 } | |
303 strcpy( http_hdr->method, method ); | |
304 } | |
305 | |
306 void | |
307 http_set_uri( HTTP_header_t *http_hdr, const char *uri ) { | |
308 if( http_hdr==NULL || uri==NULL ) return; | |
309 | |
310 http_hdr->uri = (char*)malloc(strlen(uri)+1); | |
311 if( http_hdr->uri==NULL ) { | |
5915 | 312 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 313 return; |
314 } | |
315 strcpy( http_hdr->uri, uri ); | |
316 } | |
317 | |
6514 | 318 int |
319 http_add_basic_authentication( HTTP_header_t *http_hdr, const char *username, const char *password ) { | |
320 char *auth, *usr_pass, *b64_usr_pass; | |
321 int encoded_len, pass_len=0, out_len; | |
322 if( http_hdr==NULL || username==NULL ) return -1; | |
323 | |
324 if( password!=NULL ) { | |
325 pass_len = strlen(password); | |
326 } | |
327 | |
328 usr_pass = (char*)malloc(strlen(username)+pass_len+2); | |
329 if( usr_pass==NULL ) { | |
330 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); | |
331 return -1; | |
332 } | |
333 | |
334 sprintf( usr_pass, "%s:%s", username, (password==NULL)?"":password ); | |
335 | |
336 // Base 64 encode with at least 33% more data than the original size | |
337 encoded_len = strlen(usr_pass)*2; | |
338 b64_usr_pass = (char*)malloc(encoded_len); | |
339 if( b64_usr_pass==NULL ) { | |
340 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); | |
341 return -1; | |
342 } | |
343 | |
344 out_len = base64_encode( usr_pass, strlen(usr_pass), b64_usr_pass, encoded_len); | |
345 if( out_len<0 ) { | |
346 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Base64 out overflow\n"); | |
347 return -1; | |
348 } | |
349 | |
350 b64_usr_pass[out_len]='\0'; | |
351 | |
352 auth = (char*)malloc(encoded_len+22); | |
353 if( auth==NULL ) { | |
354 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); | |
355 return -1; | |
356 } | |
357 | |
358 sprintf( auth, "Authorization: Basic %s", b64_usr_pass); | |
359 http_set_field( http_hdr, auth ); | |
360 | |
361 free( usr_pass ); | |
362 free( b64_usr_pass ); | |
363 free( auth ); | |
364 | |
365 return 0; | |
366 } | |
367 | |
870 | 368 void |
369 http_debug_hdr( HTTP_header_t *http_hdr ) { | |
3039 | 370 HTTP_field_t *field; |
371 int i = 0; | |
902 | 372 if( http_hdr==NULL ) return; |
870 | 373 |
5915 | 374 mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- START ---\n"); |
375 mp_msg(MSGT_NETWORK,MSGL_V,"protocol: [%s]\n", http_hdr->protocol ); | |
376 mp_msg(MSGT_NETWORK,MSGL_V,"http minor version: [%d]\n", http_hdr->http_minor_version ); | |
377 mp_msg(MSGT_NETWORK,MSGL_V,"uri: [%s]\n", http_hdr->uri ); | |
378 mp_msg(MSGT_NETWORK,MSGL_V,"method: [%s]\n", http_hdr->method ); | |
379 mp_msg(MSGT_NETWORK,MSGL_V,"status code: [%d]\n", http_hdr->status_code ); | |
380 mp_msg(MSGT_NETWORK,MSGL_V,"reason phrase: [%s]\n", http_hdr->reason_phrase ); | |
381 mp_msg(MSGT_NETWORK,MSGL_V,"body size: [%d]\n", http_hdr->body_size ); | |
870 | 382 |
5915 | 383 mp_msg(MSGT_NETWORK,MSGL_V,"Fields:\n"); |
3039 | 384 field = http_hdr->first_field; |
385 while( field!=NULL ) { | |
5915 | 386 mp_msg(MSGT_NETWORK,MSGL_V," %d - %s\n", i++, field->field_name ); |
3039 | 387 field = field->next; |
388 } | |
5915 | 389 mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- END ---\n"); |
870 | 390 } |
6514 | 391 |
392 int | |
393 base64_encode(const void *enc, int encLen, char *out, int outMax) { | |
394 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; | |
395 | |
396 unsigned char *encBuf; | |
397 int outLen; | |
398 unsigned int bits; | |
399 unsigned int shift; | |
400 | |
401 encBuf = (unsigned char*)enc; | |
402 outLen = 0; | |
403 bits = 0; | |
404 shift = 0; | |
405 | |
406 while( outLen<outMax ) { | |
407 if( encLen>0 ) { | |
408 // Shift in byte | |
409 bits <<= 8; | |
410 bits |= *encBuf; | |
411 shift += 8; | |
412 // Next byte | |
413 encBuf++; | |
414 encLen--; | |
415 } else if( shift>0 ) { | |
416 // Pad last bits to 6 bits - will end next loop | |
417 bits <<= 6 - shift; | |
418 shift = 6; | |
419 } else { | |
420 // Terminate with Mime style '=' | |
421 *out = '='; | |
422 outLen++; | |
423 | |
424 return outLen; | |
425 } | |
426 | |
427 // Encode 6 bit segments | |
428 while( shift>=6 ) { | |
429 shift -= 6; | |
430 *out = b64[ (bits >> shift) & 0x3F ]; | |
431 out++; | |
432 outLen++; | |
433 } | |
434 } | |
435 | |
436 // Output overflow | |
437 return -1; | |
438 } | |
439 | |
440 |