4
* Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
5
* Wed Apr 9 20:57:47 MET DST 1997
10
#if !defined(WIN32) && !defined(GENERIC)
16
#include <sys/param.h>
17
#include <sys/types.h>
18
#include <sys/socket.h>
19
#include <netinet/in.h>
20
#include <arpa/inet.h>
21
#include <sys/errno.h>
29
#define INADDR_NONE 0xffffffff
32
void writestring (int fd, char *string)
34
int result, bytes = strlen(string);
37
if ((result = write(fd, string, bytes)) < 0 && errno != EINTR) {
41
else if (result == 0) {
42
fprintf (stderr, "write: %s\n",
43
"socket closed unexpectedly");
51
void readstring (char *string, int maxlen, FILE *f)
59
if( read(fileno(f),string+pos,1) == 1) {
61
if(string[pos-1] == '\n') {
66
else if(errno != EINTR) {
67
fprintf (stderr, "Error reading from socket or unexpected EOF.\n");
73
result = fgets(string, maxlen, f);
74
} while (!result && errno == EINTR);
76
fprintf (stderr, "Error reading from socket or unexpected EOF.\n");
83
void encode64 (char *source,char *destination)
85
static char *Base64Digits =
86
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
88
int ssiz=strlen(source);
91
for (i = 0 ; i < ssiz ; i += 3) {
93
buf = ((unsigned char *)source)[i] << 16;
95
buf |= ((unsigned char *)source)[i+1] << 8;
97
buf |= ((unsigned char *)source)[i+2];
99
destination[n++] = Base64Digits[(buf >> 18) % 64];
100
destination[n++] = Base64Digits[(buf >> 12) % 64];
102
destination[n++] = Base64Digits[(buf >> 6) % 64];
104
destination[n++] = '=';
106
destination[n++] = Base64Digits[buf % 64];
108
destination[n++] = '=';
110
destination[n++] = 0;
113
/* VERY simple auth-from-URL grabber */
114
int getauthfromURL(char *url,char *auth)
120
if (!(strncasecmp(url, "http://", 7)))
123
if (!(strncasecmp(url, "ftp://", 6)))
126
if( (pos = strchr(url,'@')) ) {
128
for(i=0;i<pos-url;i++) {
132
strncpy(auth,url,pos-url);
140
static char *defaultportstr = "80";
142
char *url2hostport (char *url, char **hname, unsigned long *hip, unsigned char **port)
153
if (strncasecmp(p, "http://", 7) == 0)
156
if (strncasecmp(p, "ftp://", 6) == 0)
160
while (*p && *p != '/')
165
while (*p && hostptr < p && *p != ':' && *p != ']')
168
if (!*p || p < hostptr || *p != ':') {
175
if (*hostptr == '[' && *r_hostptr == ']') {
180
stringlength = r_hostptr - hostptr + 1;
181
h = malloc(stringlength + 1); /* removed the strndup for better portability */
187
strncpy(h, hostptr, stringlength);
188
*(h+stringlength) = '\0';
192
stringlength = (pathptr - portptr);
193
if(!stringlength) portptr = NULL;
195
if (portptr == NULL) {
196
portptr = defaultportstr;
197
stringlength = strlen(defaultportstr);
199
p0 = malloc(stringlength + 1);
206
strncpy(p0, portptr, stringlength);
207
*(p0 + stringlength) = '\0';
209
for (p = p0; *p && isdigit((unsigned char) *p); p++) ;
212
*port = (unsigned char *) p0;
217
char *proxyurl = NULL;
218
unsigned long proxyip = 0;
219
unsigned char *proxyport;
221
#define ACCEPT_HEAD "Accept: audio/mpeg, audio/x-mpegurl, */*\r\n"
223
char *httpauth = NULL;
226
int http_open (const char *url)
228
char *purl, *host, *request, *sptr;
231
unsigned char *myport;
233
int relocate, numrelocs = 0;
236
struct addrinfo hints, *res, *res0;
240
struct sockaddr_in sin;
248
if (!(proxyurl = getenv("MP3_HTTP_PROXY")))
249
if (!(proxyurl = getenv("http_proxy")))
250
proxyurl = getenv("HTTP_PROXY");
251
if (proxyurl && proxyurl[0] && strcmp(proxyurl, "none")) {
252
if (!(url2hostport(proxyurl, &host, &proxyip, &proxyport))) {
253
fprintf (stderr, "Unknown proxy host \"%s\".\n",
263
proxyip = INADDR_NONE;
267
if (proxyip == INADDR_NONE)
268
if (strncasecmp(url, "ftp://", 6) == 0){
269
fprintf(stderr,"Downloading from ftp servers without PROXY not allowed\n");
274
if ((linelength = strlen(url)+200) < 1024)
276
if (!(request = malloc(linelength)) || !(purl = malloc(1024))) {
277
fprintf (stderr, "malloc() failed, out of memory.\n");
282
* We would like spaces to be automatically converted to %20's when
284
* -- Martin Sj�gren <md9ms@mdstud.chalmers.se>
286
if ((sptr = strchr(url, ' ')) == NULL) {
287
strncpy (purl, url, 1023);
295
purllength += sptr-urlptr + 3;
296
if (purllength >= 1023)
298
strncat (purl, urlptr, sptr-urlptr);
299
/*purl[sptr-url] = '\0';*/
300
strcat (purl, "%20");
303
while ((sptr = strchr (urlptr, ' ')) != NULL);
304
strcat (purl, urlptr);
308
getauthfromURL(purl,httpauth1);
311
strcpy (request, "GET ");
312
if (proxyip != INADDR_NONE) {
313
if (strncasecmp(url, "http://", 7) != 0 && strncasecmp(url,"ftp://", 6) != 0)
314
strcat (request, "http://");
315
strcat (request, purl);
328
if (!(sptr = url2hostport(purl, &host, &myip, &myport))) {
329
fprintf (stderr, "Unknown host \"%s\".\n",
333
strcat (request, sptr);
335
sprintf (request + strlen(request),
336
" HTTP/1.0\r\nUser-Agent: %s/%s\r\n",
337
prgName, prgVersion);
339
sprintf(request + strlen(request),
340
"Host: %s:%s\r\n", host, myport);
345
strcat (request, ACCEPT_HEAD);
348
memset(&hints, 0, sizeof(hints));
349
hints.ai_socktype = SOCK_STREAM;
350
error = getaddrinfo(host, (char *)myport, &hints, &res0);
352
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
357
for (res = res0; res; res = res->ai_next) {
358
if ((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {
361
if (connect(sock, res->ai_addr, res->ai_addrlen)) {
372
hp = gethostbyname(host);
375
if (hp->h_length != sizeof(sin.sin_addr))
377
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
380
memset(&sin, 0, sizeof(sin));
381
sin.sin_family = AF_INET;
382
/* sin.sin_len = sizeof(struct sockaddr_in); */
383
memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
384
sin.sin_port = htons(atoi( (char *) myport));
385
if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) ) < 0) {
397
if (strlen(httpauth1) || httpauth) {
399
strcat (request,"Authorization: Basic ");
400
if(strlen(httpauth1))
401
encode64(httpauth1,buf);
403
encode64(httpauth,buf);
404
strcat (request,buf);
405
strcat (request,"\r\n");
407
strcat (request, "\r\n");
409
writestring (sock, request);
410
if (!(myfile = fdopen(sock, "rb"))) {
416
readstring (request, linelength-1, myfile);
417
if ((sptr = strchr(request, ' '))) {
424
fprintf (stderr, "HTTP request failed: %s",
425
sptr+1); /* '\n' is included */
430
readstring (request, linelength-1, myfile);
431
if (!strncmp(request, "Location:", 9))
432
strncpy (purl, request+10, 1023);
433
} while (request[0] != '\r' && request[0] != '\n');
434
} while (relocate && purl[0] && numrelocs++ < 5);
436
fprintf (stderr, "Too many HTTP relocations.\n");
457
void writestring (int fd, char *string)
461
void readstring (char *string, int maxlen, FILE *f)
465
char *url2hostport (char *url, char **hname, unsigned long *hip, unsigned int *port)
469
char *proxyurl = NULL;
470
unsigned long proxyip = 0;
471
unsigned int proxyport;
473
#define ACCEPT_HEAD "Accept: audio/mpeg, audio/x-mpegurl, */*\r\n"
475
int http_open (char *url)