[FFmpeg-devel] [PATCH] Rudimentary cookie support for HTTP

Duncan Salerno duncan.salerno at gmail.com
Tue Oct 9 22:09:58 CEST 2012


For comment. The aim is primarly for HLS (and I guess later HDS) where a request to an initial URL sets some cookies, which are required in later requests as authentication. There is no need for cookies to persist across runs of ffmpeg.

However with this implementation cookies are never free'd - is this okay? Any better suggestions?
---
 libavformat/http.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index d385011..ef6f296 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -87,6 +87,18 @@ static const AVClass flavor ## _context_class = {\
 HTTP_CLASS(http);
 HTTP_CLASS(https);
 
+
+/**
+ * Store cookies in a linked list.
+ */
+typedef struct Cookie {
+    const char *domain;                 ///< domain
+    const char *path;                   ///< path
+    const char *value;                  ///< cookie name value pair (ie. name=value)
+    struct Cookie *next;                ///< next Cookie
+} Cookie;
+static Cookie *cookiejar = NULL;
+
 static int http_connect(URLContext *h, const char *path, const char *local_path,
                         const char *hoststr, const char *auth,
                         const char *proxyauth, int *new_location);
@@ -344,6 +356,27 @@ static int process_line(URLContext *h, char *line, int line_count,
                 s->willclose = 1;
         } else if (!av_strcasecmp (tag, "Server") && !av_strcasecmp (p, "AkamaiGHost")) {
             s->is_akamai = 1;
+        } else if (!av_strcasecmp (tag, "Set-Cookie")) {
+            /* eg. LSID=DQAAAK…Eaem_vYg; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT */
+            char *token, *ptr=strchr(p,';');
+            if (*ptr)
+            {
+                Cookie *c = av_malloc(sizeof(Cookie));
+                *ptr++ = '\0';
+                c->value = av_strdup(p);
+                c->path = "/";
+                c->domain = NULL;
+                while (token = av_strtok(ptr, "; ", &ptr)) {
+                    char *value;
+                    av_strtok(token, "=", &value);
+                    if (av_strcasecmp (token, "Domain") == 0)
+                        c->domain = av_strdup(value);
+                    else if (av_strcasecmp (token, "Path") == 0)
+                        c->path = av_strdup(value);
+                }
+                c->next = cookiejar;
+                cookiejar = c;
+            }
         }
     }
     return 1;
@@ -439,6 +472,35 @@ static int http_connect(URLContext *h, const char *path, const char *local_path,
     if (!has_header(s->headers, "\r\nHost: "))
         len += av_strlcatf(headers + len, sizeof(headers) - len,
                            "Host: %s\r\n", hoststr);
+    if (!has_header(s->headers, "\r\nCookie: ")) {
+        Cookie *c;
+        int output_header = 0;
+        for (c = cookiejar; c != NULL; c=c->next)
+        {
+            /* Check if cookie path matches start of path */
+            if (strncmp(c->path, path, strlen(c->path)))
+                continue;
+            /* Check if end of host matches cookie host */
+            if (strlen(c->domain) > strlen(hoststr) || av_strcasecmp(c->domain, hoststr+(strlen(hoststr)-strlen(c->domain))))
+                continue;
+            /* Cookie looks good to output */
+            if (!output_header)
+            {
+                len += av_strlcatf(headers + len, sizeof(headers) - len,
+                                   "Cookie: ");
+                output_header = 1;
+            }
+            len += av_strlcatf(headers + len, sizeof(headers) - len,
+                               "%s; ", c->value);
+        }
+        if (output_header)
+        {
+            /* Switch last two characters "; " to "\r\n" */
+            headers[len-2] = '\r';
+            headers[len-1] = '\n';
+        }
+    }
+
     if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
         len += av_strlcatf(headers + len, sizeof(headers) - len,
                            "Content-Length: %d\r\n", s->post_datalen);
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list