20 #include "fileutils.h"
43 const char* authority;
59 #define MAIN_ERR_PREFIX "HTTP: "
62 #define HTTP_PERM (posix_mode_t) (POSIX_S_IRUSR | POSIX_S_IWUSR)
65 #define HTTP_LINE_MAX (size_t) 8192
71 static int http_prepare_local_file(
int* fd,
const char* lpn)
75 res =
fu_open_file(lpn, fd, POSIX_O_RDWR | POSIX_O_CREAT| POSIX_O_TRUNC,
80 if(res) {
PRINT_ERROR(
"Unable to create and lock target file"); }
96 static void http_uri_data_destructor(
struct http_uri_data** uri_data)
100 posix_free((
void*) (*uri_data)->authority);
101 posix_free((
void*) (*uri_data)->path);
102 posix_free((
void*) *uri_data);
125 static int http_uri_data_constructor(
struct http_uri_data** uri_data,
134 *uri_data = (
struct http_uri_data*)
135 posix_malloc(
sizeof(
struct http_uri_data));
136 if(NULL != *uri_data)
138 (*uri_data)->authority = NULL;
139 (*uri_data)->path = NULL;
141 if(strncmp(uri,
"http://", 7)) { res = -2; }
146 q = strchr(p, (
int)
'/');
149 len = (size_t) (q - p);
150 t = (
char*) posix_malloc(len + (
size_t) 1);
155 (*uri_data)->authority = t;
158 t = (
char*) posix_malloc(len + (
size_t) 1);
163 (*uri_data)->path = t;
175 http_uri_data_destructor(uri_data);
197 static int http_connect(
int* sd,
const char* authority)
200 int af = POSIX_AF_UNSPEC;
201 const char* host = authority;
202 const char* service =
"www";
207 int connection_failed = 0;
213 p = strchr(authority, (
int)
':');
216 i = (size_t) (p - authority);
217 len = strlen(authority);
218 q = (
char*) posix_malloc(len + (
size_t) 1);
219 if(NULL == q) { res = -1; }
222 strncpy(q, authority, len);
235 printf(
"----------------------\n");
236 printf(
"Host : %s\n", host);
237 printf(
"Service: %s\n", service);
238 printf(
"----------------------\n");
252 if(connection_failed) { res = -3; }
256 if(NULL != q) { posix_free((
void*) q); }
274 static int http_te_check(
char* resp_header)
277 posix_locale_t lcp = 0;
278 const char* te_hfn =
"Transfer-Encoding:";
279 size_t te_hfn_len = strlen(te_hfn);
280 const char* te_chunked =
"chunked";
281 size_t te_chunked_len = strlen(te_chunked);
282 char* rh = resp_header;
287 lcp = posix_newlocale(POSIX_LC_CTYPE_MASK,
"POSIX", (posix_locale_t) 0);
288 if((posix_locale_t) 0 == lcp)
299 p = strchr(rh, 0x0A);
303 if(!posix_strncasecmp_l(rh, te_hfn, te_hfn_len, lcp))
307 while(0x09 == (
int) rh[i] || 0x20 == (
int) rh[i]) { ++i; }
308 if(!posix_strncasecmp_l(&rh[i], te_chunked, te_chunked_len, lcp))
314 printf(
"%s: %sResponse has chunked transfer encoding\n",
330 if((posix_locale_t) 0 != lcp) { posix_freelocale(lcp); }
348 static int http_add_to_buffer(
char** buf,
size_t* l,
const char* line)
354 *buf = posix_realloc(*buf, *l + len);
357 PRINT_ERROR(
"Out of memory while adding data to buffer");
361 strcpy(&(*buf)[*l - (
size_t) 1], line);
381 static int http_get_tx(
int sd,
struct http_uri_data* uri_data)
393 rv = posix_snprintf(line,
HTTP_LINE_MAX,
"GET %s HTTP/1.1\r\n",
397 res = http_add_to_buffer(&buf, &l, line);
403 uri_data->authority);
406 res = http_add_to_buffer(&buf, &l, line);
412 rv = posix_snprintf(line,
HTTP_LINE_MAX,
"Connection: close\r\n");
415 res = http_add_to_buffer(&buf, &l, line);
423 "Cache-Control: max-age=1800\r\n");
426 res = http_add_to_buffer(&buf, &l, line);
441 "Accept: application/pkix-crl, "
442 "application/pkcs7-crl;q=0.8, "
443 "application/x-pkcs7-crl;q=0.2\r\n");
446 res = http_add_to_buffer(&buf, &l, line);
453 rv = posix_snprintf(line,
HTTP_LINE_MAX,
"Accept-Encoding: identity\r\n");
456 res = http_add_to_buffer(&buf, &l, line);
462 rv = posix_snprintf(line,
HTTP_LINE_MAX,
"User-Agent: %s/%s\r\n",
463 CFG_NAME, CFG_VERSION);
466 res = http_add_to_buffer(&buf, &l, line);
475 res = http_add_to_buffer(&buf, &l, line);
480 printf(
"----------------------\n");
481 if(!res) { printf(
"%s", buf); }
482 printf(
"----------------------\n");
488 len = l - (size_t) 1;
492 do { rv2 = posix_send(sd, &buf[i], len - i, 0); }
493 while((ssize_t) -1 == rv2 && POSIX_EINTR == posix_errno);
494 if((ssize_t) -1 == rv2)
505 posix_free((
void*) buf);
526 static int http_get_rx_header(
struct http_status* sc,
int sd,
int* cte)
538 int df[3] = { 100, 10, 1 };
546 resp = (
char*) posix_malloc(len);
549 PRINT_ERROR(
"Out of memory while receiving response");
556 while(!res && !eoh && len > ri)
560 do { rv = posix_recv(sd, &resp[ri], len - ri, POSIX_MSG_PEEK); }
561 while(-1 == rv && POSIX_EINTR == posix_errno);
578 if(1 == i &&
'\r' == resp[i - 1])
587 if(
'\r' == resp[i - 1]
588 &&
'\n' == resp[i - 2] &&
'\r' == resp[i - 3])
606 do { rv = posix_recv(sd, &resp[ri], i - ri, 0); }
607 while(-1 == rv && POSIX_EINTR == posix_errno);
622 p = (
char*) posix_realloc(resp, len);
625 PRINT_ERROR(
"Out of memory while receiving response");
631 if(!res && !eoh) { res = -1; }
639 printf(
"----------------------\n");
640 if(!res) { printf(
"%s", resp); }
641 printf(
"----------------------\n");
645 res = http_te_check(resp);
659 p = strchr(resp, (
int)
' ');
660 if(NULL == p) { res = -1; }
663 if((
size_t) 3 > strlen(++p)) { res = -1; }
667 for(i = 0; i < 3; ++i)
671 sc->digit[i] = p[i] - (char) 48;
672 sc->code += df[i] * (int) (sc->digit[i]);
678 posix_free((
void*) resp);
695 static int http_get_chunk_size(
size_t* cs,
int sd)
701 unsigned long int value;
707 do { rv = posix_recv(sd, &line[i], 1, 0); }
708 while(-1 == rv && POSIX_EINTR == posix_errno);
715 while(0x0A != (
int) line[i++]);
720 res = sscanf(line,
"%lx", &value);
721 if(1 != res) { res = -1; }
724 if((
unsigned long int) POSIX_UINT_MAX < value) { res = -1; }
727 *cs = (size_t) value;
734 if(res) {
PRINT_ERROR(
"Reading chunk size failed"); }
754 static int http_get_rx_body(
int fd,
int sd,
int cte)
759 size_t chunk_size = 4096;
767 chunk = (
char*) posix_malloc(chunk_size);
768 if(NULL == chunk) { res = -1; }
772 do { rv = posix_recv(sd, chunk, chunk_size, 0); }
773 while(-1 == rv && POSIX_EINTR == posix_errno);
785 if(0 > res) { res = -1; }
794 if(http_get_chunk_size(&chunk_size, sd)) { res = -1; }
798 p = (
char*) posix_realloc(chunk, chunk_size);
799 if(NULL == p) { res = -1; }
805 while(chunk_size > len)
808 do { rv = posix_recv(sd, &chunk[len], chunk_size - len, 0); }
809 while(-1 == rv && POSIX_EINTR == posix_errno);
822 if(0 > res) { res = -1; }
831 do { rv = posix_recv(sd, &crlf[len], 2 - len, 0); }
832 while(-1 == rv && POSIX_EINTR == posix_errno);
841 if(!res && (0x0D != (
int) crlf[0] || 0x0A != crlf[1]))
849 while(!res && chunk_size);
853 posix_free((
void*) chunk);
884 struct http_uri_data* uri_data = NULL;
886 struct http_status sc;
897 res = http_prepare_local_file(&fd, lpn);
901 if(!res) { res = http_uri_data_constructor(&uri_data, uri); }
902 if(!res) { res = http_connect(&sd, uri_data->authority); }
905 if(!res) { res = http_get_tx(sd, uri_data); }
906 if(!res) { res = http_get_rx_header(&sc, sd, &cte); }
910 if(2 != (
int) sc.digit[0])
913 if(5 == (
int) sc.digit[0])
917 if(404 == sc.code) { res = -4; }
920 if(!res) { res = http_get_rx_body(fd, sd, cte); }
926 http_uri_data_destructor(&uri_data);
946 printf(
"%s: %sFile successfully downloaded\n", CFG_NAME,
MAIN_ERR_PREFIX);