|
32 | 32 | #endif |
33 | 33 | #include <compat/strl.h> |
34 | 34 | #include <features/features_cpu.h> |
| 35 | +#include <file/file_path.h> |
35 | 36 | #include <string/stdstring.h> |
36 | 37 | #include <string.h> |
37 | 38 | #include <lists/string_list.h> |
@@ -1094,7 +1095,10 @@ static bool net_http_connect(struct http_t *state) |
1094 | 1095 | /* we just used/added this in _new_socket above, if it's not there it's a big bug */ |
1095 | 1096 | addr = dns_entry->addr; |
1096 | 1097 |
|
1097 | | -#ifdef HAVE_SSL |
| 1098 | +#ifndef HAVE_SSL |
| 1099 | + if (state->ssl) |
| 1100 | + return false; |
| 1101 | +#else |
1098 | 1102 | if (state->ssl) |
1099 | 1103 | { |
1100 | 1104 | if (!conn || conn->fd < 0) |
@@ -1473,6 +1477,64 @@ static bool net_http_receive_body(struct http_t *state, ssize_t newlen) |
1473 | 1477 | return true; |
1474 | 1478 | } |
1475 | 1479 |
|
| 1480 | +static bool net_http_redirect(struct http_t *state, const char *location) |
| 1481 | +{ |
| 1482 | + /* this reinitializes state based on the new location */ |
| 1483 | + |
| 1484 | + /* url may be absolute or relative to the current url */ |
| 1485 | + bool absolute = (strstr(location, "://") != NULL); |
| 1486 | + |
| 1487 | + if (absolute) |
| 1488 | + { |
| 1489 | + /* this block is a little wasteful, memory-wise */ |
| 1490 | + struct http_connection_t *new_url = net_http_connection_new(location, NULL, NULL); |
| 1491 | + net_http_connection_iterate(new_url); |
| 1492 | + if (!net_http_connection_done(new_url)) |
| 1493 | + { |
| 1494 | + net_http_connection_free(new_url); |
| 1495 | + return true; |
| 1496 | + } |
| 1497 | + state->ssl = new_url->ssl; |
| 1498 | + if (state->request.domain) |
| 1499 | + free(state->request.domain); |
| 1500 | + state->request.domain = strdup(new_url->domain); |
| 1501 | + state->request.port = new_url->port; |
| 1502 | + if (state->request.path) |
| 1503 | + free(state->request.path); |
| 1504 | + state->request.path = strdup(new_url->path); |
| 1505 | + net_http_connection_free(new_url); |
| 1506 | + } |
| 1507 | + else |
| 1508 | + { |
| 1509 | + if (*location == '/') |
| 1510 | + { |
| 1511 | + if (state->request.path) |
| 1512 | + free(state->request.path); |
| 1513 | + state->request.path = strdup(location); |
| 1514 | + } |
| 1515 | + else |
| 1516 | + { |
| 1517 | + char *path = malloc(PATH_MAX_LENGTH); |
| 1518 | + fill_pathname_resolve_relative(path, state->request.path, location, PATH_MAX_LENGTH); |
| 1519 | + free(state->request.path); |
| 1520 | + state->request.path = path; |
| 1521 | + } |
| 1522 | + } |
| 1523 | + state->request_sent = false; |
| 1524 | + state->response.part = P_HEADER_TOP; |
| 1525 | + state->response.status = -1; |
| 1526 | + state->response.buflen = 16 * 1024; |
| 1527 | + state->response.data = realloc(state->response.data, state->response.buflen); |
| 1528 | + state->response.pos = 0; |
| 1529 | + state->response.len = 0; |
| 1530 | + state->response.bodytype = T_FULL; |
| 1531 | + /* after this, assume location is invalid */ |
| 1532 | + string_list_deinitialize(state->response.headers); |
| 1533 | + string_list_initialize(state->response.headers); |
| 1534 | + /* keep going */ |
| 1535 | + return false; |
| 1536 | +} |
| 1537 | + |
1476 | 1538 | /** |
1477 | 1539 | * net_http_update: |
1478 | 1540 | * |
@@ -1557,12 +1619,25 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total) |
1557 | 1619 | { |
1558 | 1620 | net_http_conn_pool_remove(state->conn); |
1559 | 1621 | state->conn = NULL; |
1560 | | - return true; |
| 1622 | + break; |
1561 | 1623 | } |
1562 | 1624 | } |
1563 | 1625 |
|
1564 | | - state->conn->in_use = false; |
| 1626 | + if (state->conn) |
| 1627 | + state->conn->in_use = false; |
1565 | 1628 | state->conn = NULL; |
| 1629 | + |
| 1630 | + if (response->status >= 300 && response->status < 400) |
| 1631 | + { |
| 1632 | + for (newlen = 0; (size_t)newlen < response->headers->size; newlen++) |
| 1633 | + { |
| 1634 | + if (string_starts_with_case_insensitive(response->headers->elems[newlen].data, "Location: ")) |
| 1635 | + { |
| 1636 | + return net_http_redirect(state, response->headers->elems[newlen].data + STRLEN_CONST("Location: ")); |
| 1637 | + } |
| 1638 | + } |
| 1639 | + } |
| 1640 | + |
1566 | 1641 | return true; |
1567 | 1642 |
|
1568 | 1643 | error: |
|
0 commit comments