#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