From 0349c6d6572f59770898d3f40287ebdcd2f8ed30 Mon Sep 17 00:00:00 2001 From: Gentoo Date: Sat, 27 Mar 2021 10:36:05 +1100 Subject: initial commit --- source/main.h | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 source/main.h (limited to 'source/main.h') diff --git a/source/main.h b/source/main.h new file mode 100644 index 0000000..c0e35d7 --- /dev/null +++ b/source/main.h @@ -0,0 +1,320 @@ +#ifndef CODEFETCH_H +#define CODEFETCH_H + +//for directories +#include +#include + +#include "gecko.h" + +//green for printf +#define ANSI_COLOUR_GREEN "\x1b[32m" +//set the text colour back to white to reset +#define ANSI_COLOUR_RESET "\x1b[37m" + +//linker complains with .h files +void install_mod(char file[], int row); + +//Webservers decide all the time to transmit less than 4096 bytes at once, so "Content-Length:" conversion is required. +#define CHUNK 4096 + +const static char SERVER[] = "endianness.com"; +const static char REQUEST[] = "GET /root.txt HTTP/1.1\r\n" + "Host: endianness.com\r\n" + "User-Agent: Wii/1.0\r\n\r\n"; +const static char RESP_OK[] = "HTTP/1.1 200 OK"; + +int get_content_length(char buf[]) +{ +char *contentLength = strstr(buf,"Content-Length:"); +if (!contentLength){return -1;}//Content-Length not found + +return (int)strtol(contentLength+16, (void *) strstr(contentLength, "\r")-1, 10);//convert the found content length number string into an integer +} + +//filename is the file+path of file on server. Path is the file+path where it should be saved. Status is set to 0 if no downloading messages are wanted, and to 1 if they are +void download_file(char filename[], char path[], int status) +{ + s32 ret; + + char localip[16] = {0}; + char gateway[16] = {0}; + char netmask[16] = {0}; + + ret = if_config(localip,netmask,gateway,TRUE,10); + + if (status) + { + printf("\n\n\nDownloading %s...", filename); + #ifndef GECKO + gprintf("Downloading %s...", filename); + #endif + } + + struct hostent* hostp; + struct sockaddr_in serveraddr; + + s32 sock; + sock = net_socket(AF_INET,SOCK_STREAM,0); + memset(&serveraddr, 0x00,sizeof(struct sockaddr_in)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_port = htons(80); + hostp = net_gethostbyname(SERVER); + //copy the address from the looked up host to serveraddr + memcpy(&serveraddr.sin_addr,hostp->h_addr,sizeof(serveraddr.sin_addr)); + + //connect to the server + ret = net_connect(sock,(struct sockaddr*) &serveraddr,sizeof(serveraddr)); + + //The length of the filename and path is required for later + int fileLength = strlen(filename)+1; + int pathLength = strlen(path)+1; + + char fileRequest[strlen(REQUEST)+fileLength];//size of original REQUEST and fileLength is long enough +// printf("Request Length: %d\n", strlen(REQUEST)+fileLength); + + //generate the request for the requested file + ssize_t requestLen = sprintf(fileRequest, "GET /%s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Wii/1.0\r\n\r\n", filename, SERVER); + + ret = net_write(sock, fileRequest, requestLen);//send file request to server + if(ret < 0) + { + printf("Write failed!\n"); + gprintf("Write failed!"); + net_close(sock); + exit(1); + } + + char buff[CHUNK+2]; + + ssize_t n = net_read(sock, buff, CHUNK); + if (!n) + { + printf("Recieve failed\n"); + gprintf("Recieve failed"); + exit(1); + } + +// printf("Length of total header: %d\n", n); + +// buff[n] = '\0'; //add null terminator + +// printf("Header: %s", buff); + + int contentLength = get_content_length(buff); + if (contentLength < 0) + { + printf("Invalid content length recieved!\n"); + gprintf("Invalid content length recieved!"); + exit(1); + } + + if (status) + { + printf("%d bytes to download\n", contentLength); + gprintf("%d bytes to download", contentLength); + } + int total = 0;//total number of bytes read + + if (memcmp(buff, RESP_OK, strlen(RESP_OK)) != 0)//make sure that the file was found + { + printf("File not found or another error\n"); + gprintf("File not found or another error"); + exit(1); + } + + char *startOfData = strstr(buff,"\r\n\r\n")+4; //the start of the data + if (!startOfData) + { + printf("Recieved HTTP header malformed!\n"); + gprintf("Recieved HTTP header malformed!"); + exit(1); + } + + int len = n - (startOfData-buff);//subtract the amount of bytes in the header from n to get the lenght of the data in body + //printf("Length of Data in header: %d\n", len); + + total += len; //Only the content counts in total + + char newPath[pathLength+4]; + sprintf(newPath, "sd:/%s", path);//generate the path + + gprintf("Generated path: %s", newPath); + + FILE *fp = fopen(newPath,"wb"); + if (!fp) + { + printf("Could not open %s!\n", newPath); + gprintf("Could not open %s!", newPath); + exit(1); + } + int result = fwrite(startOfData, 1, len, fp);//write first read results to sd excluding header + if (result < 0){printf("Could not write to %s!\n", path); exit(1);} + + gprintf("Bytes read: %d", total); + if (total == contentLength){goto complete;}//if total is the same size as cotentlength, no more reading needs to be done since the first read did it all + + //read the rest of the data + while (1) + { + n = net_read(sock, buff, CHUNK);//recieve up to CHUNK bytes from server. (The server may decide to send a lot less); + if (!n){printf("Could not read!\n"); exit(1);} + total += n; //add n to total + printf("\b\rRecieved: %d Bytes ", total); + gprintf("\b\rRecieved: %d Bytes ", total); + if (total == contentLength)//if total equals contentLength, reading is done + { + n = fwrite(buff, 1, n, fp);//attempt to write the chunk to sd + if (n < 0){printf("Could not write to %s!\n", newPath); exit(1);} +// printf("Secondary no more reading required\n"); + break; + } + n = fwrite(buff, 1, n, fp);//attempt to write the chunk to sd + if (n < 0) + { + printf("Could not write to %s!\n", newPath); + gprintf("Could not write to %s!", newPath); + exit(1);} + } + + complete:; + + fclose(fp); + net_close(sock); + if (status) + { + printf("\nDone downloading %s\n", path); + gprintf("Done downloading %s", path); + } + return; +} + + +void create_folders(char path[]) +{ + if (!strstr(path,"/")){return;}//no need to create folders if the file is in the root directory + + char newPath[strlen(path)+4];//need to have enough space for "sd:/" + sprintf(newPath, "sd:/%s", path); + + int i; + for (i=strlen(newPath); newPath[i] != '/';--i);//find first '/' from the back. + newPath[i] = '\0';//overwrite the '/' with a null char so a dir named after the file isn't created + + int result; + struct stat st; + if (stat(newPath, &st) != 0){goto makeFullPath;}//fullpath does not exist + else + { + gprintf("Fullpath exists"); + return; + } + + makeFullPath: ; + i = 0; + while(1) + { + char *folder = strstr(path+i, "/"); + if (!folder)//if '/' is not found, we have reached the file. + { + //printf("Directory's created\n"); + return; + } + + *folder = '\0';//overwrite '/' with a null char + i=strlen(path)+1; //i equals the position of found '/'+1 so strstr finds the next '/' instead. + + sprintf(newPath, "sd:/%s", path); + gprintf("Making: %s", newPath); + + result = mkdir(newPath, 0777);//make the dir + if (result == -1) + { + if (errno == EEXIST) + { + gprintf("%s already exists", newPath); + } + else if (errno == ENOENT){printf("Parents of %s do not exist\n", newPath); exit(1);} + else{printf("Could not create %s\n", newPath); exit(1);} + } + + *folder = '/'; //replace the null char with '/' for next dir + } +return; +} + + +int parse_root_txt(char file[]) +{ +int modCount = 0;//the number of mods extracted + +FILE *fp = fopen(file, "r"); +if (!fp) + { + printf("Could not open %s\n", file); + gprintf("Could not open %s\n", file); + exit(1); + } + +fseek(fp, 0L, SEEK_END);//seek to the end of the file +int size = ftell(fp);//store lenght of file +rewind(fp);//seek back to start of file + +char buff[size]; +buff[size] = '\0';//add null char to end of buff + +char *colon = buff;//location of colon +char *secondColon = buff;//location of second colon +char *newLine = buff; //location of newline + +while(1) + { + if (fgets(buff, size, fp) == NULL){break;}//get a single line from fp to buff + colon = strstr(buff,":");//find colon in buff + if (!colon) + { + printf("root.txt malformed!0\n"); + gprintf("root.txt malformed!0"); + exit(1); + } + + secondColon = strstr(colon+1,":");//find second colon in buff + if (!secondColon) + { + printf("root.txt malformed!1\n"); + gprintf("root.txt malformed!1"); + exit(1); + } + *secondColon = '\0'; //replace second colon with null char + + newLine = strstr(secondColon+1,"\n");//find newline in buff + if (!newLine) + { + printf("root.txt malformed!6\n"); + gprintf("root.txt malformed!6"); + exit(1); + } + *newLine = '\0'; //replace newline with null char + + char elfPath[strlen(secondColon+1)+4]; + sprintf(elfPath, "sd:/%s", secondColon+1); + FILE *boot_elf = fopen(elfPath, "r"); + if (boot_elf){printf(" %s%s%s\n", ANSI_COLOUR_GREEN, colon+1, ANSI_COLOUR_RESET); fclose(boot_elf);}//make mod name green if elf is found + else {printf(" %s\n", colon+1);} + + ++modCount;//increase the mod count + } +if (!modCount) + { + printf("root.txt malformed!2\n"); + gprintf("root.txt malformed!2"); + exit(1); + } + +//move cursor back to start of the row +printf("\033[%dD", strlen(colon+1)); + +fclose(fp); +return --modCount;//return the number of lines printed (-1 to make the number correct) +} +#endif -- cgit v1.2.3