Skip to content

Commit

Permalink
Part of #2
Browse files Browse the repository at this point in the history
  • Loading branch information
luigoalma committed Nov 3, 2018
1 parent 957d4d6 commit 203d526
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 47 deletions.
14 changes: 10 additions & 4 deletions CDN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ void NintendoData::CDN::Download(const char* outdir) {
manager.SetAttribute(DownloadManager::HEADER, "X-Authentication-Key: %s", b64_encticketkey)
.SetAttribute(DownloadManager::HEADER, "X-Authentication-Data: %s", b64_encticket);
try {
manager.SetAttribute(DownloadManager::FILENAME, "tmd")
.SetAttribute(DownloadManager::URL, "%s/%016llX/tmd", baseurl, GetTitleId())
.SetAttribute(DownloadManager::BUFFER, true)
manager.SetAttribute(DownloadManager::BUFFER, true)
.SetAttribute(DownloadManager::PROGRESS, true);
if(!nodownload) manager.SetAttribute(DownloadManager::OUTPATH, "%s/tmd", outdir);
if(set_version) {
manager.SetAttribute(DownloadManager::FILENAME, "tmd.%d", version)
.SetAttribute(DownloadManager::URL, "%s/%016llX/tmd.%d", baseurl, GetTitleId(), version);
if(!nodownload) manager.SetAttribute(DownloadManager::OUTPATH, "%s/tmd.%d", outdir, version);
} else {
manager.SetAttribute(DownloadManager::FILENAME, "tmd")
.SetAttribute(DownloadManager::URL, "%s/%016llX/tmd", baseurl, GetTitleId());
if(!nodownload) manager.SetAttribute(DownloadManager::OUTPATH, "%s/tmd", outdir);
}
auto tmddownloader = manager.GetDownloader();
if(!tmddownloader.Download()) throw std::runtime_error("Failed to download TMD");
tmdbuffer = (u8*)tmddownloader.GetBufferAndDetach(tmdlen);
Expand Down
11 changes: 9 additions & 2 deletions CDN.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace NintendoData {
private:
Ticket tik;
::DownloadManager manager;
u16 version;
bool set_version;
bool nodownload;
public:
template<typename... Args> CDN& SetProxy(const char* str, Args... args) noexcept {
Expand All @@ -32,6 +34,11 @@ namespace NintendoData {
if(nodownload) SetHeaderPrint(true);
return *this;
}
CDN& SetVersion(u16 version) noexcept {
this->version = version;
this->set_version = true;
return *this;
}
u64 GetTitleId() const noexcept {return tik.TitleID();}
void Download(const char* outdir);
private:
Expand All @@ -40,8 +47,8 @@ namespace NintendoData {
.SetAttribute(DownloadManager::HEADER, "Connection: Keep-Alive");
}
public:
CDN(const Ticket& ticket) : tik(ticket, true), nodownload(false) {Init();}
CDN(const void* ticket, size_t ticketlen) : tik(ticket, ticketlen, true), nodownload(false) {Init();}
CDN(const Ticket& ticket) : tik(ticket, true), set_version(false), nodownload(false) {Init();}
CDN(const void* ticket, size_t ticketlen) : tik(ticket, ticketlen, true), set_version(false), nodownload(false) {Init();}
~CDN() noexcept {}
};
}
Expand Down
36 changes: 17 additions & 19 deletions DownloadManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ size_t DownloadManager::Downloader::write_data(void *ptr, size_t size, size_t nm
size_t foobar = _this->buffer_data.size + realsize;
if(_this->buffer_data.size != foobar){ //incase this function is called when realsize = 0
u8* foo = (u8*)realloc(_this->buffer_data.buffer, foobar);
if(foo) {
_this->buffer_data.buffer = foo;
memcpy((void*)(&((char*)_this->buffer_data.buffer)[_this->buffer_data.size]), ptr, realsize);
_this->buffer_data.size = foobar;
if(!_this->out) return realsize; //if no file, return now, to continue with download to buffer
} else {
if(!foo) {
free(_this->buffer_data.buffer);
_this->buffer_data.buffer = NULL;
return 0; //abort
}
_this->buffer_data.buffer = foo;
memcpy((void*)(&((char*)_this->buffer_data.buffer)[_this->buffer_data.size]), ptr, realsize);
_this->buffer_data.size = foobar;
if(!_this->out) return realsize; //if no file, return now, to continue with download to buffer
}
}
if(_this->out) {
Expand All @@ -56,19 +55,18 @@ size_t DownloadManager::Downloader::headerprint(void *ptr, size_t size, size_t n
Downloader* _this = (Downloader*)data;
size_t realsize = size*nmemb;
size_t foobar = _this->header_data.size + realsize;
if(_this->header_data.size != foobar){ //incase this function is called when realsize = 0
u8* foo = (u8*)realloc(_this->header_data.buffer, foobar);
if(foo) {
_this->header_data.buffer = foo;
memcpy((void*)(&((char*)_this->header_data.buffer)[_this->header_data.size]), ptr, realsize);
_this->header_data.size = foobar;
return realsize;
} else {
free(_this->header_data.buffer);
_this->header_data.buffer = NULL;
return 0; //abort
}
} else return 0;
if(_this->header_data.size == foobar) //incase this function is called when realsize = 0
return 0;
u8* foo = (u8*)realloc(_this->header_data.buffer, foobar);
if(!foo) {
free(_this->header_data.buffer);
_this->header_data.buffer = NULL;
return 0; //abort
}
_this->header_data.buffer = foo;
memcpy((void*)(&((char*)_this->header_data.buffer)[_this->header_data.size]), ptr, realsize);
_this->header_data.size = foobar;
return realsize;
}

DownloadManager::Downloader::Downloader(DownloadManager& data) : outpath(NULL), curl_handle(NULL), chunk(NULL), progress({}), buffer_data({}), header_data({}), res((CURLcode)~CURLE_OK) {
Expand Down
108 changes: 86 additions & 22 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,13 @@ static void loadcerts(u8*& ptr, const char* proxy) {
}

struct arguments {
struct entry {
const char* path = NULL;
u16 version = 0;
bool latest = true;
};
const char* proxy = NULL;
std::vector<const char*> files;
std::vector<struct entry> files;
bool printhelp = false;
bool useforcetkregardless = false;
bool printresponseheaders = false;
Expand Down Expand Up @@ -123,6 +128,28 @@ static const char* checkifvalidticket(const char* ptr) {
return NULL;
}

static bool parse_a_title(std::string& strerr, struct arguments& args, int i, char** argv) {
const char* reason;
if((reason = checkifvalidticket(argv[i])) != NULL) {
strerr += "Argument ignored: ";
strerr += argv[i];
strerr += "\n ";
strerr += reason;
strerr += "\n";
return false;
}
bool found = false;
for(size_t foo = 0; foo < args.files.size(); foo++)
if(!strcmp(argv[i], args.files[foo].path)) {
found = true;
break;
}
struct arguments::entry newentry;
newentry.path = argv[i];
if(!found) args.files.push_back(newentry);
return !found;
}

//Clean? Nope. Works? yup.
//Enjoy indentation mess.
static void parse_args(struct arguments& args, int argc, char** argv) {
Expand All @@ -131,22 +158,7 @@ static void parse_args(struct arguments& args, int argc, char** argv) {
for(int i = 1; i < argc; i++) {
if(!*argv[i]) continue; //?? shouldn't happen but I'll leave it in as a fail safe..
if(*argv[i] != '-') {
const char* reason;
if((reason = checkifvalidticket(argv[i])) != NULL) {
strerr += "Argument ignored: ";
strerr += argv[i];
strerr += "\n ";
strerr += reason;
strerr += "\n";
continue;
}
bool found = false;
for(size_t foo = 0; foo < args.files.size(); foo++)
if(!strcmp(argv[i], args.files[foo])) {
found = true;
break;
}
if(!found) args.files.push_back(argv[i]);
parse_a_title(strerr, args, i, argv);
continue;
}
if(!argv[i][1]) {
Expand Down Expand Up @@ -181,6 +193,32 @@ static void parse_args(struct arguments& args, int argc, char** argv) {
args.nodownload = true;
args.printresponseheaders = true;
break;
case 'v':
if(!argv[i + 1] || !argv[i + 2]) {
strerr += "Argument ignored: v\n No more arguments.\n";
continue;
}
if(!parse_a_title(strerr, args, i + 2, argv)) {
i+=2;
strerr += "Argument ignored: v\n Bad ticket path.\n";
continue;
}
{
auto version = strtoul(argv[i + 1], NULL, 0);
if(version > 0xffff) {
args.files.pop_back();
strerr += "Argument ignored: v\n Bad Version.\n Won't process:\n ";
strerr += argv[i + 2];
strerr += "\n";
i+=2;
continue;
}
auto index = args.files.size()-1;
args.files[index].version = version;
args.files[index].latest = false;
}
i+=2;
break;
default:
strerr += "Argument ignored: ";
strerr += argv[current][j];
Expand Down Expand Up @@ -222,6 +260,31 @@ static void parse_args(struct arguments& args, int argc, char** argv) {
args.printresponseheaders = true;
continue;
}
if(!strcmp(&argv[i][2], "version")) {
if(!argv[i + 1] || !argv[i + 2]) {
strerr += "Argument ignored: v\n No more arguments.\n";
continue;
}
if(!parse_a_title(strerr, args, i + 2, argv)) {
i+=2;
strerr += "Argument ignored: v\n Bad ticket path.\n";
continue;
}
auto version = strtoul(argv[i + 1], NULL, 0);
if(version > 0xffff) {
args.files.pop_back();
strerr += "Argument ignored: v\n Bad Version.\n Won't process:\n ";
strerr += argv[i + 2];
strerr += "\n";
i+=2;
continue;
}
auto index = args.files.size()-1;
args.files[index].version = version;
args.files[index].latest = false;
i+=2;
continue;
}
if(!strcmp(&argv[i][2], "help") || !strcmp(&argv[i][2], "usage")) {
args.printhelp = true;
throw 0;
Expand Down Expand Up @@ -269,14 +332,14 @@ int main(int argc, char** argv) {
}
for(size_t i = 0; i < args.files.size(); i++) {
//this only supports RSA_2048_SHA256 type and Root-CA00000003-XS0000000c issuer tickets.
FILE *fp = fopen(args.files[i], "rb");
FILE *fp = fopen(args.files[i].path, "rb");
if(!fp) {
fprintf(stderr, "Failed to open \"%s\". Skipping...\n", args.files[i]);
fprintf(stderr, "Failed to open \"%s\". Skipping...\n", args.files[i].path);
continue;
}
auto readtotal = fread(tikbuffer, 1, 848, fp);
if(readtotal != 848) {
fprintf(stderr, "Failed to read 848 bytes from \"%s\". Skipping...\n", args.files[i]);
fprintf(stderr, "Failed to read 848 bytes from \"%s\". Skipping...\n", args.files[i].path);
fclose(fp);
continue;
}
Expand All @@ -291,7 +354,7 @@ int main(int argc, char** argv) {
break;
}
if(skip) {
printf("Skipping \"%s\", already downloaded title from ticket.\n", args.files[i]);
printf("Skipping \"%s\", already downloaded title from ticket.\n", args.files[i].path);
continue;
}
if(!args.useforcetkregardless && (tik.eShopID() || tik.ConsoleID())) {
Expand All @@ -315,6 +378,7 @@ int main(int argc, char** argv) {
cdnaccess.SetNoDownload(true);
outpath = NULL;
}
if(!args.files[i].latest) cdnaccess.SetVersion(args.files[i].version);
cdnaccess.Download(outpath);
if(!args.nodownload) {
snprintf(outpath, len+1, "%016llX/cetk", (unsigned long long)cdnaccess.GetTitleId());
Expand All @@ -335,7 +399,7 @@ int main(int argc, char** argv) {
fflush(stdout);
fprintf(stderr, "Something prevented the program to download target.\n"
"Skipping \"%s\"...\n"
"Caugth exception message: %s\n\n", args.files[i], e.what());
"Caugth exception message: %s\n\n", args.files[i].path, e.what());
free(outpath);
outpath = NULL;
continue;
Expand Down

0 comments on commit 203d526

Please sign in to comment.