summaryrefslogtreecommitdiffstats
path: root/mpg123_artsplugin/mpg123/httpget.c
diff options
context:
space:
mode:
Diffstat (limited to 'mpg123_artsplugin/mpg123/httpget.c')
-rw-r--r--mpg123_artsplugin/mpg123/httpget.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/mpg123_artsplugin/mpg123/httpget.c b/mpg123_artsplugin/mpg123/httpget.c
new file mode 100644
index 00000000..71750115
--- /dev/null
+++ b/mpg123_artsplugin/mpg123/httpget.c
@@ -0,0 +1,481 @@
+/*
+ * httpget.c
+ *
+ * Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
+ * Wed Apr 9 20:57:47 MET DST 1997
+ */
+
+#undef ALSA
+
+#if !defined(WIN32) && !defined(GENERIC)
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/errno.h>
+#include <ctype.h>
+
+extern int errno;
+
+#include "mpg123.h"
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+void writestring (int fd, char *string)
+{
+ int result, bytes = strlen(string);
+
+ while (bytes) {
+ if ((result = write(fd, string, bytes)) < 0 && errno != EINTR) {
+ perror ("write");
+ exit (1);
+ }
+ else if (result == 0) {
+ fprintf (stderr, "write: %s\n",
+ "socket closed unexpectedly");
+ exit (1);
+ }
+ string += result;
+ bytes -= result;
+ }
+}
+
+void readstring (char *string, int maxlen, FILE *f)
+{
+#if 0
+ char *result;
+#endif
+ int pos = 0;
+
+ while(1) {
+ if( read(fileno(f),string+pos,1) == 1) {
+ pos++;
+ if(string[pos-1] == '\n') {
+ string[pos] = 0;
+ break;
+ }
+ }
+ else if(errno != EINTR) {
+ fprintf (stderr, "Error reading from socket or unexpected EOF.\n");
+ exit(1);
+ }
+ }
+#if 0
+ do {
+ result = fgets(string, maxlen, f);
+ } while (!result && errno == EINTR);
+ if (!result) {
+ fprintf (stderr, "Error reading from socket or unexpected EOF.\n");
+ exit (1);
+ }
+#endif
+
+}
+
+void encode64 (char *source,char *destination)
+{
+ static char *Base64Digits =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ int n = 0;
+ int ssiz=strlen(source);
+ int i;
+
+ for (i = 0 ; i < ssiz ; i += 3) {
+ unsigned int buf;
+ buf = ((unsigned char *)source)[i] << 16;
+ if (i+1 < ssiz)
+ buf |= ((unsigned char *)source)[i+1] << 8;
+ if (i+2 < ssiz)
+ buf |= ((unsigned char *)source)[i+2];
+
+ destination[n++] = Base64Digits[(buf >> 18) % 64];
+ destination[n++] = Base64Digits[(buf >> 12) % 64];
+ if (i+1 < ssiz)
+ destination[n++] = Base64Digits[(buf >> 6) % 64];
+ else
+ destination[n++] = '=';
+ if (i+2 < ssiz)
+ destination[n++] = Base64Digits[buf % 64];
+ else
+ destination[n++] = '=';
+ }
+ destination[n++] = 0;
+}
+
+/* VERY simple auth-from-URL grabber */
+int getauthfromURL(char *url,char *auth)
+{
+ char *pos;
+
+ *auth = 0;
+
+ if (!(strncasecmp(url, "http://", 7)))
+ url += 7;
+
+ if (!(strncasecmp(url, "ftp://", 6)))
+ url += 6;
+
+ if( (pos = strchr(url,'@')) ) {
+ int i;
+ for(i=0;i<pos-url;i++) {
+ if( url[i] == '/' )
+ return 0;
+ }
+ strncpy(auth,url,pos-url);
+ auth[pos-url] = 0;
+ strcpy(url,pos+1);
+ return 1;
+ }
+ return 0;
+}
+
+static char *defaultportstr = "80";
+
+char *url2hostport (char *url, char **hname, unsigned long *hip, unsigned char **port)
+{
+ char *h, *p;
+ char *hostptr;
+ char *r_hostptr;
+ char *pathptr;
+ char *portptr;
+ char *p0;
+ size_t stringlength;
+
+ p = url;
+ if (strncasecmp(p, "http://", 7) == 0)
+ p += 7;
+
+ if (strncasecmp(p, "ftp://", 6) == 0)
+ p += 6;
+
+ hostptr = p;
+ while (*p && *p != '/')
+ p++;
+ pathptr = p;
+
+ r_hostptr = --p;
+ while (*p && hostptr < p && *p != ':' && *p != ']')
+ p--;
+
+ if (!*p || p < hostptr || *p != ':') {
+ portptr = NULL;
+ }
+ else{
+ portptr = p + 1;
+ r_hostptr = p - 1;
+ }
+ if (*hostptr == '[' && *r_hostptr == ']') {
+ hostptr++;
+ r_hostptr--;
+ }
+
+ stringlength = r_hostptr - hostptr + 1;
+ h = malloc(stringlength + 1); /* removed the strndup for better portability */
+ if (h == NULL) {
+ *hname = NULL;
+ *port = NULL;
+ return NULL;
+ }
+ strncpy(h, hostptr, stringlength);
+ *(h+stringlength) = '\0';
+ *hname = h;
+
+ if (portptr) {
+ stringlength = (pathptr - portptr);
+ if(!stringlength) portptr = NULL;
+ }
+ if (portptr == NULL) {
+ portptr = defaultportstr;
+ stringlength = strlen(defaultportstr);
+ }
+ p0 = malloc(stringlength + 1);
+ if (p0 == NULL) {
+ free(h);
+ *hname = NULL;
+ *port = NULL;
+ return NULL;
+ }
+ strncpy(p0, portptr, stringlength);
+ *(p0 + stringlength) = '\0';
+
+ for (p = p0; *p && isdigit((unsigned char) *p); p++) ;
+
+ *p = '\0';
+ *port = (unsigned char *) p0;
+
+ return pathptr;
+}
+
+char *proxyurl = NULL;
+unsigned long proxyip = 0;
+unsigned char *proxyport;
+
+#define ACCEPT_HEAD "Accept: audio/mpeg, audio/x-mpegurl, */*\r\n"
+
+char *httpauth = NULL;
+char httpauth1[256];
+
+int http_open (const char *url)
+{
+ char *purl, *host, *request, *sptr;
+ int linelength;
+ unsigned long myip;
+ unsigned char *myport;
+ int sock;
+ int relocate, numrelocs = 0;
+ FILE *myfile;
+#ifdef INET6
+ struct addrinfo hints, *res, *res0;
+ int error;
+#else
+ struct hostent *hp;
+ struct sockaddr_in sin;
+#endif
+
+ host = NULL;
+ proxyport = NULL;
+ myport = NULL;
+ if (!proxyip) {
+ if (!proxyurl)
+ if (!(proxyurl = getenv("MP3_HTTP_PROXY")))
+ if (!(proxyurl = getenv("http_proxy")))
+ proxyurl = getenv("HTTP_PROXY");
+ if (proxyurl && proxyurl[0] && strcmp(proxyurl, "none")) {
+ if (!(url2hostport(proxyurl, &host, &proxyip, &proxyport))) {
+ fprintf (stderr, "Unknown proxy host \"%s\".\n",
+ host ? host : "");
+ exit (1);
+ }
+#if 0
+ if (host)
+ free (host);
+#endif
+ }
+ else
+ proxyip = INADDR_NONE;
+ }
+
+
+ if (proxyip == INADDR_NONE)
+ if (strncasecmp(url, "ftp://", 6) == 0){
+ fprintf(stderr,"Downloading from ftp servers without PROXY not allowed\n");
+ exit(1);
+ }
+
+
+ if ((linelength = strlen(url)+200) < 1024)
+ linelength = 1024;
+ if (!(request = malloc(linelength)) || !(purl = malloc(1024))) {
+ fprintf (stderr, "malloc() failed, out of memory.\n");
+ exit (1);
+ }
+ /*
+ * 2000-10-21:
+ * We would like spaces to be automatically converted to %20's when
+ * fetching via HTTP.
+ * -- Martin Sjögren <md9ms@mdstud.chalmers.se>
+ */
+ if ((sptr = strchr(url, ' ')) == NULL) {
+ strncpy (purl, url, 1023);
+ purl[1023] = '\0';
+ }
+ else {
+ int purllength = 0;
+ char *urlptr = url;
+ purl[0] = '\0';
+ do {
+ purllength += sptr-urlptr + 3;
+ if (purllength >= 1023)
+ break;
+ strncat (purl, urlptr, sptr-urlptr);
+ /*purl[sptr-url] = '\0';*/
+ strcat (purl, "%20");
+ urlptr = sptr + 1;
+ }
+ while ((sptr = strchr (urlptr, ' ')) != NULL);
+ strcat (purl, urlptr);
+ }
+
+
+ getauthfromURL(purl,httpauth1);
+
+ do {
+ strcpy (request, "GET ");
+ if (proxyip != INADDR_NONE) {
+ if (strncasecmp(url, "http://", 7) != 0 && strncasecmp(url,"ftp://", 6) != 0)
+ strcat (request, "http://");
+ strcat (request, purl);
+ myport = proxyport;
+ myip = proxyip;
+ }
+ else {
+ if (host) {
+ free(host);
+ host=NULL;
+ }
+ if (proxyport) {
+ free(proxyport);
+ proxyport=NULL;
+ }
+ if (!(sptr = url2hostport(purl, &host, &myip, &myport))) {
+ fprintf (stderr, "Unknown host \"%s\".\n",
+ host ? host : "");
+ exit (1);
+ }
+ strcat (request, sptr);
+ }
+ sprintf (request + strlen(request),
+ " HTTP/1.0\r\nUser-Agent: %s/%s\r\n",
+ prgName, prgVersion);
+ if (host) {
+ sprintf(request + strlen(request),
+ "Host: %s:%s\r\n", host, myport);
+#if 0
+ free (host);
+#endif
+ }
+ strcat (request, ACCEPT_HEAD);
+
+#ifdef INET6
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, (char *)myport, &hints, &res0);
+ if (error) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
+ exit(1);
+ }
+
+ sock = -1;
+ for (res = res0; res; res = res->ai_next) {
+ if ((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {
+ continue;
+ }
+ if (connect(sock, res->ai_addr, res->ai_addrlen)) {
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ break;
+ }
+
+ freeaddrinfo(res0);
+#else
+ sock = -1;
+ hp = gethostbyname(host);
+ if (!hp)
+ goto fail;
+ if (hp->h_length != sizeof(sin.sin_addr))
+ goto fail;
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock < 0)
+ goto fail;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ /* sin.sin_len = sizeof(struct sockaddr_in); */
+ memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
+ sin.sin_port = htons(atoi( (char *) myport));
+ if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) ) < 0) {
+ close(sock);
+ sock = -1;
+ }
+fail:
+#endif
+
+ if (sock < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ if (strlen(httpauth1) || httpauth) {
+ char buf[1023];
+ strcat (request,"Authorization: Basic ");
+ if(strlen(httpauth1))
+ encode64(httpauth1,buf);
+ else
+ encode64(httpauth,buf);
+ strcat (request,buf);
+ strcat (request,"\r\n");
+ }
+ strcat (request, "\r\n");
+
+ writestring (sock, request);
+ if (!(myfile = fdopen(sock, "rb"))) {
+ perror ("fdopen");
+ exit (1);
+ };
+ relocate = FALSE;
+ purl[0] = '\0';
+ readstring (request, linelength-1, myfile);
+ if ((sptr = strchr(request, ' '))) {
+ switch (sptr[1]) {
+ case '3':
+ relocate = TRUE;
+ case '2':
+ break;
+ default:
+ fprintf (stderr, "HTTP request failed: %s",
+ sptr+1); /* '\n' is included */
+ exit (1);
+ }
+ }
+ do {
+ readstring (request, linelength-1, myfile);
+ if (!strncmp(request, "Location:", 9))
+ strncpy (purl, request+10, 1023);
+ } while (request[0] != '\r' && request[0] != '\n');
+ } while (relocate && purl[0] && numrelocs++ < 5);
+ if (relocate) {
+ fprintf (stderr, "Too many HTTP relocations.\n");
+ exit (1);
+ }
+ free (purl);
+ free (request);
+ free(host);
+ free(proxyport);
+ free(myport);
+
+ return sock;
+}
+
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+extern int errno;
+
+#include "mpg123.h"
+
+void writestring (int fd, char *string)
+{
+}
+
+void readstring (char *string, int maxlen, FILE *f)
+{
+}
+
+char *url2hostport (char *url, char **hname, unsigned long *hip, unsigned int *port)
+{
+}
+
+char *proxyurl = NULL;
+unsigned long proxyip = 0;
+unsigned int proxyport;
+
+#define ACCEPT_HEAD "Accept: audio/mpeg, audio/x-mpegurl, */*\r\n"
+
+int http_open (char *url)
+{
+}
+#endif
+
+/* EOF */
+