mirror of
https://github.com/Maschell/libutils.git
synced 2024-12-27 04:11:55 +01:00
Added a FileDownloader, bases on the one from loadiine
This commit is contained in:
parent
94d64db894
commit
a8305b55b4
3
Makefile
3
Makefile
@ -22,6 +22,7 @@ SOURCES := source \
|
||||
source/fs \
|
||||
source/utils \
|
||||
source/language \
|
||||
source/network \
|
||||
source/system \
|
||||
source/kernel
|
||||
INCLUDES := include \
|
||||
@ -106,12 +107,14 @@ install:
|
||||
@mkdir -p $(INCLUDEDIR)/utils/
|
||||
@mkdir -p $(INCLUDEDIR)/kernel/
|
||||
@mkdir -p $(INCLUDEDIR)/system/
|
||||
@mkdir -p $(INCLUDEDIR)/network/
|
||||
@mkdir -p $(INCLUDEDIR)/language/
|
||||
@mkdir -p $(INCLUDEDIR)/fs/
|
||||
@cp source/utils/*.h $(INCLUDEDIR)/utils/
|
||||
@cp source/utils/*.hpp $(INCLUDEDIR)/utils/
|
||||
@cp source/system/*.h $(INCLUDEDIR)/system/
|
||||
@cp source/language/*.h $(INCLUDEDIR)/language/
|
||||
@cp source/network/*.h $(INCLUDEDIR)/network/
|
||||
@cp source/fs/*.h $(INCLUDEDIR)/fs/
|
||||
@cp source/fs/*.hpp $(INCLUDEDIR)/fs/
|
||||
@cp source/kernel/*.h $(INCLUDEDIR)/kernel/
|
||||
|
185
source/network/FileDownloader.cpp
Normal file
185
source/network/FileDownloader.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016 Dimok
|
||||
* Modified by Maschell, 2018
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "FileDownloader.h"
|
||||
#include <dynamic_libs/curl_functions.h>
|
||||
#include "utils/logger.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
|
||||
bool FileDownloader::getFile(const std::string & downloadUrl, std::string & fileBuffer, ProgressCallback callback, void *arg) {
|
||||
curl_private_data_t private_data;
|
||||
private_data.progressCallback = callback;
|
||||
private_data.progressArg = arg;
|
||||
private_data.buffer = 0;
|
||||
private_data.filesize = 0;
|
||||
private_data.file = 0;
|
||||
|
||||
bool result = internalGetFile(downloadUrl, &private_data);
|
||||
|
||||
if(private_data.filesize > 0 && private_data.buffer) {
|
||||
fileBuffer.resize(private_data.filesize);
|
||||
memcpy(&fileBuffer[0], private_data.buffer, private_data.filesize);
|
||||
}
|
||||
|
||||
if(private_data.buffer) {
|
||||
free(private_data.buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FileDownloader::getFile(const std::string & downloadUrl, const std::string & outputPath, ProgressCallback callback, void *arg) {
|
||||
curl_private_data_t private_data;
|
||||
private_data.progressCallback = callback;
|
||||
private_data.progressArg = arg;
|
||||
private_data.buffer = 0;
|
||||
private_data.filesize = 0;
|
||||
|
||||
s32 res = open(outputPath.c_str(), O_CREAT | O_TRUNC | O_WRONLY);
|
||||
close(res);
|
||||
|
||||
private_data.file = new CFile(outputPath.c_str(), CFile::WriteOnly);
|
||||
|
||||
if(!private_data.file->isOpen()) {
|
||||
delete private_data.file;
|
||||
DEBUG_FUNCTION_LINE("Can not write to file %s\n", outputPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = internalGetFile(downloadUrl, &private_data);
|
||||
|
||||
private_data.file->close();
|
||||
delete private_data.file;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FileDownloader::internalGetFile(const std::string & downloadUrl, curl_private_data_t * private_data) {
|
||||
bool result = false;
|
||||
int resp = 404;
|
||||
int ret = -1;
|
||||
CURL * curl = n_curl_easy_init();
|
||||
if(!curl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int ssl_context = -1;
|
||||
|
||||
std::string prefix = "https";
|
||||
if(strncmp(downloadUrl.c_str(), prefix.c_str(), prefix.size()) == 0) {
|
||||
DEBUG_FUNCTION_LINE("Needs a SSL context\n");
|
||||
ssl_context = NSSLCreateContext(0);
|
||||
if(ssl_context < 0) {
|
||||
DEBUG_FUNCTION_LINE("Failed to create SSL Context\n");
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
// Add all existing certs
|
||||
for(int i = 100; i<106; i++) {
|
||||
NSSLAddServerPKI(ssl_context,i);
|
||||
}
|
||||
|
||||
for(int i = 1001; i<1034; i++) {
|
||||
NSSLAddServerPKI(ssl_context,i);
|
||||
}
|
||||
n_curl_easy_setopt(curl, CURLOPT_GSSAPI_DELEGATION, ssl_context); // Is CURLOPT_NSSL_CONTEXT on the Wii U
|
||||
}
|
||||
|
||||
n_curl_easy_setopt(curl, CURLOPT_URL, downloadUrl.c_str());
|
||||
n_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FileDownloader::curlCallback);
|
||||
n_curl_easy_setopt(curl, CURLOPT_WRITEDATA, private_data);
|
||||
n_curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
//n_curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
|
||||
if(private_data->progressCallback) {
|
||||
n_curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, FileDownloader::curlProgressCallback);
|
||||
n_curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, private_data);
|
||||
n_curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
}
|
||||
|
||||
ret = n_curl_easy_perform(curl);
|
||||
if(ret) {
|
||||
DEBUG_FUNCTION_LINE("n_curl_easy_perform ret %i\n", ret);
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
if(!private_data->filesize) {
|
||||
DEBUG_FUNCTION_LINE("file length is 0\n");
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
n_curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp);
|
||||
|
||||
if(resp != 200) {
|
||||
DEBUG_FUNCTION_LINE("response != 200\n");
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
exit_error:
|
||||
if(ssl_context >= 0) {
|
||||
NSSLDestroyContext(ssl_context);
|
||||
}
|
||||
|
||||
n_curl_easy_cleanup(curl);
|
||||
return result;
|
||||
}
|
||||
|
||||
int FileDownloader::curlCallback(void *buffer, int size, int nmemb, void *userp) {
|
||||
curl_private_data_t *private_data = (curl_private_data_t *)userp;
|
||||
int read_len = size*nmemb;
|
||||
|
||||
if(private_data->file) {
|
||||
int res = private_data->file->write((u8*)buffer, read_len);
|
||||
private_data->filesize += res;
|
||||
return res;
|
||||
} else {
|
||||
if(!private_data->buffer) {
|
||||
private_data->buffer = (u8*) malloc(read_len);
|
||||
} else {
|
||||
u8 *tmp = (u8*) realloc(private_data->buffer, private_data->filesize + read_len);
|
||||
if(!tmp) {
|
||||
free(private_data->buffer);
|
||||
private_data->buffer = NULL;
|
||||
} else {
|
||||
private_data->buffer = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if(!private_data->buffer) {
|
||||
private_data->filesize = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(private_data->buffer + private_data->filesize, buffer, read_len);
|
||||
private_data->filesize += read_len;
|
||||
return read_len;
|
||||
}
|
||||
}
|
||||
|
||||
int FileDownloader::curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) {
|
||||
curl_private_data_t *private_data = (curl_private_data_t *)clientp;
|
||||
if(private_data->progressCallback) {
|
||||
private_data->progressCallback(private_data->progressArg, (u32)dlnow, (u32)dltotal);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
46
source/network/FileDownloader.h
Normal file
46
source/network/FileDownloader.h
Normal file
@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016 Dimok
|
||||
* Modified by Maschell, 2018
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#ifndef _FILE_DOWNLOADER_H
|
||||
#define _FILE_DOWNLOADER_H
|
||||
|
||||
#include <string>
|
||||
#include "fs/CFile.hpp"
|
||||
|
||||
class FileDownloader
|
||||
{
|
||||
public:
|
||||
typedef void (*ProgressCallback)(void *arg, u32 done, u32 total);
|
||||
|
||||
static bool getFile(const std::string & downloadUrl, std::string & fileBuffer, ProgressCallback callback = 0, void *arg = 0);
|
||||
static bool getFile(const std::string & downloadUrl, const std::string & outputPath, ProgressCallback callback = 0, void *arg = 0);
|
||||
private:
|
||||
typedef struct
|
||||
{
|
||||
ProgressCallback progressCallback;
|
||||
void *progressArg;
|
||||
CFile * file;
|
||||
u8 *buffer;
|
||||
u32 filesize;
|
||||
} curl_private_data_t;
|
||||
|
||||
static bool internalGetFile(const std::string & downloadUrl, curl_private_data_t * private_data);
|
||||
static int curlCallback(void *buffer, int size, int nmemb, void *userp);
|
||||
static int curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
|
||||
};
|
||||
|
||||
#endif // _FILE_DOWNLOADER_H
|
Loading…
Reference in New Issue
Block a user