mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-25 04:36:53 +01:00
* Added SSL support, Thanks to Fix94
* Updated Nintendont update URL to github * Updated http.c to use less memory (thanks nintendont) * Added progressWindows support for downloads * Disabled Theme Downloader Menu access (not enough memory)
This commit is contained in:
parent
26c671bd7b
commit
b69bc9b789
@ -2,8 +2,8 @@
|
|||||||
<app version="1">
|
<app version="1">
|
||||||
<name> USB Loader GX</name>
|
<name> USB Loader GX</name>
|
||||||
<coder>USB Loader GX Team</coder>
|
<coder>USB Loader GX Team</coder>
|
||||||
<version>3.0 r1252</version>
|
<version>3.0 r1253</version>
|
||||||
<release_date>20150712124252</release_date>
|
<release_date>20150713135453</release_date>
|
||||||
<!-- // remove this line to enable arguments
|
<!-- // remove this line to enable arguments
|
||||||
<arguments>
|
<arguments>
|
||||||
<arg>--ios=250</arg>
|
<arg>--ios=250</arg>
|
||||||
|
@ -215,9 +215,9 @@ int MainMenu(int menu)
|
|||||||
case MENU_THEMEMENU:
|
case MENU_THEMEMENU:
|
||||||
currentMenu = ThemeMenu::Execute();
|
currentMenu = ThemeMenu::Execute();
|
||||||
break;
|
break;
|
||||||
case MENU_THEMEDOWNLOADER:
|
// case MENU_THEMEDOWNLOADER:
|
||||||
currentMenu = ThemeDownloader::Execute();
|
// currentMenu = ThemeDownloader::Execute();
|
||||||
break;
|
// break;
|
||||||
case MENU_HOMEBREWBROWSE:
|
case MENU_HOMEBREWBROWSE:
|
||||||
currentMenu = HomebrewBrowser::Execute();
|
currentMenu = HomebrewBrowser::Execute();
|
||||||
break;
|
break;
|
||||||
|
@ -1,9 +1,41 @@
|
|||||||
|
/* http -- http convenience functions
|
||||||
|
|
||||||
|
Copyright (C) 2008 bushing
|
||||||
|
2008-2014 Dimok
|
||||||
|
2015 Fix94 ; Cyan
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 2.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ogc/lwp_watchdog.h>
|
||||||
|
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
|
#include "ssl.h"
|
||||||
#include "../svnrev.h"
|
#include "../svnrev.h"
|
||||||
|
#include "prompts/ProgressWindow.h"
|
||||||
|
#include "language/gettext.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
|
|
||||||
extern char incommingIP[50];
|
extern char incommingIP[50];
|
||||||
static u8 retryloop = 0;
|
static u8 retryloop = 0;
|
||||||
|
static bool displayProgressWindow = false;
|
||||||
|
|
||||||
|
http_res result;
|
||||||
|
u16 http_port;
|
||||||
|
u32 http_status;
|
||||||
|
u32 content_length;
|
||||||
|
char content_location[255] = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emptyblock is a statically defined variable for functions to return if they are unable
|
* Emptyblock is a statically defined variable for functions to return if they are unable
|
||||||
@ -11,18 +43,19 @@ static u8 retryloop = 0;
|
|||||||
*/
|
*/
|
||||||
const struct block emptyblock = { 0, NULL };
|
const struct block emptyblock = { 0, NULL };
|
||||||
|
|
||||||
//The maximum amount of bytes to send per net_write() call
|
|
||||||
//#define NET_BUFFER_SIZE 1024
|
|
||||||
#define NET_BUFFER_SIZE 3600
|
|
||||||
|
|
||||||
// Write our message to the server
|
// Write our message to the server
|
||||||
static s32 send_message(s32 server, char *msg)
|
static s32 tcp_write(s32 server, char *msg)
|
||||||
{
|
{
|
||||||
s32 bytes_transferred = 0;
|
s32 bytes_transferred = 0;
|
||||||
s32 remaining = strlen(msg);
|
s32 remaining = strlen(msg);
|
||||||
|
s32 res = 0;
|
||||||
while (remaining)
|
while (remaining)
|
||||||
{
|
{
|
||||||
if ((bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining)) > 0)
|
if(http_port == 443)
|
||||||
|
res = (bytes_transferred = ssl_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining));
|
||||||
|
else
|
||||||
|
res = (bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining));
|
||||||
|
if (res > 0)
|
||||||
{
|
{
|
||||||
remaining -= bytes_transferred;
|
remaining -= bytes_transferred;
|
||||||
msg += bytes_transferred;
|
msg += bytes_transferred;
|
||||||
@ -47,7 +80,7 @@ static s32 send_message(s32 server, char *msg)
|
|||||||
* @param u32 the port to connect to on the server
|
* @param u32 the port to connect to on the server
|
||||||
* @return s32 The connection to the server (negative number if connection could not be established)
|
* @return s32 The connection to the server (negative number if connection could not be established)
|
||||||
*/
|
*/
|
||||||
static s32 server_connect(u32 ipaddress, u16 socket_port)
|
static s32 tcp_connect(u32 ipaddress, u16 socket_port)
|
||||||
{
|
{
|
||||||
//Initialize socket
|
//Initialize socket
|
||||||
s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
||||||
@ -61,7 +94,7 @@ static s32 server_connect(u32 ipaddress, u16 socket_port)
|
|||||||
|
|
||||||
sprintf(incommingIP, "%s", inet_ntoa(connect_addr.sin_addr));
|
sprintf(incommingIP, "%s", inet_ntoa(connect_addr.sin_addr));
|
||||||
|
|
||||||
//Attemt to open the socket
|
//Attempt to open the socket
|
||||||
if (net_connect(connection, (struct sockaddr*) &connect_addr, sizeof(connect_addr)) == -1)
|
if (net_connect(connection, (struct sockaddr*) &connect_addr, sizeof(connect_addr)) == -1)
|
||||||
{
|
{
|
||||||
net_close(connection);
|
net_close(connection);
|
||||||
@ -70,82 +103,168 @@ static s32 server_connect(u32 ipaddress, u16 socket_port)
|
|||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
//The amount of memory in bytes reserved initially to store the HTTP response in
|
|
||||||
//Be careful in increasing this number, reading from a socket on the Wii
|
|
||||||
//will fail if you request more than 20k or so
|
|
||||||
#define HTTP_BUFFER_SIZE 1024 * 5
|
|
||||||
|
|
||||||
//The amount of memory the buffer should expanded with if the buffer is full
|
|
||||||
#define HTTP_BUFFER_GROWTH 1024 * 5
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function reads all the data from a connection into a buffer which it returns.
|
* Reads the current connection data line by line
|
||||||
* It will return an empty buffer if something doesn't go as planned
|
|
||||||
*
|
*
|
||||||
* @param s32 connection The connection identifier to suck the response out of
|
* @return string up to "\r\n" or until max_length is reached.
|
||||||
* @return block A 'block' struct (see http.h) in which the buffer is located
|
|
||||||
*/
|
*/
|
||||||
struct block read_message(s32 connection)
|
char * tcp_readLine (const s32 s, const u16 max_length, const u64 start_time, const u16 timeout) {
|
||||||
{
|
char *buf;
|
||||||
//Create a block of memory to put in the response
|
u16 c;
|
||||||
struct block buffer;
|
s32 res;
|
||||||
buffer.data = malloc(HTTP_BUFFER_SIZE);
|
char *ret;
|
||||||
buffer.size = HTTP_BUFFER_SIZE;
|
|
||||||
|
|
||||||
if (buffer.data == NULL)
|
buf = malloc(max_length);
|
||||||
{
|
|
||||||
return emptyblock;
|
|
||||||
}
|
|
||||||
|
|
||||||
//The offset variable always points to the first byte of memory that is free in the buffer
|
c = 0;
|
||||||
u32 offset = 0;
|
ret = NULL;
|
||||||
|
while (true) {
|
||||||
|
if (ticks_to_millisecs (diff_ticks (start_time, gettime ())) > timeout)
|
||||||
|
break;
|
||||||
|
|
||||||
while (1)
|
if(http_port == 443)
|
||||||
{
|
res = ssl_read (s, &buf[c], 1);
|
||||||
//Fill the buffer with a new batch of bytes from the connection,
|
else
|
||||||
//starting from where we left of in the buffer till the end of the buffer
|
res = net_read (s, &buf[c], 1);
|
||||||
s32 bytes_read = net_read(connection, buffer.data + offset, buffer.size - offset);
|
|
||||||
|
|
||||||
//Anything below 0 is an error in the connection
|
if ((res == 0) || (res == -EAGAIN)) {
|
||||||
if (bytes_read < 0)
|
usleep (20 * 1000);
|
||||||
{
|
|
||||||
//printf("Connection error from net_read() Errorcode: %i\n", bytes_read);
|
continue;
|
||||||
return emptyblock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//No more bytes were read into the buffer,
|
if (res < 0) break;
|
||||||
//we assume this means the HTTP response is done
|
|
||||||
if (bytes_read == 0)
|
if ((c > 0) && (buf[c - 1] == '\r') && (buf[c] == '\n')) {
|
||||||
{
|
if (c == 1) {
|
||||||
|
ret = strdup ("");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = strndup (buf, c - 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += bytes_read;
|
c++;
|
||||||
|
|
||||||
//Check if we have enough buffer left over,
|
if (c == max_length)
|
||||||
//if not expand it with an additional HTTP_BUFFER_GROWTH worth of bytes
|
break;
|
||||||
if (offset >= buffer.size)
|
|
||||||
{
|
|
||||||
buffer.size += HTTP_BUFFER_GROWTH;
|
|
||||||
u8 * tmp = realloc(buffer.data, buffer.size);
|
|
||||||
|
|
||||||
if (tmp == NULL)
|
|
||||||
{
|
|
||||||
free(buffer.data);
|
|
||||||
return emptyblock;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buffer.data = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//At the end of above loop offset should be precisely the amount of bytes that were read from the connection
|
free (buf);
|
||||||
buffer.size = offset;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
//Shrink the size of the buffer so the data fits exactly in it
|
/**
|
||||||
buffer.data = realloc(buffer.data, buffer.size);
|
* This function reads all the data from a connection into a buffer.
|
||||||
|
*
|
||||||
|
* @param s32 connection The connection identifier to suck the response out of
|
||||||
|
* @return bool True if data downloaded succesfully.
|
||||||
|
*/
|
||||||
|
bool tcp_readData(const s32 connection, u8 **buffer, const u32 length)
|
||||||
|
{
|
||||||
|
u8 *p;
|
||||||
|
u32 left, block, received;
|
||||||
|
s64 t;
|
||||||
|
s32 res;
|
||||||
|
|
||||||
return buffer;
|
p = *buffer;
|
||||||
|
left = length;
|
||||||
|
received = 0;
|
||||||
|
|
||||||
|
t = gettime ();
|
||||||
|
while (left)
|
||||||
|
{
|
||||||
|
if (ticks_to_millisecs (diff_ticks (t, gettime ())) > TCP_BLOCK_RECV_TIMEOUT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Update the progress bar
|
||||||
|
if(displayProgressWindow)
|
||||||
|
{
|
||||||
|
ShowProgress(received, length);
|
||||||
|
if(ProgressCanceled())
|
||||||
|
{
|
||||||
|
ProgressStop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next block size
|
||||||
|
block = left;
|
||||||
|
if (block > TCP_BLOCK_SIZE)
|
||||||
|
block = TCP_BLOCK_SIZE;
|
||||||
|
|
||||||
|
if(http_port == 443)
|
||||||
|
res = ssl_read (connection, p, block);
|
||||||
|
else
|
||||||
|
res = net_read (connection, p, block);
|
||||||
|
|
||||||
|
if ((res == 0) || (res == -EAGAIN))
|
||||||
|
{
|
||||||
|
usleep (20 * 1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res < 0) break;
|
||||||
|
|
||||||
|
received += res;
|
||||||
|
left -= res;
|
||||||
|
p += res;
|
||||||
|
|
||||||
|
// update timing after each downloaded block
|
||||||
|
t = gettime ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return left == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the HTTP replied header
|
||||||
|
*
|
||||||
|
* @param s32 connection identification
|
||||||
|
* @return bool true if max header lines not reached. Stores HTTP answers into global variables.
|
||||||
|
*/
|
||||||
|
u8 read_header(s32 connection)
|
||||||
|
{
|
||||||
|
int linecount = 0;
|
||||||
|
result = HTTPR_OK;
|
||||||
|
|
||||||
|
for (linecount = 0; linecount < 32; linecount++)
|
||||||
|
{
|
||||||
|
char *line = tcp_readLine (connection, 0xff, gettime(), (u16)HTTP_TIMEOUT);
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
{
|
||||||
|
http_status = 404;
|
||||||
|
result = HTTPR_ERR_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen (line) < 1)
|
||||||
|
{
|
||||||
|
free (line);
|
||||||
|
line = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sscanf (line, "HTTP/1.%*u %u", &http_status);
|
||||||
|
sscanf (line, "Content-Length: %u", &content_length);
|
||||||
|
sscanf (line, "Location: %s", content_location);
|
||||||
|
//gprintf(line);
|
||||||
|
//gprintf("\n");
|
||||||
|
free (line);
|
||||||
|
line = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linecount == 32)
|
||||||
|
{
|
||||||
|
http_status = 404;
|
||||||
|
result = HTTPR_ERR_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,15 +273,27 @@ struct block read_message(s32 connection)
|
|||||||
*/
|
*/
|
||||||
struct block downloadfile(const char *url)
|
struct block downloadfile(const char *url)
|
||||||
{
|
{
|
||||||
|
int sslcontext = -1;
|
||||||
|
|
||||||
//Check if the url starts with "http://", if not it is not considered a valid url
|
//Check if the url starts with "http://", if not it is not considered a valid url
|
||||||
if (strncmp(url, "http://", strlen("http://")) != 0)
|
if (strncmp(url, "http://", strlen("http://")) == 0)
|
||||||
|
http_port = 80;
|
||||||
|
else if(strncmp(url, "https://", strlen("https://")) == 0)
|
||||||
{
|
{
|
||||||
//printf("URL '%s' doesn't start with 'http://'\n", url);
|
http_port = 443;
|
||||||
return emptyblock;
|
gprintf("Initializing ssl...\n");
|
||||||
|
if(ssl_init() < 0)
|
||||||
|
return emptyblock;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return emptyblock;
|
||||||
|
|
||||||
//Locate the path part of the url by searching for '/' past "http://"
|
//Locate the path part of the url by searching for '/' past "http://"
|
||||||
char *path = strchr(url + strlen("http://"), '/');
|
char *path = 0;
|
||||||
|
if(http_port == 443)
|
||||||
|
path = strchr(url + strlen("https://"), '/');
|
||||||
|
else
|
||||||
|
path = strchr(url + strlen("http://"), '/');
|
||||||
|
|
||||||
//At the very least the url has to end with '/', ending with just a domain is invalid
|
//At the very least the url has to end with '/', ending with just a domain is invalid
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
@ -172,7 +303,7 @@ struct block downloadfile(const char *url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Extract the domain part out of the url
|
//Extract the domain part out of the url
|
||||||
int domainlength = path - url - strlen("http://");
|
int domainlength = path - url - strlen("http://") - (http_port == 443 ? 1 : 0);
|
||||||
|
|
||||||
if (domainlength == 0)
|
if (domainlength == 0)
|
||||||
{
|
{
|
||||||
@ -181,7 +312,7 @@ struct block downloadfile(const char *url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char domain[domainlength + 1];
|
char domain[domainlength + 1];
|
||||||
strlcpy(domain, url + strlen("http://"), domainlength + 1);
|
strlcpy(domain, url + strlen("http://") + (http_port == 443 ? 1 : 0), domainlength + 1);
|
||||||
|
|
||||||
//Parsing of the URL is done, start making an actual connection
|
//Parsing of the URL is done, start making an actual connection
|
||||||
u32 ipaddress = getipbynamecached(domain);
|
u32 ipaddress = getipbynamecached(domain);
|
||||||
@ -192,7 +323,7 @@ struct block downloadfile(const char *url)
|
|||||||
return emptyblock;
|
return emptyblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 connection = server_connect(ipaddress, 80);
|
s32 connection = tcp_connect(ipaddress, http_port);
|
||||||
|
|
||||||
if (connection < 0)
|
if (connection < 0)
|
||||||
{
|
{
|
||||||
@ -200,6 +331,39 @@ struct block downloadfile(const char *url)
|
|||||||
return emptyblock;
|
return emptyblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(http_port == 443)
|
||||||
|
{
|
||||||
|
//patched out anyways so just to set something
|
||||||
|
sslcontext = ssl_new((u8*)domain,0);
|
||||||
|
|
||||||
|
if(sslcontext < 0)
|
||||||
|
{
|
||||||
|
//gprintf("ssl_new\n");
|
||||||
|
result = HTTPR_ERR_CONNECT;
|
||||||
|
net_close (connection);
|
||||||
|
return emptyblock;
|
||||||
|
}
|
||||||
|
//patched out anyways so just to set something
|
||||||
|
ssl_setbuiltinclientcert(sslcontext,0);
|
||||||
|
if(ssl_connect(sslcontext,connection) < 0)
|
||||||
|
{
|
||||||
|
//gprintf("ssl_connect\n");
|
||||||
|
result = HTTPR_ERR_CONNECT;
|
||||||
|
ssl_shutdown(sslcontext);
|
||||||
|
net_close (connection);
|
||||||
|
return emptyblock;
|
||||||
|
}
|
||||||
|
int ret = ssl_handshake(sslcontext);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
//gprintf("ssl_handshake %i\n", ret);
|
||||||
|
result = HTTPR_ERR_STATUS;
|
||||||
|
ssl_shutdown(sslcontext);
|
||||||
|
net_close (connection);
|
||||||
|
return emptyblock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove Referer from the request header for incompatible websites (ex. Cloudflare proxy)
|
// Remove Referer from the request header for incompatible websites (ex. Cloudflare proxy)
|
||||||
char referer[domainlength + 12];
|
char referer[domainlength + 12];
|
||||||
snprintf(referer, sizeof(referer), "Referer: %s\r\n", domain);
|
snprintf(referer, sizeof(referer), "Referer: %s\r\n", domain);
|
||||||
@ -216,131 +380,96 @@ struct block downloadfile(const char *url)
|
|||||||
//gprintf("%s\n",header);
|
//gprintf("%s\n",header);
|
||||||
|
|
||||||
//Do the request and get the response
|
//Do the request and get the response
|
||||||
send_message(connection, header);
|
tcp_write(http_port == 443 ? sslcontext : connection, header);
|
||||||
struct block response = read_message(connection);
|
read_header( http_port == 443 ? sslcontext : connection);
|
||||||
net_close(connection);
|
|
||||||
|
|
||||||
// dump response
|
if (http_status >= 400) // Not found
|
||||||
// hexdump(response.data, response.size);
|
|
||||||
|
|
||||||
//Search for the 4-character sequence \r\n\r\n in the response which signals the start of the http payload (file)
|
|
||||||
unsigned char *filestart = NULL;
|
|
||||||
u32 filesize = 0;
|
|
||||||
u32 i;
|
|
||||||
char newURL[512];
|
|
||||||
bool redirect = false;
|
|
||||||
|
|
||||||
for (i = 3; i < response.size; i++)
|
|
||||||
{
|
{
|
||||||
if (response.data[i] == '\n' && response.data[i - 1] == '\r' && response.data[i - 2] == '\n' && response.data[i - 3] == '\r')
|
//gprintf("HTTP ERROR: %d\n", http_status);
|
||||||
{
|
return emptyblock;
|
||||||
filestart = response.data + i + 1;
|
|
||||||
filesize = response.size - i - 1;
|
|
||||||
|
|
||||||
// Check the HTTP response code
|
|
||||||
if (response.size > 10 && strncmp((char*)response.data, "HTTP/", 5)==0)
|
|
||||||
{
|
|
||||||
char htstat[i];
|
|
||||||
strncpy(htstat, (char*)response.data, i);
|
|
||||||
htstat[i] = 0;
|
|
||||||
char *codep;
|
|
||||||
codep = strchr(htstat, ' ');
|
|
||||||
if (codep)
|
|
||||||
{
|
|
||||||
int code;
|
|
||||||
if (sscanf(codep+1, "%d", &code) == 1)
|
|
||||||
{
|
|
||||||
//gprintf("HTTP response code: %d\n", code);
|
|
||||||
if (code == 302) // 302 FOUND (redirected link)
|
|
||||||
{
|
|
||||||
char *ptr = strcasestr((char*)response.data, "Location: ");
|
|
||||||
if(ptr)
|
|
||||||
{
|
|
||||||
ptr += strlen("Location: ");
|
|
||||||
strncpy(newURL, ptr, sizeof(newURL));
|
|
||||||
*(strchr(newURL, '\r'))=0;
|
|
||||||
|
|
||||||
redirect = true;
|
|
||||||
//gprintf("New URL to download = %s \n", newURL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//gprintf("HTTP ERROR: %s\n", htstat);
|
|
||||||
free(response.data);
|
|
||||||
return emptyblock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (code >=400) // Not found
|
|
||||||
{
|
|
||||||
//gprintf("HTTP ERROR: %s\n", htstat);
|
|
||||||
free(response.data);
|
|
||||||
return emptyblock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(redirect)
|
if(!content_length)
|
||||||
|
content_length = 0;
|
||||||
|
|
||||||
|
// create data buffer to return
|
||||||
|
struct block response;
|
||||||
|
response.data = malloc(content_length);
|
||||||
|
response.size = content_length;
|
||||||
|
if (response.data == NULL)
|
||||||
{
|
{
|
||||||
// Prevent endless loop
|
return emptyblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (http_status == 200)
|
||||||
|
{
|
||||||
|
if(displayProgressWindow)
|
||||||
|
{
|
||||||
|
ProgressCancelEnable(true);
|
||||||
|
StartProgress(tr("Downloading file..."), tr("Please wait"), 0, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = tcp_readData(http_port == 443 ? sslcontext : connection, &response.data, content_length);
|
||||||
|
if(!ret)
|
||||||
|
{
|
||||||
|
free(response.data);
|
||||||
|
result = HTTPR_ERR_RECEIVE;
|
||||||
|
if(http_port == 443)
|
||||||
|
ssl_shutdown(sslcontext);
|
||||||
|
net_close (connection);
|
||||||
|
return emptyblock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (http_status == 302) // 302 FOUND (redirected link)
|
||||||
|
{
|
||||||
|
// close current connection
|
||||||
|
if(http_port == 443)
|
||||||
|
ssl_shutdown(sslcontext);
|
||||||
|
net_close (connection);
|
||||||
|
|
||||||
|
// prevent infinite loops
|
||||||
retryloop++;
|
retryloop++;
|
||||||
if(retryloop > 3)
|
if(retryloop > 3)
|
||||||
{
|
{
|
||||||
retryloop = 0;
|
retryloop = 0;
|
||||||
free(response.data);
|
|
||||||
return emptyblock;
|
return emptyblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct block redirected = downloadfile(newURL);
|
struct block redirected = downloadfile(content_location);
|
||||||
|
if(redirected.size == 0)
|
||||||
|
return emptyblock;
|
||||||
|
|
||||||
// copy the newURL data into the original data
|
// copy the newURL data into the original data
|
||||||
u8 * tmp = realloc(response.data, redirected.size);
|
u8 * tmp = realloc(response.data, redirected.size);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
{
|
{
|
||||||
//gprintf("Could not allocate enough memory for new URL. Download canceled.\n");
|
gprintf("Could not allocate enough memory for new URL. Download canceled.\n");
|
||||||
free(response.data);
|
free(response.data);
|
||||||
|
response.size = 0;
|
||||||
free(redirected.data);
|
free(redirected.data);
|
||||||
|
result = HTTPR_ERR_RECEIVE;
|
||||||
|
if(http_port == 443)
|
||||||
|
ssl_shutdown(sslcontext);
|
||||||
|
net_close (connection);
|
||||||
return emptyblock;
|
return emptyblock;
|
||||||
}
|
}
|
||||||
response.data = tmp;
|
response.data = tmp;
|
||||||
memcpy(response.data, redirected.data, redirected.size);
|
memcpy(response.data, redirected.data, redirected.size);
|
||||||
|
|
||||||
// Set filestart's new size based on redirected file
|
|
||||||
filestart = response.data;
|
|
||||||
filesize = redirected.size;
|
|
||||||
free(redirected.data);
|
free(redirected.data);
|
||||||
|
response.size = redirected.size;
|
||||||
|
|
||||||
}
|
}
|
||||||
retryloop = 0;
|
retryloop = 0;
|
||||||
|
|
||||||
if (filestart == NULL)
|
// reset progress window if used
|
||||||
|
if(displayProgressWindow)
|
||||||
{
|
{
|
||||||
//printf("HTTP Response was without a file\n");
|
ProgressStop();
|
||||||
free(response.data);
|
ProgressCancelEnable(false);
|
||||||
return emptyblock;
|
displayProgressWindow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Copy the file part of the response into a new memoryblock to return
|
return response;
|
||||||
struct block file;
|
|
||||||
file.data = malloc(filesize);
|
|
||||||
file.size = filesize;
|
|
||||||
|
|
||||||
if (file.data == NULL)
|
|
||||||
{
|
|
||||||
//printf("No more memory to copy file from HTTP response\n");
|
|
||||||
free(response.data);
|
|
||||||
return emptyblock;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(file.data, filestart, filesize);
|
|
||||||
|
|
||||||
//Dispose of the original response
|
|
||||||
free(response.data);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 GetConnection(char * domain)
|
s32 GetConnection(char * domain)
|
||||||
@ -351,7 +480,12 @@ s32 GetConnection(char * domain)
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s32 connection = server_connect(ipaddress, 80);
|
s32 connection = tcp_connect(ipaddress, 80);
|
||||||
return connection;
|
return connection;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void displayDownloadProgress(bool display)
|
||||||
|
{
|
||||||
|
displayProgressWindow = display;
|
||||||
|
}
|
@ -6,6 +6,27 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TCP_CONNECT_TIMEOUT 5000
|
||||||
|
#define TCP_BLOCK_SIZE (16 * 1024)
|
||||||
|
#define TCP_BLOCK_RECV_TIMEOUT 4000
|
||||||
|
#define TCP_BLOCK_SEND_TIMEOUT 4000
|
||||||
|
#define HTTP_TIMEOUT 300000
|
||||||
|
|
||||||
|
//The maximum amount of bytes to send per net_write() call
|
||||||
|
#define NET_BUFFER_SIZE 3600
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HTTPR_OK,
|
||||||
|
HTTPR_ERR_CONNECT,
|
||||||
|
HTTPR_ERR_REQUEST,
|
||||||
|
HTTPR_ERR_STATUS,
|
||||||
|
HTTPR_ERR_TOOBIG,
|
||||||
|
HTTPR_ERR_RECEIVE
|
||||||
|
} http_res;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -18,14 +39,15 @@ extern "C"
|
|||||||
*/
|
*/
|
||||||
struct block
|
struct block
|
||||||
{
|
{
|
||||||
u32 size;
|
u32 size;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct block emptyblock;
|
extern const struct block emptyblock;
|
||||||
|
|
||||||
struct block downloadfile(const char *url);
|
struct block downloadfile(const char *url);
|
||||||
s32 GetConnection(char * domain);
|
s32 GetConnection(char * domain);
|
||||||
|
void displayDownloadProgress(bool display);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
284
source/network/ssl.c
Normal file
284
source/network/ssl.c
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/* Code taken from http://wiibrew.org/wiki//dev/net/ssl/code */
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ssl.h"
|
||||||
|
#include "system/runtimeiospatch.h"
|
||||||
|
|
||||||
|
#define ISALIGNED(x) ((((u32)x)&0x1F)==0)
|
||||||
|
|
||||||
|
static char __ssl_fs[] ATTRIBUTE_ALIGN(32) = "/dev/net/ssl";
|
||||||
|
|
||||||
|
static s32 __ssl_fd = -1;
|
||||||
|
static s32 __ssl_hid = -1;
|
||||||
|
|
||||||
|
s32 ssl_init(void){
|
||||||
|
|
||||||
|
if(__ssl_hid < 0 ) {
|
||||||
|
__ssl_hid = iosCreateHeap(SSL_HEAP_SIZE);
|
||||||
|
if(__ssl_hid < 0){
|
||||||
|
return __ssl_hid;
|
||||||
|
}
|
||||||
|
if(IosPatch_SSL(false) < 4)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ssl_open(void){
|
||||||
|
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
if (__ssl_fd < 0) {
|
||||||
|
ret = IOS_Open(__ssl_fs,0);
|
||||||
|
if(ret<0){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
__ssl_fd = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ssl_close(void){
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
if(__ssl_fd < 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = IOS_Close(__ssl_fd);
|
||||||
|
|
||||||
|
__ssl_fd = -1;
|
||||||
|
|
||||||
|
if(ret<0){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ssl_new(u8 * CN, u32 ssl_verify_options){
|
||||||
|
|
||||||
|
s32 ret;
|
||||||
|
s32 aContext[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
u32 aVerify_options[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
aVerify_options[0] = ssl_verify_options;
|
||||||
|
|
||||||
|
if(ISALIGNED(CN)){ //Avoid alignment if the input is aligned
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, CN, 0x100);
|
||||||
|
}else{
|
||||||
|
u8 *aCN = NULL;
|
||||||
|
|
||||||
|
aCN = iosAlloc(__ssl_hid, 0x100);
|
||||||
|
if (!aCN) {
|
||||||
|
return IPC_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(aCN, CN, 0x100);
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, aCN, 0x100);
|
||||||
|
|
||||||
|
if(aCN){
|
||||||
|
iosFree(__ssl_hid, aCN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aContext[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index){
|
||||||
|
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aIndex[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
aIndex[0] = index;
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETBUILTINCLIENTCERT, "d:dd", aResponse, 32, aSsl_context, 32, aIndex, 32);
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length){
|
||||||
|
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
|
||||||
|
if(ISALIGNED(root)){ //Avoid alignment if the input is aligned
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, root, length);
|
||||||
|
}else{
|
||||||
|
u8 *aRoot = NULL;
|
||||||
|
|
||||||
|
aRoot = iosAlloc(__ssl_hid, length);
|
||||||
|
if (!aRoot) {
|
||||||
|
return IPC_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(aRoot, root, length);
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aRoot, length);
|
||||||
|
|
||||||
|
if(aRoot){
|
||||||
|
iosFree(__ssl_hid, aRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 ssl_connect(s32 ssl_context, s32 socket){
|
||||||
|
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aSocket[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
aSocket[0] = socket;
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_CONNECT, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aSocket, 0x20);
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 ssl_handshake( s32 ssl_context ){
|
||||||
|
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_HANDSHAKE, "d:d", aResponse, 0x20, aSsl_context, 0x20);
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 ssl_read(s32 ssl_context, void* buffer, u32 length){
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!buffer){
|
||||||
|
return IPC_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *aBuffer = NULL;
|
||||||
|
aBuffer = iosAlloc(__ssl_hid, length);
|
||||||
|
if (!aBuffer) {
|
||||||
|
return IPC_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_READ, "dd:d", aResponse, 0x20, aBuffer, length, aSsl_context, 0x20);
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
if(ret == IPC_OK){
|
||||||
|
memcpy(buffer, aBuffer, aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(aBuffer){
|
||||||
|
iosFree(__ssl_hid, aBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ssl_write(s32 ssl_context, const void *buffer, u32 length){
|
||||||
|
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!buffer){
|
||||||
|
return IPC_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
|
||||||
|
if(ISALIGNED(buffer)){ //Avoid alignment if the input is aligned
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, buffer, length);
|
||||||
|
}else{
|
||||||
|
u8 *aBuffer = NULL;
|
||||||
|
aBuffer = iosAlloc(__ssl_hid, length);
|
||||||
|
if (!aBuffer) {
|
||||||
|
return IPC_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(aBuffer, buffer, length);
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aBuffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ssl_shutdown( s32 ssl_context){
|
||||||
|
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = ssl_open();
|
||||||
|
if(ret){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSsl_context[0] = ssl_context;
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SHUTDOWN, "d:d", aResponse, 0x20, aSsl_context, 0x20);
|
||||||
|
|
||||||
|
ssl_close();
|
||||||
|
|
||||||
|
return (ret ? ret : aResponse[0]);
|
||||||
|
}
|
36
source/network/ssl.h
Normal file
36
source/network/ssl.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* Code taken from http://wiibrew.org/wiki//dev/net/ssl/code */
|
||||||
|
#ifndef _SSL_H_
|
||||||
|
#define _SSL_H_
|
||||||
|
|
||||||
|
#define IOCTLV_SSL_NEW 1
|
||||||
|
#define IOCTLV_SSL_CONNECT 2
|
||||||
|
#define IOCTLV_SSL_HANDSHAKE 3
|
||||||
|
#define IOCTLV_SSL_READ 4
|
||||||
|
#define IOCTLV_SSL_WRITE 5
|
||||||
|
#define IOCTLV_SSL_SHUTDOWN 6
|
||||||
|
#define IOCTLV_SSL_SETROOTCA 10
|
||||||
|
#define IOCTLV_SSL_SETBUILTINCLIENTCERT 14
|
||||||
|
|
||||||
|
#define SSL_HEAP_SIZE 0xB000
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
s32 ssl_init(void);
|
||||||
|
u32 ssl_open(void);
|
||||||
|
u32 ssl_close(void);
|
||||||
|
s32 ssl_new(u8 * CN, u32 verify_options);
|
||||||
|
s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index);
|
||||||
|
s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length);
|
||||||
|
s32 ssl_connect(s32 ssl_context, s32 socket);
|
||||||
|
s32 ssl_handshake( s32 ssl_context );
|
||||||
|
s32 ssl_read(s32 ssl_context, void* buffer, u32 length);
|
||||||
|
s32 ssl_write(s32 ssl_context, const void * buffer, u32 length);
|
||||||
|
s32 ssl_shutdown( s32 ssl_context);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif
|
@ -32,7 +32,7 @@
|
|||||||
#include "settings/SettingsPrompts.h"
|
#include "settings/SettingsPrompts.h"
|
||||||
#include "network/Wiinnertag.h"
|
#include "network/Wiinnertag.h"
|
||||||
#include "network/networkops.h"
|
#include "network/networkops.h"
|
||||||
#include "network/FileDownloader.h"
|
#include "network/http.h"
|
||||||
#include "FileOperations/fileops.h"
|
#include "FileOperations/fileops.h"
|
||||||
#include "prompts/PromptWindows.h"
|
#include "prompts/PromptWindows.h"
|
||||||
#include "prompts/ProgressWindow.h"
|
#include "prompts/ProgressWindow.h"
|
||||||
@ -541,23 +541,39 @@ int FeatureSettingsMenu::GetMenuInternal()
|
|||||||
RenameFile(NINUpdatePath, NINUpdatePathBak);
|
RenameFile(NINUpdatePath, NINUpdatePathBak);
|
||||||
|
|
||||||
// Download latest loader.dol as boot.dol
|
// Download latest loader.dol as boot.dol
|
||||||
int filesize = DownloadFileToPath("http://nintendon-t.googlecode.com/svn/trunk/loader/loader.dol", NINUpdatePath, false);
|
bool success = false;
|
||||||
|
displayDownloadProgress(true); // enable progress window for next download
|
||||||
if(filesize <= 0)
|
struct block file = downloadfile("https://raw.githubusercontent.com/FIX94/Nintendont/master/loader/loader.dol");
|
||||||
|
if (file.data != NULL)
|
||||||
{
|
{
|
||||||
RemoveFile(NINUpdatePath);
|
FILE * pfile = fopen(NINUpdatePath, "wb");
|
||||||
if(CheckFile(NINUpdatePathBak))
|
if(pfile)
|
||||||
RenameFile(NINUpdatePathBak, NINUpdatePath);
|
{
|
||||||
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" ));
|
fwrite(file.data, 1, file.size, pfile);
|
||||||
|
fclose(pfile);
|
||||||
|
WindowPrompt(tr( "Successfully Updated" ), 0, tr( "OK" ));
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" ));
|
||||||
|
|
||||||
|
free(file.data);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(success)
|
||||||
{
|
{
|
||||||
//remove existing loader.dol file if found as it has priority over boot.dol, and boot.bak
|
//remove existing loader.dol file if found as it has priority over boot.dol, and boot.bak
|
||||||
snprintf(NINUpdatePath, sizeof(NINUpdatePath), "%s/loader.dol", Settings.NINLoaderPath);
|
snprintf(NINUpdatePath, sizeof(NINUpdatePath), "%s/loader.dol", Settings.NINLoaderPath);
|
||||||
RemoveFile(NINUpdatePath);
|
RemoveFile(NINUpdatePath);
|
||||||
RemoveFile(NINUpdatePathBak);
|
RemoveFile(NINUpdatePathBak);
|
||||||
|
}
|
||||||
WindowPrompt(tr( "Successfully Updated" ), 0, tr( "OK" ));
|
else
|
||||||
|
{
|
||||||
|
// Restore backup file if found
|
||||||
|
RemoveFile(NINUpdatePath);
|
||||||
|
if(CheckFile(NINUpdatePathBak))
|
||||||
|
RenameFile(NINUpdatePathBak, NINUpdatePath);
|
||||||
|
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,10 @@ void GlobalSettings::CreateSettingsMenu(int menuNr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
returnMenu = MENU_THEMEDOWNLOADER;
|
WindowPrompt(tr( "Warning:" ), tr( "Sorry, the theme downloader menu is not working anymore because http://wii.spiffy360.com now requires user registration." ), tr( "OK" ));
|
||||||
|
return;
|
||||||
|
|
||||||
|
// returnMenu = MENU_THEMEDOWNLOADER;
|
||||||
}
|
}
|
||||||
//! Update
|
//! Update
|
||||||
else if(menuNr == Idx++)
|
else if(menuNr == Idx++)
|
||||||
|
@ -134,6 +134,16 @@ s32 IosPatch_RUNTIME(bool wii, bool sciifii, bool vwii, bool verbose);
|
|||||||
*/
|
*/
|
||||||
s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS);
|
s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function patches only SSL certificate check
|
||||||
|
* @param verbose Flag determing whether or not to print messages on-screen.
|
||||||
|
* @example if(AHBPROT_DISABLED) IosPatch_SSL(true);
|
||||||
|
* @return Signed 32bit integer representing code
|
||||||
|
* > 0 : Success - return equals to number of applied patches
|
||||||
|
* ERROR_AHBPROT : Error - No HW_AHBPROT access
|
||||||
|
*/
|
||||||
|
s32 IosPatch_SSL(bool verbose);
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// C++ footer
|
// C++ footer
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
Loading…
Reference in New Issue
Block a user