/**************************************************************************** * http_request * Retrieves the specified URL, and stores it in the specified file or buffer ***************************************************************************/ int http_request(const char *url, FILE *hfile, u8 *buffer, u32 maxsize, bool silent) { int res = 0; char http_host[1024]; char http_path[1024]; u16 http_port; http_res result; u32 http_status; u32 sizeread = 0, content_length = 0; int linecount; if(maxsize > MAX_SIZE) return 0; if (url == NULL || (hfile == NULL && buffer == NULL)) return 0; if (!http_split_url(http_host, http_path, url)) return 0; http_port = 80; http_status = 404; int s = tcp_connect(http_host, http_port); if (s < 0) { result = HTTPR_ERR_CONNECT; return 0; } char request[1024]; char *r = request; r += sprintf(r, "GET %s HTTP/1.1\r\n", http_path); r += sprintf(r, "Host: %s\r\n", http_host); r += sprintf(r, "Cache-Control: no-cache\r\n\r\n"); res = tcp_write(s, (u8 *) request, strlen(request)); char line[256]; for (linecount = 0; linecount < 32; linecount++) { if (tcp_readln(s, line, 255) != 0) { http_status = 404; result = HTTPR_ERR_REQUEST; break; } if (strlen(line) < 1) break; sscanf(line, "HTTP/1.%*u %u", &http_status); sscanf(line, "Content-Length: %u", &content_length); } if (http_status != 200) { result = HTTPR_ERR_STATUS; net_close(s); return 0; } // length unknown - just read as much as we can if(content_length == 0) { content_length = maxsize; } else if (content_length > maxsize) { result = HTTPR_ERR_TOOBIG; net_close(s); return 0; } if (buffer != NULL) { if(!silent) ShowAction("Downloading..."); sizeread = tcp_read(s, buffer, content_length); if(!silent) CancelAction(); } else { // read into file u32 bufSize = (1024 * 32); u32 bytesLeft = content_length; u32 readSize; if(!silent) ShowProgress("Downloading...", 0, content_length); u8 * fbuffer = (u8 *) malloc(bufSize); if(fbuffer) { while (bytesLeft > 0) { if (bytesLeft < bufSize) readSize = bytesLeft; else readSize = bufSize; res = tcp_read(s, fbuffer, readSize); if (!res) break; sizeread += res; bytesLeft -= res; res = fwrite(fbuffer, 1, res, hfile); if (!res) break; if(!silent) ShowProgress("Downloading...", (content_length - bytesLeft), content_length); } free(fbuffer); } if(!silent) CancelAction(); } net_close(s); if (content_length < maxsize && sizeread != content_length) { result = HTTPR_ERR_RECEIVE; return 0; } result = HTTPR_OK; return sizeread; }
bool http_post (const char *url, const u32 max_size, const char *postData) { int linecount; if (!http_split_url(&http_host, &http_path, url)) return false; http_port = 80; http_max_size = max_size; http_status = 404; content_length = 0; http_data = NULL; int s = tcp_connect (http_host, http_port); if (s < 0) { result = HTTPR_ERR_CONNECT; return false; } char *request = (char *) memalign (32, 1024*6); snprintf(request, 1024*6, "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "Content-type: application/x-www-form-urlencoded\r\n" "Content-length: %d\r\n\r\n" "%s", http_path, http_host, strlen(postData), postData); gprintf("\n request:\n"); //gprintf(request); gprintf("\n :request\n"); bool b = tcp_write (s, (u8 *) request, strlen (request)); free (request); linecount = 0; for (linecount=0; linecount < 32; linecount++) { char *line = tcp_readln (s, 0xff, gettime(), (u16)HTTP_TIMEOUT); if (!line) { http_status = 404; result = HTTPR_ERR_REQUEST; break; } if (strlen (line) < 1) { free (line); line = NULL; break; } sscanf (line, "HTTP/1.%*u %u", &http_status); sscanf (line, "Content-Length: %u", &content_length); gprintf(line); gprintf("\n"); free (line); line = NULL; } if (linecount == 32 || !content_length) http_status = 404; if (http_status != 200) { result = HTTPR_ERR_STATUS; net_close (s); return false; } if (content_length > http_max_size) { result = HTTPR_ERR_TOOBIG; net_close (s); return false; } http_data = (u8 *) memalign (32, content_length); b = tcp_read (s, &http_data, content_length); if (!b) { free (http_data); http_data = NULL; result = HTTPR_ERR_RECEIVE; net_close (s); return false; } result = HTTPR_OK; net_close (s); return true; }
bool http_request (const char *url, const u32 max_size) { int linecount; if (!http_split_url(&http_host, &http_path, url)) return false; http_port = 80; http_max_size = max_size; http_status = 404; content_length = 0; http_data = NULL; int s = tcp_connect (http_host, http_port); // printDebugMsg(NORMAL_DEBUG_MESSAGE,"tcp_connect(%s, %hu) = %d\n", http_host, http_port, s); if (s < 0) { result = HTTPR_ERR_CONNECT; return false; } char *request = (char *) malloc (1024); char *r = request; r += sprintf (r, "GET %s HTTP/1.1\r\n", http_path); r += sprintf (r, "Host: %s\r\n", http_host); r += sprintf (r, "Cache-Control: no-cache\r\n\r\n"); // printDebugMsg(NORMAL_DEBUG_MESSAGE,"request = %s\n", request); bool b = tcp_write (s, (u8 *) request, strlen (request)); // printDebugMsg(NORMAL_DEBUG_MESSAGE,"tcp_write returned %d\n", b); free (request); linecount = 0; for (linecount=0; linecount < 32; linecount++) { char *line = tcp_readln (s, 0xff, gettime(), HTTP_TIMEOUT); // printDebugMsg(NORMAL_DEBUG_MESSAGE,"tcp_readln returned %p (%s)\n", line, line?line:"(null)"); if (!line) { http_status = 404; result = HTTPR_ERR_REQUEST; break; } if (strlen (line) < 1) { free (line); line = NULL; break; } sscanf (line, "HTTP/1.1 %u", &http_status); sscanf (line, "Content-Length: %u", &content_length); free (line); line = NULL; } // printDebugMsg(NORMAL_DEBUG_MESSAGE,"content_length = %d, status = %d, linecount = %d\n", content_length, http_status, linecount); if (linecount == 32 || !content_length) http_status = 404; if (http_status != 200) { result = HTTPR_ERR_STATUS; net_close (s); return false; } if (content_length > http_max_size) { result = HTTPR_ERR_TOOBIG; net_close (s); return false; } http_data = (u8 *) malloc (content_length); b = tcp_read (s, &http_data, content_length); if (!b) { free (http_data); http_data = NULL; result = HTTPR_ERR_RECEIVE; net_close (s); return false; } result = HTTPR_OK; net_close (s); return true; }
bool http_request (const char *url, const u32 max_size) { int linecount; int sslcontext = -1; if (!http_split_url(&http_host, &http_path, url)) return false; if (strncasecmp (url, "http://", 7) == 0) http_port = 80; else http_port = 443; http_max_size = max_size; http_status = 404; content_length = 0; http_data = NULL; int s = tcp_connect (http_host, http_port); if (s < 0) { result = HTTPR_ERR_CONNECT; return false; } if(http_port == 443) { //patched out anyways so just to set something sslcontext = ssl_new((u8*)http_host,0); if(sslcontext < 0) { gprintf("ssl_new\n"); result = HTTPR_ERR_CONNECT; net_close (s); return false; } //patched out anyways so just to set something ssl_setbuiltinclientcert(sslcontext,0); if(ssl_connect(sslcontext,s) < 0) { gprintf("ssl_connect\n"); result = HTTPR_ERR_CONNECT; ssl_shutdown(sslcontext); net_close (s); return false; } int ret = ssl_handshake(sslcontext); if(ret < 0) { gprintf("ssl_handshake %i\n", ret); result = HTTPR_ERR_STATUS; ssl_shutdown(sslcontext); net_close (s); return false; } } char *request = (char *) memalign (32, 1024*2); snprintf(request, 1024*2, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Cache-Control: no-cache\r\n\r\n", http_path, http_host); bool b = tcp_write (http_port == 443 ? sslcontext : s, (u8 *) request, strlen (request)); free (request); linecount = 0; for (linecount=0; linecount < 32; linecount++) { char *line = tcp_readln (http_port == 443 ? sslcontext : s, 0xff, gettime(), (u16)HTTP_TIMEOUT); if (!line) { http_status = 404; result = HTTPR_ERR_REQUEST; break; } if (strlen (line) < 1) { free (line); line = NULL; break; } sscanf (line, "HTTP/1.%*u %u", &http_status); sscanf (line, "Content-Length: %u", &content_length); gprintf(line); gprintf("\n"); free (line); line = NULL; } if (linecount == 32 || !content_length) http_status = 404; if (http_status != 200) { result = HTTPR_ERR_STATUS; if(http_port == 443) ssl_shutdown(sslcontext); net_close (s); return false; } if (content_length > http_max_size) { result = HTTPR_ERR_TOOBIG; if(http_port == 443) ssl_shutdown(sslcontext); net_close (s); return false; } http_data = (u8 *) memalign (32, content_length); b = tcp_read (http_port == 443 ? sslcontext : s, &http_data, content_length); if (!b) { free (http_data); http_data = NULL; result = HTTPR_ERR_RECEIVE; if(http_port == 443) ssl_shutdown(sslcontext); net_close (s); return false; } result = HTTPR_OK; if(http_port == 443) ssl_shutdown(sslcontext); net_close (s); return true; }
/**************************************************************************** * http_request * Retrieves the specified URL, and stores it in the specified file or buffer ***************************************************************************/ int http_request(const char *url, FILE *hfile, u8 *buffer, u32 maxsize, bool silent, bool accept_encoding) { int res = 0; int chunked = 0; char http_host[64]; char http_path[256]; char content_encoding[16] = ""; u16 http_port; #ifdef DEBUGHEADERS int debugging = 0; #endif http_res result; u32 sizeread = 0; content_length = 0; int linecount; if(maxsize > MAX_SIZE){ #ifdef DEBUGERRORS InfoPrompt("maxsize > MAX_SIZE"); #endif return 0; } if (url == NULL || (hfile == NULL && buffer == NULL)){ #ifdef DEBUGERRORS InfoPrompt("!url || (!hfile && !buffer)"); #endif return 0; } if(!silent) ShowAction("Sending data..."); split_res = http_split_url(http_host, http_path, url); // 2 : https ; 1 : http ; 0 : invalid url if (split_res == 2){ http_port = 443; writeFunc = ssl_write; readFunc = ssl_read; }else if( split_res == 1 ){ http_port = 80; writeFunc = net_write; readFunc = net_read; }else{ #ifdef DEBUGERRORS InfoPrompt("Invalid url"); #endif return 0; } http_status = 404; int s = tcp_connect(http_host, http_port); if (s < 0) { result = HTTPR_ERR_CONNECT; #ifdef DEBUGERRORS InfoPrompt("Socket!"); #endif return 0; } int ssl_context = 0; if(split_res == 2){ ssl_context = ssl_setup(http_host, s); #ifdef DEBUGERRORS if(ssl_context < 0){ InfoPrompt("ssl_context() failed"); } #endif if(ssl_context < 0){ net_close(s); return 0; } scktctx = &ssl_context; } else{ scktctx = &s; } if(curl_request){ //Request made by through the CURL class res = tcp_write(*scktctx, (u8 *) curl_request, strlen(curl_request)); }else{ char request[1024]; char *r = request; r += sprintf(r, "GET %s HTTP/1.1\r\n", http_path); r += sprintf(r, "Host: %s\r\n", http_host); if(accept_encoding && hfile){ r += sprintf(r, "Accept-Encoding: gzip, deflate\r\n"); } r += sprintf(r, "Cache-Control: no-cache\r\n\r\n"); res = tcp_write(*scktctx, (u8 *) request, strlen(request)); } if(!silent) CancelAction(); #ifdef DEBUGHEADERS InfoPrompt(http_path); #endif char line[1024]; //Twitter sends a long header for (linecount = 0; linecount < 45; linecount++) { if (tcp_readln(*scktctx, line, 1024) != 0) { #ifdef DEBUGERRORS InfoPrompt("tcp_readln != 0"); #endif http_status = 404; result = HTTPR_ERR_REQUEST; break; } if (!line[0]) break; #ifdef DEBUGHEADERS if(sscanf(line, "HTTP/1.%*u %u", &http_status)){ if(http_status != 200) debugging = 1; } if(sscanf(line, "Content-Length: %u", &content_length) || sscanf(line, "Content-Encoding: %s", content_encoding)){ if(!debugging){ InfoPrompt(line); } } if(!strncmp(line, "Transfer-Encoding: chunked", 25)){ InfoPrompt("Transfer-Encoding: chunked"); chunked = 1; } #else sscanf(line, "HTTP/1.%*u %u", &http_status); sscanf(line, "Content-Length: %u", &content_length); sscanf(line, "Content-Encoding: %s", content_encoding); if(!strncmp(line, "Transfer-Encoding: chunked", 25)) chunked = 1; #endif u32 api_ratelimit=0; if(sscanf(line, "X-RateLimit-Remaining: %u", &api_ratelimit) && api_ratelimit <= 10 && api_ratelimit % 5 == 0){ WindowPrompt("You are on fire!", "You are about to reach Twitter's requests limit. WiiTweet will not work correctly then.", "I'll take a break", 0); } if(get_timeoffset){ if(!strncasecmp(line, "Date:", 5)){ //Case insensitiveness just in case... const char format[] = "%a, %d %b %Y %H:%M:%S %Z"; const char *pointline = line; pointline += 6; struct tm tm; memset(&tm, 0, sizeof(tm)); strptime(pointline, format, &tm); timeoffset = mktime(&tm) - time(NULL); get_timeoffset = 0; } } #ifdef DEBUGHEADERS if(debugging){ InfoPrompt(line); } #endif } if (http_status != 200) { result = HTTPR_ERR_STATUS; #ifdef DEBUGERRORS if(ssl_context){ if(ssl_shutdown(ssl_context)){ InfoPrompt("ssl_shutdown() 1"); } } net_close(s); #else if(ssl_context){ssl_shutdown(ssl_context);} net_close(s); #endif #ifdef DEBUGERRORS char status[64]; sprintf(status, "HTTP Status = %d", http_status); InfoPrompt(status); #endif return 0; }//Try to read anyways? ssl gets rude if it is not convinced there is no data //length unknown - just read as much as we can if(content_length == 0) { content_length = maxsize; } else if (content_length > maxsize) //ssl_shutdown() would fail in this case (?), but it is not likely for our purposes... { result = HTTPR_ERR_TOOBIG; #ifdef DEBUGERRORS if(ssl_context){ if(ssl_shutdown(ssl_context)){ InfoPrompt("ssl_shutdown() 2"); } } net_close(s); #else if(ssl_context){ssl_shutdown(ssl_context);} net_close(s); #endif #ifdef DEBUGERRORS InfoPrompt("content_length > maxsize"); #endif return 0; } unsigned int inflatetype = 0; if(!strncasecmp(content_encoding, "gzip", 4)){ inflatetype = 2; }else if(!strncasecmp(content_encoding, "deflate", 7)){ inflatetype = 1; }else if(content_encoding[0] != '\0'){//Unsupported encoding. This should never happen. #ifdef DEBUGERRORS if(ssl_context){ if(ssl_shutdown(ssl_context)){ InfoPrompt("ssl_shutdown() 3"); } } net_close(s); #else if(ssl_context){ssl_shutdown(ssl_context);} net_close(s); #endif #ifdef DEBUGERRORS InfoPrompt("Unsupported encoding"); #endif return 0; } if (buffer != NULL) { if(!silent) ShowAction("Downloading..."); if(inflatetype){ //Compressed content u8 * inflate_me = (u8 *) mem2_malloc(content_length, MEM2_OTHER); if(!inflate_me){ #ifdef DEBUGERRORS if(ssl_context){ if(ssl_shutdown(ssl_context)){ InfoPrompt("ssl_shutdown() 4"); } } net_close(s); #else if(ssl_context){ssl_shutdown(ssl_context);} net_close(s); #endif #ifdef DEBUGERRORS InfoPrompt("!inflate_me"); #endif return 0; } #ifdef DEBUGHEADERS int tcpread = tcp_read(*scktctx, inflate_me, content_length, chunked); char atoi[64]; sprintf(atoi, "%d", tcpread); WindowPrompt("tcp_read()", atoi, "ok", 0); #else int tcpread = tcp_read(*scktctx, inflate_me, content_length, chunked); #endif /* static int s = 0; char path[256]; sprintf(path, "sd:/catcha%d", s++); SaveFile ((char *)inflate_me, path, tcpread, 1); */ sizeread = httpInflate(buffer, inflate_me, tcpread, inflatetype); if(sizeread < 0){ mem2_free(inflate_me, MEM2_OTHER); #ifdef DEBUGERRORS if(ssl_context){ if(ssl_shutdown(ssl_context)){ InfoPrompt("ssl_shutdown() 5"); } } net_close(s); #else if(ssl_context){ssl_shutdown(ssl_context);} net_close(s); #endif #ifdef DEBUGERRORS InfoPrompt("sizeread < 0"); #endif return 0; } mem2_free(inflate_me, MEM2_OTHER); }else{ //Uncomprpessed content sizeread = tcp_read(*scktctx, buffer, content_length, chunked); } if(!silent) CancelAction(); } else // write into file { /* Uncompressed data. This may fail if the content is chunked and longer than 32KB+2B but chunked is not used in such scenarios */ u32 bufSize = (1024 * 32); u32 bytesLeft = content_length; u32 readSize; if(!silent) ShowProgress("Downloading...", 0, content_length); u8 * fbuffer = (u8 *) malloc(bufSize); if(fbuffer) { while (bytesLeft > 0) { if (bytesLeft < bufSize) readSize = bytesLeft; else readSize = bufSize; res = tcp_read(*scktctx, fbuffer, readSize, chunked); if (!res) break; sizeread += res; bytesLeft -= res; res = fwrite(fbuffer, 1, res, hfile); if (!res) break; if(!silent) ShowProgress("Downloading...", (content_length - bytesLeft), content_length); } free(fbuffer); } if(!silent) CancelAction(); } #ifdef DEBUGERRORS if(ssl_context){ if(ssl_shutdown(ssl_context)){ InfoPrompt("ssl_shutdown() 6"); } } net_close(s); #else if(ssl_context){ssl_shutdown(ssl_context);} net_close(s); #endif if (content_length < maxsize && sizeread != content_length && !inflatetype) { #ifdef DEBUGERRORS InfoPrompt("ERR_RECEIVE"); #endif result = HTTPR_ERR_RECEIVE; return 0; } if (http_status != 200){ #ifdef DEBUGERRORS InfoPrompt("http_status != 200"); #endif return 0; } if(result) //Avoid ugly compiler warning :p result = HTTPR_OK; return sizeread; }