summaryrefslogtreecommitdiffstats
path: root/source/main.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/main.h')
-rw-r--r--source/main.h320
1 files changed, 320 insertions, 0 deletions
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 <errno.h>
+#include <sys/stat.h>
+
+#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