diff --git a/include/camera.h b/include/camera.h index 49ac53f..a608c98 100644 --- a/include/camera.h +++ b/include/camera.h @@ -36,5 +36,6 @@ bool qr_mode; void init_qr(void); void exit_qr(void); void take_picture(void); +Result http_get(char *url, char *path); #endif \ No newline at end of file diff --git a/source/camera.c b/source/camera.c index bde3800..3af719d 100644 --- a/source/camera.c +++ b/source/camera.c @@ -27,8 +27,8 @@ #include "camera.h" #include "quirc/quirc.h" -#include "pp2d/pp2d/pp2d.h" #include "draw.h" +#include "fs.h" void init_qr(void) { @@ -70,4 +70,122 @@ void take_picture(void) CAMU_StopCapture(PORT_CAM1); svcCloseHandle(cam_handle); CAMU_Activate(PORT_NONE); +} + +/* +Putting this in camera because I'm too lazy to make a network.c +This'll probably get refactored later +*/ +Result http_get(char *url, char *path) +{ + Result ret; + httpcContext context; + char *new_url = NULL; + u32 status_code; + u32 content_size = 0; + u32 read_size = 0; + u32 size = 0; + u8 *buf; + u8 *last_buf; + + do { + ret = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 1); + ret = httpcSetSSLOpt(&context, SSLCOPT_DisableVerify); // should let us do https + ret = httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED); + ret = httpcAddRequestHeaderField(&context, "User-Agent", "Anemone3DS/1.1.0"); + ret = httpcAddRequestHeaderField(&context, "Connection", "Keep-Alive"); + + ret = httpcBeginRequest(&context); + if (ret != 0) + { + httpcCloseContext(&context); + if (new_url != NULL) free(new_url); + return ret; + } + + ret = httpcGetResponseStatusCode(&context, &status_code); + if(ret!=0){ + httpcCloseContext(&context); + if(new_url!=NULL) free(new_url); + return ret; + } + + if ((status_code >= 301 && status_code <= 303) || (status_code >= 307 && status_code <= 308)) + { + if (new_url == NULL) new_url = malloc(0x1000); + ret = httpcGetResponseHeader(&context, "Location", new_url, 0x1000); + url = new_url; + httpcCloseContext(&context); + } + } while ((status_code >= 301 && status_code <= 303) || (status_code >= 307 && status_code <= 308)); + + if (status_code != 200) + { + httpcCloseContext(&context); + if (new_url != NULL) free(new_url); + return ret; + } + + ret = httpcGetDownloadSizeState(&context, NULL, &content_size); + if (ret != 0) + { + httpcCloseContext(&context); + if (new_url != NULL) free(new_url); + return ret; + } + + buf = malloc(0x1000); + if (buf == NULL) + { + httpcCloseContext(&context); + free(new_url); + return -2; + } + + char *content_disposition = malloc(1024); + ret = httpcGetResponseHeader(&context, "Content-Disposition", content_disposition, 1024); + if (ret != 0) + { + free(content_disposition); + free(new_url); + free(buf); + } + + char *filename; + filename = strtok(content_disposition, "\""); + filename = strtok(NULL, "\""); + + do { + ret = httpcDownloadData(&context, buf + size, 0x1000, &read_size); + size += read_size; + + if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING) + { + last_buf = buf; + buf = realloc(buf, size + 0x1000); + if (buf == NULL) + { + httpcCloseContext(&context); + free(last_buf); + return ret; + } + } + } while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING); + + last_buf = buf; + buf = realloc(buf, size); + if (buf == NULL) + { + httpcCloseContext(&context); + free(last_buf); + return -1; + } + + char path_to_file[0x106] = {0}; + strcpy(path_to_file, path); + strcat(path_to_file, filename); + remake_file(path_to_file, ArchiveSD, size); + buf_to_file(size, path_to_file, ArchiveSD, (char*)buf); + + return 0; } \ No newline at end of file diff --git a/source/draw.c b/source/draw.c index e78b482..4f1d80d 100644 --- a/source/draw.c +++ b/source/draw.c @@ -109,6 +109,8 @@ void draw_qr(void) if (!quirc_decode(&code, &data)) { qr_mode = false; + + http_get((char*)data.payload, "/Themes/"); } } } diff --git a/source/main.c b/source/main.c index 79a85bd..a53a05b 100644 --- a/source/main.c +++ b/source/main.c @@ -38,6 +38,7 @@ int init_services(void) { cfguInit(); ptmuInit(); + httpcInit(0); open_archives(); bool homebrew = true; if (!envIsHomebrew()) @@ -59,6 +60,7 @@ int exit_services(void) close_archives(); cfguExit(); ptmuExit(); + httpcExit(); return 0; }