1/* 2 * Generic HTTP routines 3 * 4 * Copyright 2004, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 11 * 12 * $Id: http.c,v 1.1.1.1 2008/10/15 03:31:22 james26_jang Exp $ 13 */ 14 15#include <stdio.h> 16#include <stdlib.h> 17#include <limits.h> 18#include <ctype.h> 19#include <string.h> 20#include <signal.h> 21#include <time.h> 22#include <unistd.h> 23#include <errno.h> 24#include <sys/socket.h> 25#include <netinet/in.h> 26#include <arpa/inet.h> 27 28#include <shutils.h> 29 30static char * 31base64enc(const char *p, char *buf, int len) 32{ 33 char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 34 "0123456789+/"; 35 char *s = buf; 36 37 while(*p) { 38 if (s >= buf+len-4) 39 break; 40 *(s++) = al[(*p >> 2) & 0x3F]; 41 *(s++) = al[((*p << 4) & 0x30) | ((*(p+1) >> 4) & 0x0F)]; 42 *s = *(s+1) = '='; 43 *(s+2) = 0; 44 if (! *(++p)) break; 45 *(s++) = al[((*p << 2) & 0x3C) | ((*(p+1) >> 6) & 0x03)]; 46 if (! *(++p)) break; 47 *(s++) = al[*(p++) & 0x3F]; 48 } 49 50 return buf; 51} 52 53enum { 54 METHOD_GET, 55 METHOD_POST 56}; 57 58static int 59wget(int method, const char *server, char *buf, size_t count, off_t offset) 60{ 61 char url[PATH_MAX] = { 0 }, *s; 62 char *host = url, *path = "", auth[128] = { 0 }, line[512]; 63 unsigned short port = 80; 64 int fd; 65 FILE *fp; 66 struct sockaddr_in sin; 67 int chunked = 0, len = 0; 68 69 if (server == NULL || !strcmp(server, "")) { 70 dprintf("wget: null server input\n"); 71 return (0); 72 } 73 74 strncpy(url, server, sizeof(url)); 75 76 /* Parse URL */ 77 if (!strncmp(url, "http://", 7)) { 78 port = 80; 79 host = url + 7; 80 } 81 if ((s = strchr(host, '/'))) { 82 *s++ = '\0'; 83 path = s; 84 } 85 if ((s = strchr(host, '@'))) { 86 *s++ = '\0'; 87 base64enc(host, auth, sizeof(auth)); 88 host = s; 89 } 90 if ((s = strchr(host, ':'))) { 91 *s++ = '\0'; 92 port = atoi(s); 93 } 94 95 /* Open socket */ 96 if (!inet_aton(host, &sin.sin_addr)) 97 return 0; 98 sin.sin_family = AF_INET; 99 sin.sin_port = htons(port); 100 101 dprintf("Connecting to %s:%u...\n", host, port); 102 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 || 103 connect(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0 || 104 !(fp = fdopen(fd, "r+"))) { 105 perror(host); 106 if (fd >= 0) 107 close(fd); 108 return 0; 109 } 110 dprintf("connected!\n"); 111 112 /* Send HTTP request */ 113 fprintf(fp, "%s /%s HTTP/1.1\r\n", method == METHOD_POST ? "POST" : "GET", path); 114 fprintf(fp, "Host: %s\r\n", host); 115 fprintf(fp, "User-Agent: wget\r\n"); 116 if (strlen(auth)) 117 fprintf(fp, "Authorization: Basic %s\r\n", auth); 118 if (offset) 119 fprintf(fp, "Range: bytes=%ld-\r\n", offset); 120 if (method == METHOD_POST) { 121 fprintf(fp, "Content-Type: application/x-www-form-urlencoded\r\n"); 122 fprintf(fp, "Content-Length: %d\r\n\r\n", (int) strlen(buf)); 123 fputs(buf, fp); 124 } else 125 fprintf(fp,"Connection: close\r\n\r\n"); 126 127 /* Check HTTP response */ 128 dprintf("HTTP request sent, awaiting response...\n"); 129 if (fgets(line, sizeof(line), fp)) { 130 dprintf("%s", line); 131 for (s = line; *s && !isspace((int)*s); s++); 132 for (; isspace((int)*s); s++); 133 switch (atoi(s)) { 134 case 200: if (offset) goto done; else break; 135 case 206: if (offset) break; else goto done; 136 default: goto done; 137 } 138 } 139 140 /* Parse headers */ 141 while (fgets(line, sizeof(line), fp)) { 142 dprintf("%s", line); 143 for (s = line; *s == '\r'; s++); 144 if (*s == '\n') 145 break; 146 if (!strncasecmp(s, "Content-Length:", 15)) { 147 for (s += 15; isblank(*s); s++); 148 chomp(s); 149 len = atoi(s); 150 } 151 else if (!strncasecmp(s, "Transfer-Encoding:", 18)) { 152 for (s += 18; isblank(*s); s++); 153 chomp(s); 154 if (!strncasecmp(s, "chunked", 7)) 155 chunked = 1; 156 } 157 } 158 159 if (chunked && fgets(line, sizeof(line), fp)) 160 len = strtol(line, NULL, 16); 161 162 len = (len > count) ? count : len; 163 len = fread(buf, 1, len, fp); 164 165 done: 166 /* Close socket */ 167 fflush(fp); 168 fclose(fp); 169 return len; 170} 171 172int 173http_get(const char *server, char *buf, size_t count, off_t offset) 174{ 175 return wget(METHOD_GET, server, buf, count, offset); 176} 177 178int 179http_post(const char *server, char *buf, size_t count) 180{ 181 /* No continuation generally possible with POST */ 182 return wget(METHOD_POST, server, buf, count, 0); 183} 184