Skip to content

Commit d00ee5a

Browse files
authored
net_http: handle redirects (libretro#17482)
1 parent b982ff6 commit d00ee5a

File tree

1 file changed

+78
-3
lines changed

1 file changed

+78
-3
lines changed

libretro-common/net/net_http.c

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#endif
3333
#include <compat/strl.h>
3434
#include <features/features_cpu.h>
35+
#include <file/file_path.h>
3536
#include <string/stdstring.h>
3637
#include <string.h>
3738
#include <lists/string_list.h>
@@ -1094,7 +1095,10 @@ static bool net_http_connect(struct http_t *state)
10941095
/* we just used/added this in _new_socket above, if it's not there it's a big bug */
10951096
addr = dns_entry->addr;
10961097

1097-
#ifdef HAVE_SSL
1098+
#ifndef HAVE_SSL
1099+
if (state->ssl)
1100+
return false;
1101+
#else
10981102
if (state->ssl)
10991103
{
11001104
if (!conn || conn->fd < 0)
@@ -1473,6 +1477,64 @@ static bool net_http_receive_body(struct http_t *state, ssize_t newlen)
14731477
return true;
14741478
}
14751479

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+
14761538
/**
14771539
* net_http_update:
14781540
*
@@ -1557,12 +1619,25 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total)
15571619
{
15581620
net_http_conn_pool_remove(state->conn);
15591621
state->conn = NULL;
1560-
return true;
1622+
break;
15611623
}
15621624
}
15631625

1564-
state->conn->in_use = false;
1626+
if (state->conn)
1627+
state->conn->in_use = false;
15651628
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+
15661641
return true;
15671642

15681643
error:

0 commit comments

Comments
 (0)