| @@ -303,11 +303,89 @@ static int http_get_line(HTTPContext *s, char *line, int line_size) | |||
| } | |||
| } | |||
| static int check_http_code(URLContext *h, int http_code, const char *end) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| /* error codes are 4xx and 5xx, but regard 401 as a success, so we | |||
| * don't abort until all headers have been parsed. */ | |||
| if (http_code >= 400 && http_code < 600 && | |||
| (http_code != 401 || s->auth_state.auth_type != HTTP_AUTH_NONE) && | |||
| (http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) { | |||
| end += strspn(end, SPACE_CHARS); | |||
| av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", http_code, end); | |||
| return AVERROR(EIO); | |||
| } | |||
| return 0; | |||
| } | |||
| static int parse_location(HTTPContext *s, const char *p) | |||
| { | |||
| char redirected_location[MAX_URL_SIZE], *new_loc; | |||
| ff_make_absolute_url(redirected_location, sizeof(redirected_location), | |||
| s->location, p); | |||
| new_loc = av_strdup(redirected_location); | |||
| if (!new_loc) | |||
| return AVERROR(ENOMEM); | |||
| av_free(s->location); | |||
| s->location = new_loc; | |||
| return 0; | |||
| } | |||
| /* "bytes $from-$to/$document_size" */ | |||
| static void parse_content_range(URLContext *h, char *p) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| const char *slash; | |||
| if (!strncmp(p, "bytes ", 6)) { | |||
| p += 6; | |||
| s->off = strtoll(p, NULL, 10); | |||
| if ((slash = strchr(p, '/')) && strlen(slash) > 0) | |||
| s->filesize = strtoll(slash+1, NULL, 10); | |||
| } | |||
| h->is_streamed = 0; /* we _can_ in fact seek */ | |||
| } | |||
| static int parse_content_encoding(URLContext *h, char *p) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| if (!av_strncasecmp(p, "gzip", 4) || | |||
| !av_strncasecmp(p, "deflate", 7)) { | |||
| #if CONFIG_ZLIB | |||
| s->compressed = 1; | |||
| inflateEnd(&s->inflate_stream); | |||
| if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) { | |||
| av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n", | |||
| s->inflate_stream.msg); | |||
| return AVERROR(ENOSYS); | |||
| } | |||
| if (zlibCompileFlags() & (1 << 17)) { | |||
| av_log(h, AV_LOG_WARNING, | |||
| "Your zlib was compiled without gzip support.\n"); | |||
| return AVERROR(ENOSYS); | |||
| } | |||
| #else | |||
| av_log(h, AV_LOG_WARNING, | |||
| "Compressed (%s) content, need zlib with gzip support\n", p); | |||
| return AVERROR(ENOSYS); | |||
| #endif | |||
| } else if (!av_strncasecmp(p, "identity", 8)) { | |||
| // The normal, no-encoding case (although servers shouldn't include | |||
| // the header at all if this is the case). | |||
| } else { | |||
| av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p); | |||
| return AVERROR(ENOSYS); | |||
| } | |||
| return 0; | |||
| } | |||
| static int process_line(URLContext *h, char *line, int line_count, | |||
| int *new_location) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| char *tag, *p, *end; | |||
| int ret; | |||
| /* end of header */ | |||
| if (line[0] == '\0') { | |||
| @@ -325,15 +403,8 @@ static int process_line(URLContext *h, char *line, int line_count, | |||
| av_dlog(NULL, "http_code=%d\n", s->http_code); | |||
| /* error codes are 4xx and 5xx, but regard 401 as a success, so we | |||
| * don't abort until all headers have been parsed. */ | |||
| if (s->http_code >= 400 && s->http_code < 600 && | |||
| (s->http_code != 401 || s->auth_state.auth_type != HTTP_AUTH_NONE) && | |||
| (s->http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) { | |||
| end += strspn(end, SPACE_CHARS); | |||
| av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", s->http_code, end); | |||
| return AVERROR(EIO); | |||
| } | |||
| if ((ret = check_http_code(h, s->http_code, end)) < 0) | |||
| return ret; | |||
| } else { | |||
| while (*p != '\0' && *p != ':') | |||
| p++; | |||
| @@ -346,27 +417,13 @@ static int process_line(URLContext *h, char *line, int line_count, | |||
| while (av_isspace(*p)) | |||
| p++; | |||
| if (!av_strcasecmp(tag, "Location")) { | |||
| char redirected_location[MAX_URL_SIZE], *new_loc; | |||
| ff_make_absolute_url(redirected_location, sizeof(redirected_location), | |||
| s->location, p); | |||
| new_loc = av_strdup(redirected_location); | |||
| if (!new_loc) | |||
| return AVERROR(ENOMEM); | |||
| av_free(s->location); | |||
| s->location = new_loc; | |||
| if ((ret = parse_location(s, p)) < 0) | |||
| return ret; | |||
| *new_location = 1; | |||
| } else if (!av_strcasecmp(tag, "Content-Length") && s->filesize == -1) { | |||
| s->filesize = strtoll(p, NULL, 10); | |||
| } else if (!av_strcasecmp(tag, "Content-Range")) { | |||
| /* "bytes $from-$to/$document_size" */ | |||
| const char *slash; | |||
| if (!strncmp(p, "bytes ", 6)) { | |||
| p += 6; | |||
| s->off = strtoll(p, NULL, 10); | |||
| if ((slash = strchr(p, '/')) && strlen(slash) > 0) | |||
| s->filesize = strtoll(slash+1, NULL, 10); | |||
| } | |||
| h->is_streamed = 0; /* we _can_ in fact seek */ | |||
| parse_content_range(h, p); | |||
| } else if (!av_strcasecmp(tag, "Accept-Ranges") && | |||
| !strncmp(p, "bytes", 5)) { | |||
| h->is_streamed = 0; | |||
| @@ -384,31 +441,8 @@ static int process_line(URLContext *h, char *line, int line_count, | |||
| if (!strcmp(p, "close")) | |||
| s->willclose = 1; | |||
| } else if (!av_strcasecmp(tag, "Content-Encoding")) { | |||
| if (!av_strncasecmp(p, "gzip", 4) || | |||
| !av_strncasecmp(p, "deflate", 7)) { | |||
| #if CONFIG_ZLIB | |||
| s->compressed = 1; | |||
| inflateEnd(&s->inflate_stream); | |||
| if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) { | |||
| av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n", | |||
| s->inflate_stream.msg); | |||
| return AVERROR(ENOSYS); | |||
| } | |||
| if (zlibCompileFlags() & (1 << 17)) { | |||
| av_log(h, AV_LOG_WARNING, "Your zlib was compiled without gzip support.\n"); | |||
| return AVERROR(ENOSYS); | |||
| } | |||
| #else | |||
| av_log(h, AV_LOG_WARNING, "Compressed (%s) content, need zlib with gzip support\n", p); | |||
| return AVERROR(ENOSYS); | |||
| #endif | |||
| } else if (!av_strncasecmp(p, "identity", 8)) { | |||
| // The normal, no-encoding case (although servers shouldn't include | |||
| // the header at all if this is the case). | |||
| } else { | |||
| av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p); | |||
| return AVERROR(ENOSYS); | |||
| } | |||
| if ((ret = parse_content_encoding(h, p)) < 0) | |||
| return ret; | |||
| } | |||
| } | |||
| return 1; | |||