Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * HTTP protocol for ffmpeg client
  3.  * Copyright (c) 2000, 2001 Fabrice Bellard
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/avstring.h"
  23. #include "avformat.h"
  24. #include "internal.h"
  25. #include "network.h"
  26. #include "http.h"
  27. #include "os_support.h"
  28. #include "httpauth.h"
  29. #include "url.h"
  30. #include "libavutil/opt.h"
  31.  
  32. #if CONFIG_ZLIB
  33. #include <zlib.h>
  34. #endif
  35.  
  36. /* XXX: POST protocol is not completely implemented because ffmpeg uses
  37.    only a subset of it. */
  38.  
  39. /* The IO buffer size is unrelated to the max URL size in itself, but needs
  40.  * to be large enough to fit the full request headers (including long
  41.  * path names).
  42.  */
  43. #define BUFFER_SIZE MAX_URL_SIZE
  44. #define MAX_REDIRECTS 8
  45.  
  46. typedef struct {
  47.     const AVClass *class;
  48.     URLContext *hd;
  49.     unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;
  50.     int line_count;
  51.     int http_code;
  52.     int64_t chunksize;      /**< Used if "Transfer-Encoding: chunked" otherwise -1. */
  53.     char *content_type;
  54.     char *user_agent;
  55.     int64_t off, filesize;
  56.     int icy_data_read;      ///< how much data was read since last ICY metadata packet
  57.     int icy_metaint;        ///< after how many bytes of read data a new metadata packet will be found
  58.     char location[MAX_URL_SIZE];
  59.     HTTPAuthState auth_state;
  60.     HTTPAuthState proxy_auth_state;
  61.     char *headers;
  62.     int willclose;          /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */
  63.     int seekable;           /**< Control seekability, 0 = disable, 1 = enable, -1 = probe. */
  64.     int chunked_post;
  65.     int end_chunked_post;   /**< A flag which indicates if the end of chunked encoding has been sent. */
  66.     int end_header;         /**< A flag which indicates we have finished to read POST reply. */
  67.     int multiple_requests;  /**< A flag which indicates if we use persistent connections. */
  68.     uint8_t *post_data;
  69.     int post_datalen;
  70.     int is_akamai;
  71.     char *mime_type;
  72.     char *cookies;          ///< holds newline (\n) delimited Set-Cookie header field values (without the "Set-Cookie: " field name)
  73.     int icy;
  74.     char *icy_metadata_headers;
  75.     char *icy_metadata_packet;
  76. #if CONFIG_ZLIB
  77.     int compressed;
  78.     z_stream inflate_stream;
  79.     uint8_t *inflate_buffer;
  80. #endif
  81.     AVDictionary *chained_options;
  82.     int send_expect_100;
  83. } HTTPContext;
  84.  
  85. #define OFFSET(x) offsetof(HTTPContext, x)
  86. #define D AV_OPT_FLAG_DECODING_PARAM
  87. #define E AV_OPT_FLAG_ENCODING_PARAM
  88. #define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION)
  89. static const AVOption options[] = {
  90. {"seekable", "control seekability of connection", OFFSET(seekable), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, D },
  91. {"chunked_post", "use chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E },
  92. {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
  93. {"content_type", "force a content type", OFFSET(content_type), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
  94. {"user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = DEFAULT_USER_AGENT}, 0, 0, D },
  95. {"multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
  96. {"post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D|E },
  97. {"mime_type", "set MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 },
  98. {"cookies", "set cookies to be sent in applicable future requests, use newline delimited Set-Cookie HTTP field value syntax", OFFSET(cookies), AV_OPT_TYPE_STRING, {0}, 0, 0, D },
  99. {"icy", "request ICY metadata", OFFSET(icy), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D },
  100. {"icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 },
  101. {"icy_metadata_packet", "return current ICY metadata packet", OFFSET(icy_metadata_packet), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 },
  102. {"auth_type", "HTTP authentication type", OFFSET(auth_state.auth_type), AV_OPT_TYPE_INT, {.i64 = HTTP_AUTH_NONE}, HTTP_AUTH_NONE, HTTP_AUTH_BASIC, D|E, "auth_type" },
  103. {"none", "No auth method set, autodetect", 0, AV_OPT_TYPE_CONST, {.i64 = HTTP_AUTH_NONE}, 0, 0, D|E, "auth_type" },
  104. {"basic", "HTTP basic authentication", 0, AV_OPT_TYPE_CONST, {.i64 = HTTP_AUTH_BASIC}, 0, 0, D|E, "auth_type" },
  105. {"send_expect_100", "Force sending an Expect: 100-continue header for POST", OFFSET(send_expect_100), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E, "auth_type" },
  106. {NULL}
  107. };
  108. #define HTTP_CLASS(flavor)\
  109. static const AVClass flavor ## _context_class = {\
  110.     .class_name     = #flavor,\
  111.     .item_name      = av_default_item_name,\
  112.     .option         = options,\
  113.     .version        = LIBAVUTIL_VERSION_INT,\
  114. }
  115.  
  116. HTTP_CLASS(http);
  117. HTTP_CLASS(https);
  118.  
  119. static int http_connect(URLContext *h, const char *path, const char *local_path,
  120.                         const char *hoststr, const char *auth,
  121.                         const char *proxyauth, int *new_location);
  122.  
  123. void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
  124. {
  125.     memcpy(&((HTTPContext*)dest->priv_data)->auth_state,
  126.            &((HTTPContext*)src->priv_data)->auth_state, sizeof(HTTPAuthState));
  127.     memcpy(&((HTTPContext*)dest->priv_data)->proxy_auth_state,
  128.            &((HTTPContext*)src->priv_data)->proxy_auth_state,
  129.            sizeof(HTTPAuthState));
  130. }
  131.  
  132. /* return non zero if error */
  133. static int http_open_cnx(URLContext *h, AVDictionary **options)
  134. {
  135.     const char *path, *proxy_path, *lower_proto = "tcp", *local_path;
  136.     char hostname[1024], hoststr[1024], proto[10];
  137.     char auth[1024], proxyauth[1024] = "";
  138.     char path1[MAX_URL_SIZE];
  139.     char buf[1024], urlbuf[MAX_URL_SIZE];
  140.     int port, use_proxy, err, location_changed = 0, redirects = 0, attempts = 0;
  141.     HTTPAuthType cur_auth_type, cur_proxy_auth_type;
  142.     HTTPContext *s = h->priv_data;
  143.  
  144.     /* fill the dest addr */
  145.  redo:
  146.     /* needed in any case to build the host string */
  147.     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
  148.                  hostname, sizeof(hostname), &port,
  149.                  path1, sizeof(path1), s->location);
  150.     ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
  151.  
  152.     proxy_path = getenv("http_proxy");
  153.     use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), hostname) &&
  154.                 proxy_path != NULL && av_strstart(proxy_path, "http://", NULL);
  155.  
  156.     if (!strcmp(proto, "https")) {
  157.         lower_proto = "tls";
  158.         use_proxy = 0;
  159.         if (port < 0)
  160.             port = 443;
  161.     }
  162.     if (port < 0)
  163.         port = 80;
  164.  
  165.     if (path1[0] == '\0')
  166.         path = "/";
  167.     else
  168.         path = path1;
  169.     local_path = path;
  170.     if (use_proxy) {
  171.         /* Reassemble the request URL without auth string - we don't
  172.          * want to leak the auth to the proxy. */
  173.         ff_url_join(urlbuf, sizeof(urlbuf), proto, NULL, hostname, port, "%s",
  174.                     path1);
  175.         path = urlbuf;
  176.         av_url_split(NULL, 0, proxyauth, sizeof(proxyauth),
  177.                      hostname, sizeof(hostname), &port, NULL, 0, proxy_path);
  178.     }
  179.  
  180.     ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL);
  181.  
  182.     if (!s->hd) {
  183.         err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
  184.                          &h->interrupt_callback, options);
  185.         if (err < 0)
  186.             goto fail;
  187.     }
  188.  
  189.     cur_auth_type = s->auth_state.auth_type;
  190.     cur_proxy_auth_type = s->auth_state.auth_type;
  191.     if (http_connect(h, path, local_path, hoststr, auth, proxyauth, &location_changed) < 0)
  192.         goto fail;
  193.     attempts++;
  194.     if (s->http_code == 401) {
  195.         if ((cur_auth_type == HTTP_AUTH_NONE || s->auth_state.stale) &&
  196.             s->auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) {
  197.             ffurl_closep(&s->hd);
  198.             goto redo;
  199.         } else
  200.             goto fail;
  201.     }
  202.     if (s->http_code == 407) {
  203.         if ((cur_proxy_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
  204.             s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) {
  205.             ffurl_closep(&s->hd);
  206.             goto redo;
  207.         } else
  208.             goto fail;
  209.     }
  210.     if ((s->http_code == 301 || s->http_code == 302 || s->http_code == 303 || s->http_code == 307)
  211.         && location_changed == 1) {
  212.         /* url moved, get next */
  213.         ffurl_closep(&s->hd);
  214.         if (redirects++ >= MAX_REDIRECTS)
  215.             return AVERROR(EIO);
  216.         /* Restart the authentication process with the new target, which
  217.          * might use a different auth mechanism. */
  218.         memset(&s->auth_state, 0, sizeof(s->auth_state));
  219.         attempts = 0;
  220.         location_changed = 0;
  221.         goto redo;
  222.     }
  223.     return 0;
  224.  fail:
  225.     if (s->hd)
  226.         ffurl_closep(&s->hd);
  227.     return AVERROR(EIO);
  228. }
  229.  
  230. int ff_http_do_new_request(URLContext *h, const char *uri)
  231. {
  232.     HTTPContext *s = h->priv_data;
  233.     AVDictionary *options = NULL;
  234.     int ret;
  235.  
  236.     s->off = 0;
  237.     s->icy_data_read = 0;
  238.     av_strlcpy(s->location, uri, sizeof(s->location));
  239.  
  240.     av_dict_copy(&options, s->chained_options, 0);
  241.     ret = http_open_cnx(h, &options);
  242.     av_dict_free(&options);
  243.     return ret;
  244. }
  245.  
  246. static int http_open(URLContext *h, const char *uri, int flags,
  247.                      AVDictionary **options)
  248. {
  249.     HTTPContext *s = h->priv_data;
  250.     int ret;
  251.  
  252.     if( s->seekable == 1 )
  253.         h->is_streamed = 0;
  254.     else
  255.         h->is_streamed = 1;
  256.  
  257.     s->filesize = -1;
  258.     av_strlcpy(s->location, uri, sizeof(s->location));
  259.     if (options)
  260.         av_dict_copy(&s->chained_options, *options, 0);
  261.  
  262.     if (s->headers) {
  263.         int len = strlen(s->headers);
  264.         if (len < 2 || strcmp("\r\n", s->headers + len - 2))
  265.             av_log(h, AV_LOG_WARNING, "No trailing CRLF found in HTTP header.\n");
  266.     }
  267.  
  268.     ret = http_open_cnx(h, options);
  269.     if (ret < 0)
  270.         av_dict_free(&s->chained_options);
  271.     return ret;
  272. }
  273. static int http_getc(HTTPContext *s)
  274. {
  275.     int len;
  276.     if (s->buf_ptr >= s->buf_end) {
  277.         len = ffurl_read(s->hd, s->buffer, BUFFER_SIZE);
  278.         if (len < 0) {
  279.             return len;
  280.         } else if (len == 0) {
  281.             return -1;
  282.         } else {
  283.             s->buf_ptr = s->buffer;
  284.             s->buf_end = s->buffer + len;
  285.         }
  286.     }
  287.     return *s->buf_ptr++;
  288. }
  289.  
  290. static int http_get_line(HTTPContext *s, char *line, int line_size)
  291. {
  292.     int ch;
  293.     char *q;
  294.  
  295.     q = line;
  296.     for(;;) {
  297.         ch = http_getc(s);
  298.         if (ch < 0)
  299.             return ch;
  300.         if (ch == '\n') {
  301.             /* process line */
  302.             if (q > line && q[-1] == '\r')
  303.                 q--;
  304.             *q = '\0';
  305.  
  306.             return 0;
  307.         } else {
  308.             if ((q - line) < line_size - 1)
  309.                 *q++ = ch;
  310.         }
  311.     }
  312. }
  313.  
  314. static int process_line(URLContext *h, char *line, int line_count,
  315.                         int *new_location)
  316. {
  317.     HTTPContext *s = h->priv_data;
  318.     char *tag, *p, *end;
  319.     char redirected_location[MAX_URL_SIZE];
  320.  
  321.     /* end of header */
  322.     if (line[0] == '\0') {
  323.         s->end_header = 1;
  324.         return 0;
  325.     }
  326.  
  327.     p = line;
  328.     if (line_count == 0) {
  329.         while (!av_isspace(*p) && *p != '\0')
  330.             p++;
  331.         while (av_isspace(*p))
  332.             p++;
  333.         s->http_code = strtol(p, &end, 10);
  334.  
  335.         av_dlog(NULL, "http_code=%d\n", s->http_code);
  336.  
  337.         /* error codes are 4xx and 5xx, but regard 401 as a success, so we
  338.          * don't abort until all headers have been parsed. */
  339.         if (s->http_code >= 400 && s->http_code < 600 && (s->http_code != 401
  340.             || s->auth_state.auth_type != HTTP_AUTH_NONE) &&
  341.             (s->http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) {
  342.             end += strspn(end, SPACE_CHARS);
  343.             av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n",
  344.                    s->http_code, end);
  345.             return -1;
  346.         }
  347.     } else {
  348.         while (*p != '\0' && *p != ':')
  349.             p++;
  350.         if (*p != ':')
  351.             return 1;
  352.  
  353.         *p = '\0';
  354.         tag = line;
  355.         p++;
  356.         while (av_isspace(*p))
  357.             p++;
  358.         if (!av_strcasecmp(tag, "Location")) {
  359.             ff_make_absolute_url(redirected_location, sizeof(redirected_location), s->location, p);
  360.             av_strlcpy(s->location, redirected_location, sizeof(s->location));
  361.             *new_location = 1;
  362.         } else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -1) {
  363.             s->filesize = strtoll(p, NULL, 10);
  364.         } else if (!av_strcasecmp (tag, "Content-Range")) {
  365.             /* "bytes $from-$to/$document_size" */
  366.             const char *slash;
  367.             if (!strncmp (p, "bytes ", 6)) {
  368.                 p += 6;
  369.                 s->off = strtoll(p, NULL, 10);
  370.                 if ((slash = strchr(p, '/')) && strlen(slash) > 0)
  371.                     s->filesize = strtoll(slash+1, NULL, 10);
  372.             }
  373.             if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
  374.                 h->is_streamed = 0; /* we _can_ in fact seek */
  375.         } else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5) && s->seekable == -1) {
  376.             h->is_streamed = 0;
  377.         } else if (!av_strcasecmp (tag, "Transfer-Encoding") && !av_strncasecmp(p, "chunked", 7)) {
  378.             s->filesize = -1;
  379.             s->chunksize = 0;
  380.         } else if (!av_strcasecmp (tag, "WWW-Authenticate")) {
  381.             ff_http_auth_handle_header(&s->auth_state, tag, p);
  382.         } else if (!av_strcasecmp (tag, "Authentication-Info")) {
  383.             ff_http_auth_handle_header(&s->auth_state, tag, p);
  384.         } else if (!av_strcasecmp (tag, "Proxy-Authenticate")) {
  385.             ff_http_auth_handle_header(&s->proxy_auth_state, tag, p);
  386.         } else if (!av_strcasecmp (tag, "Connection")) {
  387.             if (!strcmp(p, "close"))
  388.                 s->willclose = 1;
  389.         } else if (!av_strcasecmp (tag, "Server") && !av_strcasecmp (p, "AkamaiGHost")) {
  390.             s->is_akamai = 1;
  391.         } else if (!av_strcasecmp (tag, "Content-Type")) {
  392.             av_free(s->mime_type); s->mime_type = av_strdup(p);
  393.         } else if (!av_strcasecmp (tag, "Set-Cookie")) {
  394.             if (!s->cookies) {
  395.                 if (!(s->cookies = av_strdup(p)))
  396.                     return AVERROR(ENOMEM);
  397.             } else {
  398.                 char *tmp = s->cookies;
  399.                 size_t str_size = strlen(tmp) + strlen(p) + 2;
  400.                 if (!(s->cookies = av_malloc(str_size))) {
  401.                     s->cookies = tmp;
  402.                     return AVERROR(ENOMEM);
  403.                 }
  404.                 snprintf(s->cookies, str_size, "%s\n%s", tmp, p);
  405.                 av_free(tmp);
  406.             }
  407.         } else if (!av_strcasecmp (tag, "Icy-MetaInt")) {
  408.             s->icy_metaint = strtoll(p, NULL, 10);
  409.         } else if (!av_strncasecmp(tag, "Icy-", 4)) {
  410.             // Concat all Icy- header lines
  411.             char *buf = av_asprintf("%s%s: %s\n",
  412.                 s->icy_metadata_headers ? s->icy_metadata_headers : "", tag, p);
  413.             if (!buf)
  414.                 return AVERROR(ENOMEM);
  415.             av_freep(&s->icy_metadata_headers);
  416.             s->icy_metadata_headers = buf;
  417.         } else if (!av_strcasecmp (tag, "Content-Encoding")) {
  418.             if (!av_strncasecmp(p, "gzip", 4) || !av_strncasecmp(p, "deflate", 7)) {
  419. #if CONFIG_ZLIB
  420.                 s->compressed = 1;
  421.                 inflateEnd(&s->inflate_stream);
  422.                 if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) {
  423.                     av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n",
  424.                            s->inflate_stream.msg);
  425.                     return AVERROR(ENOSYS);
  426.                 }
  427.                 if (zlibCompileFlags() & (1 << 17)) {
  428.                     av_log(h, AV_LOG_WARNING, "Your zlib was compiled without gzip support.\n");
  429.                     return AVERROR(ENOSYS);
  430.                 }
  431. #else
  432.                 av_log(h, AV_LOG_WARNING, "Compressed (%s) content, need zlib with gzip support\n", p);
  433.                 return AVERROR(ENOSYS);
  434. #endif
  435.             } else if (!av_strncasecmp(p, "identity", 8)) {
  436.                 // The normal, no-encoding case (although servers shouldn't include
  437.                 // the header at all if this is the case).
  438.             } else {
  439.                 av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p);
  440.             }
  441.         }
  442.     }
  443.     return 1;
  444. }
  445.  
  446. /**
  447.  * Create a string containing cookie values for use as a HTTP cookie header
  448.  * field value for a particular path and domain from the cookie values stored in
  449.  * the HTTP protocol context. The cookie string is stored in *cookies.
  450.  *
  451.  * @return a negative value if an error condition occurred, 0 otherwise
  452.  */
  453. static int get_cookies(HTTPContext *s, char **cookies, const char *path,
  454.                        const char *domain)
  455. {
  456.     // cookie strings will look like Set-Cookie header field values.  Multiple
  457.     // Set-Cookie fields will result in multiple values delimited by a newline
  458.     int ret = 0;
  459.     char *next, *cookie, *set_cookies = av_strdup(s->cookies), *cset_cookies = set_cookies;
  460.  
  461.     if (!set_cookies) return AVERROR(EINVAL);
  462.  
  463.     *cookies = NULL;
  464.     while ((cookie = av_strtok(set_cookies, "\n", &next))) {
  465.         int domain_offset = 0;
  466.         char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = NULL;
  467.         set_cookies = NULL;
  468.  
  469.         while ((param = av_strtok(cookie, "; ", &next_param))) {
  470.             cookie = NULL;
  471.             if        (!av_strncasecmp("path=",   param, 5)) {
  472.                 av_free(cpath);
  473.                 cpath = av_strdup(&param[5]);
  474.             } else if (!av_strncasecmp("domain=", param, 7)) {
  475.                 av_free(cdomain);
  476.                 cdomain = av_strdup(&param[7]);
  477.             } else if (!av_strncasecmp("secure",  param, 6) ||
  478.                        !av_strncasecmp("comment", param, 7) ||
  479.                        !av_strncasecmp("max-age", param, 7) ||
  480.                        !av_strncasecmp("version", param, 7)) {
  481.                 // ignore Comment, Max-Age, Secure and Version
  482.             } else {
  483.                 av_free(cvalue);
  484.                 cvalue = av_strdup(param);
  485.             }
  486.         }
  487.         if (!cdomain)
  488.             cdomain = av_strdup(domain);
  489.  
  490.         // ensure all of the necessary values are valid
  491.         if (!cdomain || !cpath || !cvalue) {
  492.             av_log(s, AV_LOG_WARNING,
  493.                    "Invalid cookie found, no value, path or domain specified\n");
  494.             goto done_cookie;
  495.         }
  496.  
  497.         // check if the request path matches the cookie path
  498.         if (av_strncasecmp(path, cpath, strlen(cpath)))
  499.             goto done_cookie;
  500.  
  501.         // the domain should be at least the size of our cookie domain
  502.         domain_offset = strlen(domain) - strlen(cdomain);
  503.         if (domain_offset < 0)
  504.             goto done_cookie;
  505.  
  506.         // match the cookie domain
  507.         if (av_strcasecmp(&domain[domain_offset], cdomain))
  508.             goto done_cookie;
  509.  
  510.         // cookie parameters match, so copy the value
  511.         if (!*cookies) {
  512.             if (!(*cookies = av_strdup(cvalue))) {
  513.                 ret = AVERROR(ENOMEM);
  514.                 goto done_cookie;
  515.             }
  516.         } else {
  517.             char *tmp = *cookies;
  518.             size_t str_size = strlen(cvalue) + strlen(*cookies) + 3;
  519.             if (!(*cookies = av_malloc(str_size))) {
  520.                 ret = AVERROR(ENOMEM);
  521.                 goto done_cookie;
  522.             }
  523.             snprintf(*cookies, str_size, "%s; %s", tmp, cvalue);
  524.             av_free(tmp);
  525.         }
  526.  
  527.         done_cookie:
  528.         av_free(cdomain);
  529.         av_free(cpath);
  530.         av_free(cvalue);
  531.         if (ret < 0) {
  532.             if (*cookies) av_freep(cookies);
  533.             av_free(cset_cookies);
  534.             return ret;
  535.         }
  536.     }
  537.  
  538.     av_free(cset_cookies);
  539.  
  540.     return 0;
  541. }
  542.  
  543. static inline int has_header(const char *str, const char *header)
  544. {
  545.     /* header + 2 to skip over CRLF prefix. (make sure you have one!) */
  546.     if (!str)
  547.         return 0;
  548.     return av_stristart(str, header + 2, NULL) || av_stristr(str, header);
  549. }
  550.  
  551. static int http_read_header(URLContext *h, int *new_location)
  552. {
  553.     HTTPContext *s = h->priv_data;
  554.     char line[MAX_URL_SIZE];
  555.     int err = 0;
  556.  
  557.     s->chunksize = -1;
  558.  
  559.     for (;;) {
  560.         if ((err = http_get_line(s, line, sizeof(line))) < 0)
  561.             return err;
  562.  
  563.         av_dlog(NULL, "header='%s'\n", line);
  564.  
  565.         err = process_line(h, line, s->line_count, new_location);
  566.         if (err < 0)
  567.             return err;
  568.         if (err == 0)
  569.             break;
  570.         s->line_count++;
  571.     }
  572.  
  573.     return err;
  574. }
  575.  
  576. static int http_connect(URLContext *h, const char *path, const char *local_path,
  577.                         const char *hoststr, const char *auth,
  578.                         const char *proxyauth, int *new_location)
  579. {
  580.     HTTPContext *s = h->priv_data;
  581.     int post, err;
  582.     char headers[4096] = "";
  583.     char *authstr = NULL, *proxyauthstr = NULL;
  584.     int64_t off = s->off;
  585.     int len = 0;
  586.     const char *method;
  587.     int send_expect_100 = 0;
  588.  
  589.  
  590.     /* send http header */
  591.     post = h->flags & AVIO_FLAG_WRITE;
  592.  
  593.     if (s->post_data) {
  594.         /* force POST method and disable chunked encoding when
  595.          * custom HTTP post data is set */
  596.         post = 1;
  597.         s->chunked_post = 0;
  598.     }
  599.  
  600.     method = post ? "POST" : "GET";
  601.     authstr = ff_http_auth_create_response(&s->auth_state, auth, local_path,
  602.                                            method);
  603.     proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth,
  604.                                                 local_path, method);
  605.     if (post && !s->post_data) {
  606.         send_expect_100 = s->send_expect_100;
  607.         /* The user has supplied authentication but we don't know the auth type,
  608.          * send Expect: 100-continue to get the 401 response including the
  609.          * WWW-Authenticate header, or an 100 continue if no auth actually
  610.          * is needed. */
  611.         if (auth && *auth &&
  612.             s->auth_state.auth_type == HTTP_AUTH_NONE &&
  613.             s->http_code != 401)
  614.             send_expect_100 = 1;
  615.     }
  616.  
  617.     /* set default headers if needed */
  618.     if (!has_header(s->headers, "\r\nUser-Agent: "))
  619.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  620.                            "User-Agent: %s\r\n", s->user_agent);
  621.     if (!has_header(s->headers, "\r\nAccept: "))
  622.         len += av_strlcpy(headers + len, "Accept: */*\r\n",
  623.                           sizeof(headers) - len);
  624.     // Note: we send this on purpose even when s->off is 0 when we're probing,
  625.     // since it allows us to detect more reliably if a (non-conforming)
  626.     // server supports seeking by analysing the reply headers.
  627.     if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->seekable == -1))
  628.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  629.                            "Range: bytes=%"PRId64"-\r\n", s->off);
  630.     if (send_expect_100 && !has_header(s->headers, "\r\nExpect: "))
  631.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  632.                            "Expect: 100-continue\r\n");
  633.  
  634.     if (!has_header(s->headers, "\r\nConnection: ")) {
  635.         if (s->multiple_requests) {
  636.             len += av_strlcpy(headers + len, "Connection: keep-alive\r\n",
  637.                               sizeof(headers) - len);
  638.         } else {
  639.             len += av_strlcpy(headers + len, "Connection: close\r\n",
  640.                               sizeof(headers) - len);
  641.         }
  642.     }
  643.  
  644.     if (!has_header(s->headers, "\r\nHost: "))
  645.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  646.                            "Host: %s\r\n", hoststr);
  647.     if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
  648.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  649.                            "Content-Length: %d\r\n", s->post_datalen);
  650.     if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type)
  651.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  652.                            "Content-Type: %s\r\n", s->content_type);
  653.     if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) {
  654.         char *cookies = NULL;
  655.         if (!get_cookies(s, &cookies, path, hoststr)) {
  656.             len += av_strlcatf(headers + len, sizeof(headers) - len,
  657.                                "Cookie: %s\r\n", cookies);
  658.             av_free(cookies);
  659.         }
  660.     }
  661.     if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy) {
  662.         len += av_strlcatf(headers + len, sizeof(headers) - len,
  663.                            "Icy-MetaData: %d\r\n", 1);
  664.     }
  665.  
  666.     /* now add in custom headers */
  667.     if (s->headers)
  668.         av_strlcpy(headers + len, s->headers, sizeof(headers) - len);
  669.  
  670.     snprintf(s->buffer, sizeof(s->buffer),
  671.              "%s %s HTTP/1.1\r\n"
  672.              "%s"
  673.              "%s"
  674.              "%s"
  675.              "%s%s"
  676.              "\r\n",
  677.              method,
  678.              path,
  679.              post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "",
  680.              headers,
  681.              authstr ? authstr : "",
  682.              proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : "");
  683.  
  684.     av_freep(&authstr);
  685.     av_freep(&proxyauthstr);
  686.     if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
  687.         return err;
  688.  
  689.     if (s->post_data)
  690.         if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0)
  691.             return err;
  692.  
  693.     /* init input buffer */
  694.     s->buf_ptr = s->buffer;
  695.     s->buf_end = s->buffer;
  696.     s->line_count = 0;
  697.     s->off = 0;
  698.     s->icy_data_read = 0;
  699.     s->filesize = -1;
  700.     s->willclose = 0;
  701.     s->end_chunked_post = 0;
  702.     s->end_header = 0;
  703.     if (post && !s->post_data && !send_expect_100) {
  704.         /* Pretend that it did work. We didn't read any header yet, since
  705.          * we've still to send the POST data, but the code calling this
  706.          * function will check http_code after we return. */
  707.         s->http_code = 200;
  708.         return 0;
  709.     }
  710.  
  711.     /* wait for header */
  712.     err = http_read_header(h, new_location);
  713.     if (err < 0)
  714.         return err;
  715.  
  716.     return (off == s->off) ? 0 : -1;
  717. }
  718.  
  719.  
  720. static int http_buf_read(URLContext *h, uint8_t *buf, int size)
  721. {
  722.     HTTPContext *s = h->priv_data;
  723.     int len;
  724.     /* read bytes from input buffer first */
  725.     len = s->buf_end - s->buf_ptr;
  726.     if (len > 0) {
  727.         if (len > size)
  728.             len = size;
  729.         memcpy(buf, s->buf_ptr, len);
  730.         s->buf_ptr += len;
  731.     } else {
  732.         if (!s->willclose && s->filesize >= 0 && s->off >= s->filesize)
  733.             return AVERROR_EOF;
  734.         len = ffurl_read(s->hd, buf, size);
  735.     }
  736.     if (len > 0) {
  737.         s->off += len;
  738.         s->icy_data_read += len;
  739.         if (s->chunksize > 0)
  740.             s->chunksize -= len;
  741.     }
  742.     return len;
  743. }
  744.  
  745. #if CONFIG_ZLIB
  746. #define DECOMPRESS_BUF_SIZE (256 * 1024)
  747. static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
  748. {
  749.     HTTPContext *s = h->priv_data;
  750.     int ret;
  751.  
  752.     if (!s->inflate_buffer) {
  753.         s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE);
  754.         if (!s->inflate_buffer)
  755.             return AVERROR(ENOMEM);
  756.     }
  757.  
  758.     if (s->inflate_stream.avail_in == 0) {
  759.         int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE);
  760.         if (read <= 0)
  761.             return read;
  762.         s->inflate_stream.next_in  = s->inflate_buffer;
  763.         s->inflate_stream.avail_in = read;
  764.     }
  765.  
  766.     s->inflate_stream.avail_out = size;
  767.     s->inflate_stream.next_out  = buf;
  768.  
  769.     ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH);
  770.     if (ret != Z_OK && ret != Z_STREAM_END)
  771.         av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s\n", ret, s->inflate_stream.msg);
  772.  
  773.     return size - s->inflate_stream.avail_out;
  774. }
  775. #endif
  776.  
  777. static int http_read(URLContext *h, uint8_t *buf, int size)
  778. {
  779.     HTTPContext *s = h->priv_data;
  780.     int err, new_location;
  781.  
  782.     if (!s->hd)
  783.         return AVERROR_EOF;
  784.  
  785.     if (s->end_chunked_post && !s->end_header) {
  786.         err = http_read_header(h, &new_location);
  787.         if (err < 0)
  788.             return err;
  789.     }
  790.  
  791.     if (s->chunksize >= 0) {
  792.         if (!s->chunksize) {
  793.             char line[32];
  794.  
  795.             for(;;) {
  796.                 do {
  797.                     if ((err = http_get_line(s, line, sizeof(line))) < 0)
  798.                         return err;
  799.                 } while (!*line);    /* skip CR LF from last chunk */
  800.  
  801.                 s->chunksize = strtoll(line, NULL, 16);
  802.  
  803.                 av_dlog(NULL, "Chunked encoding data size: %"PRId64"'\n", s->chunksize);
  804.  
  805.                 if (!s->chunksize)
  806.                     return 0;
  807.                 break;
  808.             }
  809.         }
  810.         size = FFMIN(size, s->chunksize);
  811.     }
  812.     if (s->icy_metaint > 0) {
  813.         int remaining = s->icy_metaint - s->icy_data_read; /* until next metadata packet */
  814.         if (!remaining) {
  815.             // The metadata packet is variable sized. It has a 1 byte header
  816.             // which sets the length of the packet (divided by 16). If it's 0,
  817.             // the metadata doesn't change. After the packet, icy_metaint bytes
  818.             // of normal data follow.
  819.             int ch = http_getc(s);
  820.             if (ch < 0)
  821.                 return ch;
  822.             if (ch > 0) {
  823.                 char data[255 * 16 + 1];
  824.                 int n;
  825.                 int ret;
  826.                 ch *= 16;
  827.                 for (n = 0; n < ch; n++)
  828.                     data[n] = http_getc(s);
  829.                 data[ch + 1] = 0;
  830.                 if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
  831.                     return ret;
  832.             }
  833.             s->icy_data_read = 0;
  834.             remaining = s->icy_metaint;
  835.         }
  836.         size = FFMIN(size, remaining);
  837.     }
  838. #if CONFIG_ZLIB
  839.     if (s->compressed)
  840.         return http_buf_read_compressed(h, buf, size);
  841. #endif
  842.     return http_buf_read(h, buf, size);
  843. }
  844.  
  845. /* used only when posting data */
  846. static int http_write(URLContext *h, const uint8_t *buf, int size)
  847. {
  848.     char temp[11] = "";  /* 32-bit hex + CRLF + nul */
  849.     int ret;
  850.     char crlf[] = "\r\n";
  851.     HTTPContext *s = h->priv_data;
  852.  
  853.     if (!s->chunked_post) {
  854.         /* non-chunked data is sent without any special encoding */
  855.         return ffurl_write(s->hd, buf, size);
  856.     }
  857.  
  858.     /* silently ignore zero-size data since chunk encoding that would
  859.      * signal EOF */
  860.     if (size > 0) {
  861.         /* upload data using chunked encoding */
  862.         snprintf(temp, sizeof(temp), "%x\r\n", size);
  863.  
  864.         if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 ||
  865.             (ret = ffurl_write(s->hd, buf, size)) < 0 ||
  866.             (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0)
  867.             return ret;
  868.     }
  869.     return size;
  870. }
  871.  
  872. static int http_shutdown(URLContext *h, int flags)
  873. {
  874.     int ret = 0;
  875.     char footer[] = "0\r\n\r\n";
  876.     HTTPContext *s = h->priv_data;
  877.  
  878.     /* signal end of chunked encoding if used */
  879.     if ((flags & AVIO_FLAG_WRITE) && s->chunked_post) {
  880.         ret = ffurl_write(s->hd, footer, sizeof(footer) - 1);
  881.         ret = ret > 0 ? 0 : ret;
  882.         s->end_chunked_post = 1;
  883.     }
  884.  
  885.     return ret;
  886. }
  887.  
  888. static int http_close(URLContext *h)
  889. {
  890.     int ret = 0;
  891.     HTTPContext *s = h->priv_data;
  892.  
  893. #if CONFIG_ZLIB
  894.     inflateEnd(&s->inflate_stream);
  895.     av_freep(&s->inflate_buffer);
  896. #endif
  897.  
  898.     if (!s->end_chunked_post) {
  899.         /* Close the write direction by sending the end of chunked encoding. */
  900.         ret = http_shutdown(h, h->flags);
  901.     }
  902.  
  903.     if (s->hd)
  904.         ffurl_closep(&s->hd);
  905.     av_dict_free(&s->chained_options);
  906.     return ret;
  907. }
  908.  
  909. static int64_t http_seek(URLContext *h, int64_t off, int whence)
  910. {
  911.     HTTPContext *s = h->priv_data;
  912.     URLContext *old_hd = s->hd;
  913.     int64_t old_off = s->off;
  914.     uint8_t old_buf[BUFFER_SIZE];
  915.     int old_buf_size;
  916.     AVDictionary *options = NULL;
  917.  
  918.     if (whence == AVSEEK_SIZE)
  919.         return s->filesize;
  920.     else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed)
  921.         return -1;
  922.  
  923.     /* we save the old context in case the seek fails */
  924.     old_buf_size = s->buf_end - s->buf_ptr;
  925.     memcpy(old_buf, s->buf_ptr, old_buf_size);
  926.     s->hd = NULL;
  927.     if (whence == SEEK_CUR)
  928.         off += s->off;
  929.     else if (whence == SEEK_END)
  930.         off += s->filesize;
  931.     s->off = off;
  932.  
  933.     /* if it fails, continue on old connection */
  934.     av_dict_copy(&options, s->chained_options, 0);
  935.     if (http_open_cnx(h, &options) < 0) {
  936.         av_dict_free(&options);
  937.         memcpy(s->buffer, old_buf, old_buf_size);
  938.         s->buf_ptr = s->buffer;
  939.         s->buf_end = s->buffer + old_buf_size;
  940.         s->hd = old_hd;
  941.         s->off = old_off;
  942.         return -1;
  943.     }
  944.     av_dict_free(&options);
  945.     ffurl_close(old_hd);
  946.     return off;
  947. }
  948.  
  949. static int
  950. http_get_file_handle(URLContext *h)
  951. {
  952.     HTTPContext *s = h->priv_data;
  953.     return ffurl_get_file_handle(s->hd);
  954. }
  955.  
  956. #if CONFIG_HTTP_PROTOCOL
  957. URLProtocol ff_http_protocol = {
  958.     .name                = "http",
  959.     .url_open2           = http_open,
  960.     .url_read            = http_read,
  961.     .url_write           = http_write,
  962.     .url_seek            = http_seek,
  963.     .url_close           = http_close,
  964.     .url_get_file_handle = http_get_file_handle,
  965.     .url_shutdown        = http_shutdown,
  966.     .priv_data_size      = sizeof(HTTPContext),
  967.     .priv_data_class     = &http_context_class,
  968.     .flags               = URL_PROTOCOL_FLAG_NETWORK,
  969. };
  970. #endif
  971. #if CONFIG_HTTPS_PROTOCOL
  972. URLProtocol ff_https_protocol = {
  973.     .name                = "https",
  974.     .url_open2           = http_open,
  975.     .url_read            = http_read,
  976.     .url_write           = http_write,
  977.     .url_seek            = http_seek,
  978.     .url_close           = http_close,
  979.     .url_get_file_handle = http_get_file_handle,
  980.     .url_shutdown        = http_shutdown,
  981.     .priv_data_size      = sizeof(HTTPContext),
  982.     .priv_data_class     = &https_context_class,
  983.     .flags               = URL_PROTOCOL_FLAG_NETWORK,
  984. };
  985. #endif
  986.  
  987. #if CONFIG_HTTPPROXY_PROTOCOL
  988. static int http_proxy_close(URLContext *h)
  989. {
  990.     HTTPContext *s = h->priv_data;
  991.     if (s->hd)
  992.         ffurl_closep(&s->hd);
  993.     return 0;
  994. }
  995.  
  996. static int http_proxy_open(URLContext *h, const char *uri, int flags)
  997. {
  998.     HTTPContext *s = h->priv_data;
  999.     char hostname[1024], hoststr[1024];
  1000.     char auth[1024], pathbuf[1024], *path;
  1001.     char lower_url[100];
  1002.     int port, ret = 0, attempts = 0;
  1003.     HTTPAuthType cur_auth_type;
  1004.     char *authstr;
  1005.     int new_loc;
  1006.  
  1007.     if( s->seekable == 1 )
  1008.         h->is_streamed = 0;
  1009.     else
  1010.         h->is_streamed = 1;
  1011.  
  1012.     av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
  1013.                  pathbuf, sizeof(pathbuf), uri);
  1014.     ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
  1015.     path = pathbuf;
  1016.     if (*path == '/')
  1017.         path++;
  1018.  
  1019.     ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
  1020.                 NULL);
  1021. redo:
  1022.     ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
  1023.                      &h->interrupt_callback, NULL);
  1024.     if (ret < 0)
  1025.         return ret;
  1026.  
  1027.     authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth,
  1028.                                            path, "CONNECT");
  1029.     snprintf(s->buffer, sizeof(s->buffer),
  1030.              "CONNECT %s HTTP/1.1\r\n"
  1031.              "Host: %s\r\n"
  1032.              "Connection: close\r\n"
  1033.              "%s%s"
  1034.              "\r\n",
  1035.              path,
  1036.              hoststr,
  1037.              authstr ? "Proxy-" : "", authstr ? authstr : "");
  1038.     av_freep(&authstr);
  1039.  
  1040.     if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
  1041.         goto fail;
  1042.  
  1043.     s->buf_ptr = s->buffer;
  1044.     s->buf_end = s->buffer;
  1045.     s->line_count = 0;
  1046.     s->filesize = -1;
  1047.     cur_auth_type = s->proxy_auth_state.auth_type;
  1048.  
  1049.     /* Note: This uses buffering, potentially reading more than the
  1050.      * HTTP header. If tunneling a protocol where the server starts
  1051.      * the conversation, we might buffer part of that here, too.
  1052.      * Reading that requires using the proper ffurl_read() function
  1053.      * on this URLContext, not using the fd directly (as the tls
  1054.      * protocol does). This shouldn't be an issue for tls though,
  1055.      * since the client starts the conversation there, so there
  1056.      * is no extra data that we might buffer up here.
  1057.      */
  1058.     ret = http_read_header(h, &new_loc);
  1059.     if (ret < 0)
  1060.         goto fail;
  1061.  
  1062.     attempts++;
  1063.     if (s->http_code == 407 &&
  1064.         (cur_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
  1065.         s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) {
  1066.         ffurl_closep(&s->hd);
  1067.         goto redo;
  1068.     }
  1069.  
  1070.     if (s->http_code < 400)
  1071.         return 0;
  1072.     ret = AVERROR(EIO);
  1073.  
  1074. fail:
  1075.     http_proxy_close(h);
  1076.     return ret;
  1077. }
  1078.  
  1079. static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
  1080. {
  1081.     HTTPContext *s = h->priv_data;
  1082.     return ffurl_write(s->hd, buf, size);
  1083. }
  1084.  
  1085. URLProtocol ff_httpproxy_protocol = {
  1086.     .name                = "httpproxy",
  1087.     .url_open            = http_proxy_open,
  1088.     .url_read            = http_buf_read,
  1089.     .url_write           = http_proxy_write,
  1090.     .url_close           = http_proxy_close,
  1091.     .url_get_file_handle = http_get_file_handle,
  1092.     .priv_data_size      = sizeof(HTTPContext),
  1093.     .flags               = URL_PROTOCOL_FLAG_NETWORK,
  1094. };
  1095. #endif
  1096.