int url_not_saveable(unsigned char *url) { int p, palen; unsigned char *u = translate_url(url, cast_uchar "/"); if (!u) return 1; p = parse_url(u, NULL, NULL, NULL, NULL, &palen, NULL, NULL, NULL, NULL, NULL, NULL, NULL); mem_free(u); return p || palen; }
unsigned char *translate_url(unsigned char *url, unsigned char *cwd) { unsigned char *ch; unsigned char *nu, *da; unsigned char *prefix; int sl; while (*url == ' ') url++; if (*url && url[strlen(cast_const_char url) - 1] == ' ') { nu = stracpy(url); while (*nu && nu[strlen(cast_const_char nu) - 1] == ' ') nu[strlen(cast_const_char nu) - 1] = 0; ch = translate_url(nu, cwd); mem_free(nu); return ch; } if (!casecmp(cast_uchar "proxy://", url, 8)) return NULL; if (!parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &da, NULL, NULL)) { nu = stracpy(url); goto return_nu; } if (strchr(cast_const_char url, POST_CHAR)) return NULL; if (strstr(cast_const_char url, "://")) { nu = stracpy(url); extend_str(&nu, 1); ch = cast_uchar strrchr(cast_const_char nu, '#'); if (!ch || strchr(cast_const_char ch, '/')) ch = nu + strlen(cast_const_char nu); memmove(ch + 1, ch, strlen(cast_const_char ch) + 1); *ch = '/'; if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); } prefix = cast_uchar "file://"; if (url[0] == '[' && strchr(cast_const_char url, ']')) { ch = url; goto http; } ch = url + strcspn(cast_const_char url, ".:/@"); sl = 0; #ifdef SPAD if (strchr(cast_const_char url, ':') && _is_local(cast_const_char url)) goto set_prefix; #endif if (*ch != ':' || *(url + strcspn(cast_const_char url, "/@")) == '@') { if (*url != '.' && *ch == '.') { unsigned char *f, *e; int i; for (e = ch + 1; *(f = e + strcspn(cast_const_char e, ".:/")) == '.'; e = f + 1) ; for (i = 0; i < f - e; i++) if (e[i] < '0' || e[i] > '9') goto noip; goto http; noip: if (f - e == 2 && casecmp(e, cast_uchar "gz", 2)) { http: prefix = cast_uchar "http://", sl = 1; } else { char *tld[] = { "com", "edu", "net", "org", "gov", "mil", "int", "arpa", "aero", "biz", "coop", "info", "museum", "name", "pro", "cat", "jobs", "mobi", "travel", "tel", "onion", "exit", NULL }; for (i = 0; tld[i]; i++) if ((size_t)(f - e) == strlen(cast_const_char tld[i]) && !casecmp(cast_uchar tld[i], e, f - e)) goto http; } } if (*ch == '@' || *ch == ':' || !cmpbeg(url, cast_uchar "ftp.")) prefix = cast_uchar "ftp://", sl = 1; goto set_prefix; set_prefix: nu = stracpy(prefix); add_to_strn(&nu, url); if (sl && !strchr(cast_const_char url, '/')) add_to_strn(&nu, cast_uchar "/"); if (parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { mem_free(nu); return NULL; } goto return_nu; } #ifdef DOS_FS if (ch == url + 1) goto set_prefix; #endif if (!(nu = memacpy(url, ch - url + 1))) return NULL; add_to_strn(&nu, cast_uchar "//"); add_to_strn(&nu, ch + 1); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; add_to_strn(&nu, cast_uchar "/"); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); return NULL; return_nu: insert_wd(&nu, cwd); extend_str(&nu, 1); translate_directories(nu); nu = translate_hashbang(nu); return nu; }
unsigned char *translate_url(unsigned char *url, unsigned char *cwd) { unsigned char *ch; unsigned char *nu, *da; unsigned char *prefix; int sl; while (*url == ' ') url++; if (*url && url[strlen(cast_const_char url) - 1] == ' ') { nu = stracpy(url); while (*nu && nu[strlen(cast_const_char nu) - 1] == ' ') nu[strlen(cast_const_char nu) - 1] = 0; ch = translate_url(nu, cwd); mem_free(nu); return ch; } if (!casecmp(cast_uchar "proxy://", url, 8)) return NULL; if (!parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &da, NULL, NULL)) { nu = stracpy(url); goto return_nu; } if (strchr(cast_const_char url, POST_CHAR)) return NULL; if (strstr(cast_const_char url, "://")) { nu = stracpy(url); extend_str(&nu, 1); ch = cast_uchar strrchr(cast_const_char nu, '#'); if (!ch || strchr(cast_const_char ch, '/')) ch = nu + strlen(cast_const_char nu); memmove(ch + 1, ch, strlen(cast_const_char ch) + 1); *ch = '/'; if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); } prefix = cast_uchar "file://"; if (url[0] == '[' && strchr(cast_const_char url, ']')) { ch = url; goto http; } ch = url + strcspn(cast_const_char url, ".:/@"); sl = 0; #ifdef SPAD if (strchr(cast_const_char url, ':') && _is_local(cast_const_char url)) goto set_prefix; #endif if (*ch != ':' || *(url + strcspn(cast_const_char url, "/@")) == '@') { if (*url != '.' && *ch == '.') { unsigned char *e, *f, *g; int tl; for (e = ch + 1; *(f = e + strcspn(cast_const_char e, ".:/")) == '.'; e = f + 1) ; g = memacpy(e, f - e); tl = is_tld(g); mem_free(g); if (tl) http: prefix = cast_uchar "http://", sl = 1; } if (*ch == '@' || *ch == ':' || !cmpbeg(url, cast_uchar "ftp.")) prefix = cast_uchar "ftp://", sl = 1; goto set_prefix; set_prefix: nu = stracpy(prefix); add_to_strn(&nu, url); if (sl && !strchr(cast_const_char url, '/')) add_to_strn(&nu, cast_uchar "/"); if (parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { mem_free(nu); return NULL; } goto return_nu; } #ifdef DOS_FS if (ch == url + 1) goto set_prefix; #endif if (!(nu = memacpy(url, ch - url + 1))) return NULL; add_to_strn(&nu, cast_uchar "//"); add_to_strn(&nu, ch + 1); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; add_to_strn(&nu, cast_uchar "/"); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); return NULL; return_nu: insert_wd(&nu, cwd); extend_str(&nu, 1); translate_directories(nu); nu = translate_hashbang(nu); return nu; }
int win32_net_http_open(char* url, struct httpdata *hd) { mpg123_string purl, host, port, path; mpg123_string request, response, request_url; mpg123_string httpauth1; ws.local_socket = SOCKET_ERROR; int oom = 0; int relocate, numrelocs = 0; int got_location = FALSE; /* workaround for http://www.global24music.com/rautemusik/files/extreme/isdn.pls this site's apache gives me a relocation to the same place when I give the port in Host request field for the record: Apache/2.0.51 (Fedora) */ int try_without_port = 0; mpg123_init_string(&purl); mpg123_init_string(&host); mpg123_init_string(&port); mpg123_init_string(&path); mpg123_init_string(&request); mpg123_init_string(&response); mpg123_init_string(&request_url); mpg123_init_string(&httpauth1); /* Get initial info for proxy server. Once. */ if(hd->proxystate == PROXY_UNKNOWN && !proxy_init(hd)) goto exit; if(!translate_url(url, &purl)){ oom=1; goto exit; } /* Don't confuse the different auth strings... */ if(!split_url(&purl, &httpauth1, NULL, NULL, NULL) ){ oom=1; goto exit; } /* "GET http://" 11 * " HTTP/1.0\r\nUser-Agent: <PACKAGE_NAME>/<PACKAGE_VERSION>\r\n" * 26 + PACKAGE_NAME + PACKAGE_VERSION * accept header + accept_length() * "Authorization: Basic \r\n" 23 * "\r\n" 2 * ... plus the other predefined header lines */ /* Just use this estimate as first guess to reduce malloc calls in string library. */ { size_t length_estimate = 62 + strlen(PACKAGE_NAME) + strlen(PACKAGE_VERSION) + accept_length() + strlen(CONN_HEAD) + strlen(icy_yes) + purl.fill; if( !mpg123_grow_string(&request, length_estimate) || !mpg123_grow_string(&response,4096) ) { oom=1; goto exit; } } do { /* Storing the request url, with http:// prepended if needed. */ /* used to be url here... seemed wrong to me (when loop advanced...) */ if(strncasecmp(purl.p, "http://", 7) != 0) mpg123_set_string(&request_url, "http://"); else mpg123_set_string(&request_url, ""); mpg123_add_string(&request_url, purl.p); if (hd->proxystate >= PROXY_HOST) { /* We will connect to proxy, full URL goes into the request. */ if( !mpg123_copy_string(&hd->proxyhost, &host) || !mpg123_copy_string(&hd->proxyport, &port) || !mpg123_set_string(&request, "GET ") || !mpg123_add_string(&request, request_url.p) ) { oom=1; goto exit; } } else { /* We will connect to the host from the URL and only the path goes into the request. */ if(!split_url(&purl, NULL, &host, &port, &path)){ oom=1; goto exit; } if( !mpg123_set_string(&request, "GET ") || !mpg123_add_string(&request, path.p) ) { oom=1; goto exit; } } if(!fill_request(&request, &host, &port, &httpauth1, &try_without_port)){ oom=1; goto exit; } httpauth1.fill = 0; /* We use the auth data from the URL only once. */ debug2("attempting to open_connection to %s:%s", host.p, port.p); win32_net_open_connection(&host, &port); if(ws.local_socket == SOCKET_ERROR) { error1("Unable to establish connection to %s", host.fill ? host.p : ""); goto exit; } debug("win32_net_open_connection succeed"); #define http_failure win32_net_close(ws.local_socket); ws.local_socket=SOCKET_ERROR; goto exit; if(param.verbose > 2) fprintf(stderr, "HTTP request:\n%s\n",request.p); if(!win32_net_writestring(ws.local_socket, &request)){ http_failure; } debug("Skipping fdopen for WSA sockets"); relocate = FALSE; /* Arbitrary length limit here... */ #define safe_readstring \ win32_net_readstring(&response, SIZE_MAX/16, NULL); \ if(response.fill > SIZE_MAX/16) /* > because of appended zero. */ \ { \ error("HTTP response line exceeds max. length"); \ http_failure; \ } \ else if(response.fill == 0) \ { \ error("readstring failed"); \ http_failure; \ } \ if(param.verbose > 2) fprintf(stderr, "HTTP in: %s", response.p); safe_readstring; { char *sptr; if((sptr = strchr(response.p, ' '))) { if(response.fill > sptr-response.p+2) switch (sptr[1]) { case '3': relocate = TRUE; case '2': break; default: fprintf (stderr, "HTTP request failed: %s", sptr+1); /* '\n' is included */ http_failure; } else{ error("Too short response,"); http_failure; } } } /* If we are relocated, we need to look out for a Location header. */ got_location = FALSE; do { safe_readstring; /* Think about that: Should we really error out when we get nothing? Could be that the server forgot the trailing empty line... */ if (!strncasecmp(response.p, "Location: ", 10)) { /* It is a redirection! */ if(!win32_net_resolve_redirect(&response, &request_url, &purl)){ oom=1, http_failure; } if(!strcmp(purl.p, request_url.p)) { warning("relocated to very same place! trying request again without host port"); try_without_port = 1; } got_location = TRUE; } else { /* We got a header line (or the closing empty line). */ char *tmp; debug1("searching for header values... %s", response.p); /* Not sure if I want to bail out on error here. */ /* Also: What text encoding are these strings in? Doesn't need to be plain ASCII... */ get_header_string(&response, "content-type", &hd->content_type); get_header_string(&response, "icy-name", &hd->icy_name); get_header_string(&response, "icy-url", &hd->icy_url); /* watch out for icy-metaint */ if((tmp = get_header_val("icy-metaint", &response))) { hd->icy_interval = (off_t) atol(tmp); /* atoll ? */ debug1("got icy-metaint %li", (long int)hd->icy_interval); } } } while(response.p[0] != '\r' && response.p[0] != '\n'); } while(relocate && got_location && purl.fill && numrelocs++ < HTTP_MAX_RELOCATIONS); if(relocate) { if(!got_location) error("Server meant to redirect but failed to provide a location!"); else error1("Too many HTTP relocations (%i).", numrelocs); http_failure; } exit: /* The end as well as the exception handling point... */ if(oom) error("Apparently, I ran out of memory or had some bad input data..."); mpg123_free_string(&purl); mpg123_free_string(&host); mpg123_free_string(&port); mpg123_free_string(&path); mpg123_free_string(&request); mpg123_free_string(&response); mpg123_free_string(&request_url); mpg123_free_string(&httpauth1); if (ws.local_socket == SOCKET_ERROR || oom) return -1; else return 1; }