22
extern FILE *stdout_fp, *stderr_fp;
25
/* are these values ok? */
21
/* Are these values OK ? */
26
22
#define HTTP_REQUEST_MAXLEN (8 * 1024 - 1)
27
23
#define HTTP_HEADER_FIELD_MAXLEN (2 * 1024 - 1)
28
24
#define MAX_HTTP_REDIRECT 8
34
30
/* S_MOD -> true in multiple selection mode / false otherwise */
35
#define S_MOD (get_ticker_env()->selection_mode == MULTIPLE)
31
#define S_MOD (get_ticker_env()->selection_mode == MULTIPLE)
37
static void remove_chunk_info(char **response)
33
void remove_chunk_info(char **response)
52
48
*response = response2;
55
/* 'quickly check feed format' (xml/rss2.0/atom), get shift to beginnig
56
* and cut off trailing part */
51
/* 'Quickly check feed format' (xml/rss2.0/atom), get shift to beginnig
52
* and cut off trailing part. */
57
53
static int format_quick_check(char *response, int *shift)
61
/* this may return false positives so disabled
57
/* This may return false positives so disabled
62
58
if (strcmp(get_http_header_value("Content-Type", response), "text/xml") != 0)
63
59
return FEED_FORMAT_ERROR;*/
98
/* get host from url but if connecting through proxy */
94
/* Get host from url but if connecting through proxy */
99
95
int connect_with_url(sockt *sock, char *url)
101
97
char host[FILE_NAME_MAXLEN + 1];
112
108
warning(S_MOD, 2, url, ":\nHTTPS protocol not currently supported");
113
109
return HTTP_UNSUPPORTED_SCHEME;
114
110
} else if (strcmp(get_scheme_from_url(url), "file") == 0)
115
;/* do nothing here */
111
;/* Do nothing here */
116
112
else if (get_scheme_from_url(url)[0] == '\0') {
117
113
warning(S_MOD, 2, "No scheme found in URL: ", url);
118
114
return HTTP_UNSUPPORTED_SCHEME;
122
118
return HTTP_UNSUPPORTED_SCHEME;
125
/* connect via proxy */
121
/* Connect via proxy */
126
122
str_n_cpy(host, get_proxy_host(), FILE_NAME_MAXLEN);
127
123
str_n_cpy(port_num, get_proxy_port(), PORT_STR_MAXLEN);
150
146
/* ***********************************
151
* TODO: DOCUMENT BETTER THIS FUNC
147
* TODO: BETTER DOCUMENT THIS FUNC
152
148
* ***********************************/
153
/* we replace resrc->id with modified url and file_name = downloaded resource
154
* maxlen of file_name, url, new_url = FILE_NAME_MAXLEN */
149
/* We replace resrc->id with modified url and file_name = downloaded resource.
150
* Max length of file_name, url, and new_url = FILE_NAME_MAXLEN. */
155
151
int fetch_resource(const char *resrc_id, const char *file_name, char *url)
228
/* status checked here are those returned by get_http_response()
229
* so we must make sure they all match */
224
/* Status checked here are those returned by get_http_response()
225
* so we must make sure they all match. */
230
226
if (status == HTTP_CONTINUE) {
232
228
status = get_http_response(sock, "GET", "", url, &new_url, &response, &recv_status);
242
238
} else if (status == OK) {
243
239
if (strcmp(get_http_header_value("Transfer-Encoding", response), "chunked") == 0) {
244
/* chunked transfer encoding */
240
/* Chunked transfer encoding */
245
241
remove_chunk_info(&response);
246
242
} else if ((content_length = atoi(get_http_header_value("Content-Length", response))) > 0) {
247
243
/* 'Content-Length' = length of entity body is mandatory
248
* but if 'Transfer-Encoding: chunked' */
244
* but if 'Transfer-Encoding: chunked'. */
251
#ifdef VERBOSE_OUTPUT /* only if verbose because notification only, nothing done */
247
#ifdef VERBOSE_OUTPUT /* Only if verbose because notification only, nothing done. */
252
248
fprintf(STD_ERR, "No 'Transfer-Encoding' nor 'Content-Length' "
253
249
"header field in HTTP response\n");
256
/* quickly 'check format' (xml and rss2.0/atom stuff),
257
* shift to beginnig and cut off trailing part */
252
/* Quickly 'check format' (xml and rss2.0/atom stuff),
253
* shift to beginnig and cut off trailing part. */
258
254
if ((j = format_quick_check(response, &i)) != OK) {
262
/* if ok, save to dump file */
258
/* If OK, save to dump file. */
263
259
if ((fp = g_fopen(file_name, "wb+")) != NULL) {
264
260
fprintf(fp, "%s", response + i);
427
/* rq_str may contain header fields(s) separated and ended by "\r\n" */
423
/* 'rq_str' may contain header fields(s) separated and ended by "\r\n" */
428
424
const char *build_http_request(const char *method, const char *path,\
429
425
const char *host, const char* rq_str)
431
427
static char str[HTTP_REQUEST_MAXLEN + 1];
433
429
snprintf(str, HTTP_REQUEST_MAXLEN,
434
"%s %s HTTP/1.1\r\n" /* start line with method and path */
435
"Host: %s\r\n" /* mandatory host header field */
430
"%s %s HTTP/1.1\r\n" /* Start line with method and path */
431
"Host: %s\r\n" /* Mandatory host header field */
436
432
"User-Agent: "APP_NAME"-"APP_VERSION_NUMBER"\r\n"
437
433
"%s\r\n", /* optional extra header field(s) */
438
434
method, path, host, rq_str);
443
* rq_str may contain header field(s) separated and ended by "\r\n"
444
* must 'free2' response afterwards
439
* 'rq_str' may contain header field(s) separated and ended by "\r\n".
440
* Must 'free2' response afterwards.
446
442
int get_http_response(sockt sock, const char *rq_method, const char *rq_str,
447
443
const char *rq_url, char **new_rq_url, char **response, int *recv_status)
455
451
*response = NULL;
456
452
str = (char *)build_http_request(
458
(get_use_proxy() ? rq_url : get_path_from_url(rq_url)), /* path or full (absolute) url if using proxy */
454
(get_use_proxy() ? rq_url : get_path_from_url(rq_url)), /* Path or full (absolute) url if using proxy */
459
455
/* is that correct when using proxy? */
460
456
get_host_from_url(rq_url),
467
463
return HTTP_SWITCH_PROTO;
468
464
else if (status_code == 200)
470
else if ( /* 'multiple choices' */
466
else if ( /* 'Multiple choices' */
471
467
status_code == 300 ||\
472
/* 'moved permanently' */
468
/* 'Moved permanently' */
473
469
status_code == 301 ||\
475
471
status_code == 302 ||\
477
473
status_code == 303 ||\
479
475
status_code == 304 ||\
480
/* 'moved temporarily' */
476
/* 'Moved temporarily' */
481
477
status_code == 307) {
482
478
str_n_cpy(location, get_http_header_value("Location", *response),
483
479
FILE_NAME_MAXLEN);
484
return HTTP_MOVED; /* must use the new url in 'Location' */
480
return HTTP_MOVED; /* Must use the new url in 'Location' */
485
481
} else if (status_code == 305)
486
482
return HTTP_USE_PROXY;
487
483
else if (status_code == 400)
527
523
return atoi(status_code);
530
/* get header_value as string (empty one if header name not found) */
526
/* Get header_value as string (empty one if header name not found) */
531
527
const char *get_http_header_value(const char *header_name, const char *response)
533
529
static char header_value[1024];
591
/* response must point to chunk size hexa str or preceeding space(s)
592
* return -1 if invalid chunk size format (ie not an hexa str) */
587
/* 'response' must point to chunk size hexa str or preceeding space(s).
588
* Return -1 if invalid chunk size format (ie not an hexa str). */
593
589
int get_http_chunk_size(const char *response)
595
591
char size_str[32], *tailptr;
619
615
* 'http://www.sth1.org/sth2/sth2.xml' -> 'http'
620
* (expect one scheme in url, return empty str if none)
616
* (expect one scheme in url, return empty str if none).
622
618
const char *get_scheme_from_url(const char* url)
637
633
* 'http://www.sth1.org/sth2/sth2.xml' -> 'www.sth1.org'
638
* (expect one scheme in url, return empty str if none)
634
* (expect one scheme in url, return empty str if none).
640
636
const char *get_host_from_url(const char* url)
659
655
* 'http://www.sth1.org/sth2/sth2.xml' -> '/sth2/sth2.xml'
660
* (expect one scheme in url, return empty str if none)
656
* (expect one scheme in url, return empty str if none).
662
658
const char *get_path_from_url(const char* url)