📄 httpget.c
字号:
{ request_url_size = strlen(purl) + 8; if(request_url != NULL) free(request_url); request_url = (char*) malloc(request_url_size); if(request_url != NULL) request_url[request_url_size-1] = '\0'; else { fprintf(stderr, "malloc() failed, out of memory.\n"); exit(1); } } /* used to be url here... seemed wrong to me (when loop advanced...) */ if (strncasecmp(purl, "http://", 7) != 0) strcpy(request_url, "http://"); else request_url[0] = '\0'; strcat(request_url, purl); if (proxyip != INADDR_NONE) { myport = proxyport; myip = proxyip; linelength = linelengthbase + strlen(purl); if (linelength < linelengthbase) { fprintf(stderr, "URL too long. Skipping...\n"); sock = -1; goto exit; } if(host) { tmp = 9 + strlen(host) + 5; if (strlen(host) >= SIZE_MAX - 14 || linelength + tmp < linelength) { fprintf(stderr, "Hostname info too long. Skipping...\n"); sock = -1; goto exit; } /* "Host: <host>:<port>\r\n" */ linelength += tmp; } /* Buffer is reused for receiving later on, so ensure * minimum size. */ linelength = (linelength < 4096) ? 4096 : linelength; /* ugly fix for an ugly memory leak */ if(request != NULL) free(request); request = (char *)malloc((linelength + 1)); if(response != NULL) free(response); response = (char *)malloc((linelength + 1)); if ((request == NULL) || (response == NULL)) { fprintf (stderr, "malloc() failed, out of memory.\n"); exit(1); } strcpy (request, "GET "); strcat(request, request_url); } else { if (host) { free (host); host = NULL; } sptr = url2hostport(purl, &host, &myip, &myport); if (!sptr) { fprintf (stderr, "Unknown host \"%s\".\n", host ? host : ""); sock = -1; goto exit; } linelength = linelengthbase + strlen(sptr); if (linelength < linelengthbase) { fprintf(stderr, "URL too long. Skipping...\n"); sock = -1; goto exit; } if(host) { tmp = 9 + strlen(host) + 5; if (strlen(host) >= SIZE_MAX - 14 || linelength + tmp < linelength) { fprintf(stderr, "Hostname info too long. Skipping...\n"); sock = -1; goto exit; } /* "Host: <host>:<port>\r\n" */ linelength += tmp; } /* Buffer is reused for receiving later on, so ensure * minimum size. */ linelength = (linelength < 4096) ? 4096 : linelength; /* ugly fix for an ugly memory leak */ if(request != NULL) free(request); request = (char *)malloc((linelength + 1)); if(response != NULL) free(response); response = (char *)malloc((linelength + 1)); if ((request == NULL) || (response == NULL)) { fprintf (stderr, "malloc() failed, out of memory.\n"); exit(1); } strcpy (request, "GET "); strcat (request, sptr); } /* hm, my test redirection had troubles with line break before HTTP/1.0 */ if((ttemp = strchr(request,'\r')) != NULL) *ttemp = 0; if((ttemp = strchr(request,'\n')) != NULL) *ttemp = 0; sprintf (request + strlen(request), " HTTP/1.0\r\nUser-Agent: %s/%s\r\n", PACKAGE_NAME, PACKAGE_VERSION); if (host) { debug2("Host: %s:%u", host, myport); if(!try_without_port) sprintf(request + strlen(request), "Host: %s:%u\r\n", host, myport); else { sprintf(request + strlen(request), "Host: %s\r\n", host); try_without_port = 0; } }/* else { fprintf(stderr, "Error: No host! This must be an error! My HTTP/1.1 request is invalid."); } */ strcat (request, ACCEPT_HEAD); strcat (request, CONN_HEAD); server.sin_family = AF_INET; server.sin_port = htons(myport); server.sin_addr.s_addr = myip; if ((sock = socket(PF_INET, SOCK_STREAM, 6)) < 0) { perror ("socket"); goto exit; } if (connect(sock, (struct sockaddr *)&server, sizeof(server))) { perror ("connect"); close(sock); sock = -1; goto exit; } if (httpauth1 || httpauth) { char *buf; strcat (request,"Authorization: Basic "); if(httpauth1) { buf=(char *)malloc((strlen(httpauth1) + 1) * 4); if(!buf) { fprintf(stderr, "Error allocating sufficient memory for http authentication. Exiting."); exit(1); } encode64(httpauth1,buf); free(httpauth1); httpauth1 = NULL; } else { buf=(char *)malloc((strlen(httpauth) + 1) * 4); if(!buf) { fprintf(stderr, "Error allocating sufficient memory for http authentication. Exiting."); exit(1); } encode64(httpauth,buf); } strcat (request, buf); strcat (request,"\r\n"); free(buf); } strcat (request, "\r\n"); debug1("<request>\n%s</request>",request); writestring (sock, request); if (!(myfile = fdopen(sock, "rb"))) { perror ("fdopen"); close(sock); sock = -1; goto exit; } relocate = FALSE; purl[0] = '\0'; if (readstring (response, linelength-1, myfile) == linelength-1) { fprintf(stderr, "Command exceeds max. length\n"); close(sock); sock = -1; goto exit; } debug1("<response>\n%s</response>",response); if ((sptr = strchr(response, ' '))) { switch (sptr[1]) { case '3': relocate = TRUE; case '2': break; default: fprintf (stderr, "HTTP request failed: %s", sptr+1); /* '\n' is included */ close(sock); sock = -1; goto exit; } } do { if (readstring (response, linelength-1, myfile) == linelength-1) { fprintf(stderr, "URL exceeds max. length\n"); close(sock); sock = -1; goto exit; } if (!strncmp(response, "Location: ", 10)) { size_t needed_length; char* prefix = (char*) malloc(strlen(request_url)+1); if(prefix == NULL){ error("out of memory here... cannot handle that gracefully (yet)"); exit(1); } strcpy(prefix, request_url); /* fits and is terminated! */ debug1("request_url:%s", request_url); /* initialized with full old url */ if(strncmp(response, "Location: http://", 17)) { char* ptmp = NULL; /* though it's not RFC (?), accept relative URIs as wget does */ fprintf(stderr, "NOTE: no complete URL in redirect, constructing one\n"); /* not absolute uri, could still be server-absolute */ /* I prepend a part of the request... out of the request */ if(response[10] == '/') { /* only prepend http://server/ */ /* I null the first / after http:// */ if((ptmp = strchr(prefix+7,'/')) != NULL) ptmp[0] = 0; } else { /* prepend http://server/path/ */ /* now we want the last / */ ptmp = strrchr(prefix+7, '/'); if(ptmp != NULL) ptmp[1] = 0; } } else prefix[0] = 0; debug1("prefix=%s", prefix); /* Isn't C string mangling just evil? ;-) */ /* we want to allow urls longer than purl */ /* eh, why *3 here? I don't see it that in this loop any x -> %yz conversion is done */ needed_length = strlen(prefix) + strlen(response+10)*3+1; if(purl_size < needed_length) { purl_size = needed_length; purl = realloc(purl, purl_size); if(purl == NULL) { close(sock); sock = -1; goto exit; } /* Why am I always so picky about the trailing zero, nobody else seems to care? */ purl[purl_size-1] = 0; } /* now that we ensured that purl is big enough, we can just hit it */ strcpy(purl, prefix); strcat(purl, response+10); debug1(" purl: %s",purl); debug1("old request_url: %s", request_url); if(!strcmp(purl, request_url)) { warning("relocated to very same place! trying request again without host port"); try_without_port = 1; } free(prefix); } else { /* watch out for content type */ debug1("searching for content-type... %s", response); if(!strncasecmp("content-type:", response, 13)) { if(content_type != NULL) { char *tmp = NULL; size_t len = 0; if((tmp = strchr(response, '\r')) != NULL ) tmp[0] = 0; if((tmp = strchr(response, '\n')) != NULL ) tmp[0] = 0; len = strlen(response)-13; tmp = response+13; while(len && ((tmp[0] == ' ') || (tmp[0] == '\t'))) { ++tmp; --len; } if(len) { if(*content_type != NULL) free(*content_type); *content_type = (char*) malloc(len+1); if(*content_type != NULL) { strncpy(*content_type, tmp, len); (*content_type)[len] = 0; debug1("got type %s", *content_type); } else fprintf(stderr, "Error: canno allocate memory for content type!\n"); } } } } } while (response[0] != '\r' && response[0] != '\n'); } while (relocate && purl[0] && numrelocs++ < HTTP_MAX_RELOCATIONS); if (relocate) { fprintf (stderr, "Too many HTTP relocations.\n"); close(sock); sock = -1; }exit: if(host != NULL) free(host); if(purl != NULL) free(purl); if(request != NULL) free(request); if(response != NULL) free(response); if(request_url != NULL) free(request_url); return sock;}#else /* defined(WIN32) || defined(GENERIC) */#include <stdlib.h>#include <stdio.h>#include <string.h>extern int errno;#include "mpg123.h"/* stubs for Win32 */void writestring (int fd, char *string){}int 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -