Re: [FFmpeg-devel] Backport HLS Cookie Authentication Fixes to 3.3

2017-06-03 Thread Micah Galizia

On 2017-06-01 09:04 PM, Michael Niedermayer wrote:


On Tue, May 30, 2017 at 09:29:53PM -0400, Micah Galizia wrote:

Hello,

I'd like to backport the HLS cookie authentication fixes to 3.3 so that Kodi 18 
picks them up. Originally, this was a three patch set but the first fix (to 
av_small_strptime) is already in 3.3 and doesn't need to be backported.  The 
two that are still required are:

- c4c73020f4bbf261f0b263be82de575c17fa5a60 (hls)
- 28b24670741e1de25bfc7b5ea7c1d6dbae1aef6f (http)

Hopefully this is acceptable - let me know if anything is out of order.

applied

thx


Excellent, TYVM.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] libavformat/http: Ignore expired cookies

2017-05-30 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc>
(cherry picked from commit 28b24670741e1de25bfc7b5ea7c1d6dbae1aef6f)
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 213 +++--
 1 file changed, 156 insertions(+), 57 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7204..d06103ab6d 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY19
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -680,10 +683,112 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 return 0;
 }
 
+static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
+{
+char exp_buf[MAX_EXPIRY];
+int i, j, exp_buf_len = MAX_EXPIRY-1;
+char *expiry;
+
+// strip off any punctuation or whitespace
+for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
+if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
+(exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
+(exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
+exp_buf[j] = exp_str[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+expiry = exp_buf;
+
+// move the string beyond the day of week
+while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
+expiry++;
+
+return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : 
AVERROR(EINVAL);
+}
+
+static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
+{
+char *param, *next_param, *cstr, *back;
+
+if (!(cstr = av_strdup(set_cookie)))
+return AVERROR(EINVAL);
+
+// strip any trailing whitespace
+back = [strlen(cstr)-1];
+while (strchr(WHITESPACES, *back)) {
+*back='\0';
+back--;
+}
+
+next_param = cstr;
+while ((param = av_strtok(next_param, ";", _param))) {
+char *name, *value;
+param += strspn(param, WHITESPACES);
+if ((name = av_strtok(param, "=", ))) {
+if (av_dict_set(dict, name, value, 0) < 0) {
+av_free(cstr);
+return -1;
+}
+}
+}
+
+av_free(cstr);
+return 0;
+}
+
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
+AVDictionary *new_params = NULL;
+AVDictionaryEntry *e, *cookie_entry;
 char *eql, *name;
 
+// ensure the cookie is parsable
+if (parse_set_cookie(p, _params))
+return -1;
+
+// if there is no cookie value there is nothing to parse
+cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
+if (!cookie_entry || !cookie_entry->value) {
+av_dict_free(_params);
+return -1;
+}
+
+// ensure the cookie is not expired or older than an existing value
+if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
+struct tm new_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+AVDictionaryEntry *e2;
+
+// if the cookie has already expired ignore it
+if (av_timegm(_tm) < av_gettime() / 100) {
+av_dict_free(_params);
+return -1;
+}
+
+// only replace an older cookie with the same name
+e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
+if (e2 && e2->value) {
+AVDictionary *old_params = NULL;
+if (!parse_set_cookie(p, _params)) {
+e2 = av_dict_get(old_params, "expires", NULL, 0);
+if (e2 && e2->value) {
+struct tm old_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+if (av_timegm(_tm) < av_timegm(_tm)) {
+av_dict_free(_params);
+av_dict_free(_params);
+return -1;
+}
+}
+}
+}
+av_dict_free(_params);
+}
+}
+}
+
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
@@ -868,7 +973,7 @

[FFmpeg-devel] [PATCH 2/2] libavformat/hls: Observe Set-Cookie headers

2017-05-30 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc>
(cherry picked from commit c4c73020f4bbf261f0b263be82de575c17fa5a60)
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/hls.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..42022690f1 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
 if (ret >= 0) {
 // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (!(s->flags & AVFMT_FLAG_CUSTOM_IO))
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
 av_dict_set(, "cookies", c->cookies, 0);
 }
 
-- 
2.11.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] Backport HLS Cookie Authentication Fixes to 3.3

2017-05-30 Thread Micah Galizia
Hello,

I'd like to backport the HLS cookie authentication fixes to 3.3 so that Kodi 18 
picks them up. Originally, this was a three patch set but the first fix (to 
av_small_strptime) is already in 3.3 and doesn't need to be backported.  The 
two that are still required are:

- c4c73020f4bbf261f0b263be82de575c17fa5a60 (hls)
- 28b24670741e1de25bfc7b5ea7c1d6dbae1aef6f (http)

Hopefully this is acceptable - let me know if anything is out of order.

Thanks,

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-30 Thread Micah Galizia

On 2017-05-28 08:44 PM, Michael Niedermayer wrote:

On Fri, May 26, 2017 at 09:29:04PM -0400, Micah Galizia wrote:

On Sat, May 20, 2017 at 9:36 PM, Micah Galizia <micahgali...@gmail.com> wrote:

On 2017-05-17 05:23 AM, wm4 wrote:

On Sat, 6 May 2017 14:28:10 -0400
Micah Galizia <micahgali...@gmail.com> wrote:


On 2017-05-05 09:28 PM, wm4 wrote:

On Fri,  5 May 2017 20:55:05 -0400
Micah Galizia <micahgali...@gmail.com> wrote:


Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
libavformat/hls.c | 12 ++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..bda9abecfa 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s,
AVIOContext **pb, const char *url,
ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
if (ret >= 0) {
// update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (s->flags ^ AVFMT_FLAG_CUSTOM_IO)
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN,
(uint8_t**)_cookies);

Did you mean & instead of ^?

No, the original code was structured to set *u to null (and thus did not
copy cookies) iff AVFMT_FLAG_CUSTOM_IO was set in the flags.  So using ^
is logically equivalent -- cookies are copied only if
AVFMT_FLAG_CUSTOM_IO is not set.


Did you find out yet what difference AVFMT_FLAG_CUSTOM_IO is supposed
to make in the existing code?

Yes, I wrote back about it a day or two ago... here is the reference to
its original inclusion:
https://lists.ffmpeg.org/pipermail/ffmpeg-trac/2013-February/013020.html.
When the code was originally implemented we were using s->pb->opaque,
which in FFMPEG we could assume was a URLContext with options (one of
them possibly being "cookies").

Based on the email above, that wasn't true for other apps like mplayer,
and could cause crashes trying to treat opaque as a URLContext. So that
is the purpose of checking the AVFMT_FLAG_CUSTOM_IO flag (way back in
2013).

Now though, we don't seem to touch opaque at all. The options are stored
in AVIOContext's av_class, which does have options.  Based on this I
think both patches are safe: this version has less change, but the
original gets rid of the check against AVFMT_FLAG_CUSTOM_IO that I don't
think we need anymore.

I hope that clears things up.

Sorry, I missed that. I guess this code is an artifact of some severely
unclean hook up of the AVOPtion API to AVIOContext, that breaks with
custom I/O. I guess your patch is fine then.

I just wonder how an API user is supposed to pass along cookies then.
My code passes an AVDictionary via a "cookies" entry when opening the
HLS demuxer with custom I/O, so I was wondering whether the patch
changes behavior here.


I wouldn't have expected anyone to pass the cookies to the HLS demuxer
directly -- there is an http protocol AVOption that should pass it along to
the demuxer. But I guess thats the whole point of the custom IO, right? It'd
replace the http demuxer?

Even so, I don't think this is a good reason to hold up the the patch - it
corrects the problem for apps that use the http protocol and maintains the
existing behavior -- cookies are not (and were not) copied when the custom
flag is set because u was set to null. Am I wrong in that interpretation of
the existing behavior?

Hi,

What else do I need to do to get this fix checked in?

patch applied

thx


TYVM!
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-26 Thread Micah Galizia
On Sat, May 20, 2017 at 9:36 PM, Micah Galizia <micahgali...@gmail.com> wrote:
> On 2017-05-17 05:23 AM, wm4 wrote:
>>
>> On Sat, 6 May 2017 14:28:10 -0400
>> Micah Galizia <micahgali...@gmail.com> wrote:
>>
>>> On 2017-05-05 09:28 PM, wm4 wrote:
>>>>
>>>> On Fri,  5 May 2017 20:55:05 -0400
>>>> Micah Galizia <micahgali...@gmail.com> wrote:
>>>>
>>>>>
>>>>> Signed-off-by: Micah Galizia <micahgali...@gmail.com>
>>>>> ---
>>>>>libavformat/hls.c | 12 ++--
>>>>>1 file changed, 10 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/libavformat/hls.c b/libavformat/hls.c
>>>>> index bac53a4350..bda9abecfa 100644
>>>>> --- a/libavformat/hls.c
>>>>> +++ b/libavformat/hls.c
>>>>> @@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s,
>>>>> AVIOContext **pb, const char *url,
>>>>>ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
>>>>>if (ret >= 0) {
>>>>>// update cookies on http response with setcookies.
>>>>> -void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
>>>>> -update_options(>cookies, "cookies", u);
>>>>> +char *new_cookies = NULL;
>>>>> +
>>>>> +if (s->flags ^ AVFMT_FLAG_CUSTOM_IO)
>>>>> +av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN,
>>>>> (uint8_t**)_cookies);
>>>>
>>>> Did you mean & instead of ^?
>>>
>>> No, the original code was structured to set *u to null (and thus did not
>>> copy cookies) iff AVFMT_FLAG_CUSTOM_IO was set in the flags.  So using ^
>>> is logically equivalent -- cookies are copied only if
>>> AVFMT_FLAG_CUSTOM_IO is not set.
>>>
>>>> Did you find out yet what difference AVFMT_FLAG_CUSTOM_IO is supposed
>>>> to make in the existing code?
>>>
>>> Yes, I wrote back about it a day or two ago... here is the reference to
>>> its original inclusion:
>>> https://lists.ffmpeg.org/pipermail/ffmpeg-trac/2013-February/013020.html.
>>> When the code was originally implemented we were using s->pb->opaque,
>>> which in FFMPEG we could assume was a URLContext with options (one of
>>> them possibly being "cookies").
>>>
>>> Based on the email above, that wasn't true for other apps like mplayer,
>>> and could cause crashes trying to treat opaque as a URLContext. So that
>>> is the purpose of checking the AVFMT_FLAG_CUSTOM_IO flag (way back in
>>> 2013).
>>>
>>> Now though, we don't seem to touch opaque at all. The options are stored
>>> in AVIOContext's av_class, which does have options.  Based on this I
>>> think both patches are safe: this version has less change, but the
>>> original gets rid of the check against AVFMT_FLAG_CUSTOM_IO that I don't
>>> think we need anymore.
>>>
>>> I hope that clears things up.
>>
>> Sorry, I missed that. I guess this code is an artifact of some severely
>> unclean hook up of the AVOPtion API to AVIOContext, that breaks with
>> custom I/O. I guess your patch is fine then.
>>
>> I just wonder how an API user is supposed to pass along cookies then.
>> My code passes an AVDictionary via a "cookies" entry when opening the
>> HLS demuxer with custom I/O, so I was wondering whether the patch
>> changes behavior here.
>
>
> I wouldn't have expected anyone to pass the cookies to the HLS demuxer
> directly -- there is an http protocol AVOption that should pass it along to
> the demuxer. But I guess thats the whole point of the custom IO, right? It'd
> replace the http demuxer?
>
> Even so, I don't think this is a good reason to hold up the the patch - it
> corrects the problem for apps that use the http protocol and maintains the
> existing behavior -- cookies are not (and were not) copied when the custom
> flag is set because u was set to null. Am I wrong in that interpretation of
> the existing behavior?

Hi,

What else do I need to do to get this fix checked in?

Thanks
-- 
"The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one."   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-20 Thread Micah Galizia

On 2017-05-17 05:23 AM, wm4 wrote:

On Sat, 6 May 2017 14:28:10 -0400
Micah Galizia <micahgali...@gmail.com> wrote:


On 2017-05-05 09:28 PM, wm4 wrote:

On Fri,  5 May 2017 20:55:05 -0400
Micah Galizia <micahgali...@gmail.com> wrote:
  

Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
   libavformat/hls.c | 12 ++--
   1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..bda9abecfa 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
   ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
   if (ret >= 0) {
   // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (s->flags ^ AVFMT_FLAG_CUSTOM_IO)
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);

Did you mean & instead of ^?

No, the original code was structured to set *u to null (and thus did not
copy cookies) iff AVFMT_FLAG_CUSTOM_IO was set in the flags.  So using ^
is logically equivalent -- cookies are copied only if
AVFMT_FLAG_CUSTOM_IO is not set.


Did you find out yet what difference AVFMT_FLAG_CUSTOM_IO is supposed
to make in the existing code?

Yes, I wrote back about it a day or two ago... here is the reference to
its original inclusion:
https://lists.ffmpeg.org/pipermail/ffmpeg-trac/2013-February/013020.html.
When the code was originally implemented we were using s->pb->opaque,
which in FFMPEG we could assume was a URLContext with options (one of
them possibly being "cookies").

Based on the email above, that wasn't true for other apps like mplayer,
and could cause crashes trying to treat opaque as a URLContext. So that
is the purpose of checking the AVFMT_FLAG_CUSTOM_IO flag (way back in 2013).

Now though, we don't seem to touch opaque at all. The options are stored
in AVIOContext's av_class, which does have options.  Based on this I
think both patches are safe: this version has less change, but the
original gets rid of the check against AVFMT_FLAG_CUSTOM_IO that I don't
think we need anymore.

I hope that clears things up.

Sorry, I missed that. I guess this code is an artifact of some severely
unclean hook up of the AVOPtion API to AVIOContext, that breaks with
custom I/O. I guess your patch is fine then.

I just wonder how an API user is supposed to pass along cookies then.
My code passes an AVDictionary via a "cookies" entry when opening the
HLS demuxer with custom I/O, so I was wondering whether the patch
changes behavior here.


I wouldn't have expected anyone to pass the cookies to the HLS demuxer 
directly -- there is an http protocol AVOption that should pass it along 
to the demuxer. But I guess thats the whole point of the custom IO, 
right? It'd replace the http demuxer?


Even so, I don't think this is a good reason to hold up the the patch - 
it corrects the problem for apps that use the http protocol and 
maintains the existing behavior -- cookies are not (and were not) copied 
when the custom flag is set because u was set to null. Am I wrong in 
that interpretation of the existing behavior?


Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-16 Thread Micah Galizia

On 2017-05-16 04:57 PM, Michael Niedermayer wrote:

On Sat, May 06, 2017 at 02:28:10PM -0400, Micah Galizia wrote:

On 2017-05-05 09:28 PM, wm4 wrote:


Did you mean & instead of ^?

No, the original code was structured to set *u to null (and thus did
not copy cookies) iff AVFMT_FLAG_CUSTOM_IO was set in the flags.  So
using ^ is logically equivalent -- cookies are copied only if
AVFMT_FLAG_CUSTOM_IO is not set.

it would also copy if another flag is set, is that intended ?


... I think that is what wm4 was getting at too. That is wrong and not 
intended. I'll resubmit with !(a) which is the proper logic.


Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-16 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/hls.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..42022690f1 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
 if (ret >= 0) {
 // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (!(s->flags & AVFMT_FLAG_CUSTOM_IO))
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
 av_dict_set(, "cookies", c->cookies, 0);
 }
 
-- 
2.11.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-14 Thread Micah Galizia

On 2017-05-06 02:28 PM, Micah Galizia wrote:

On 2017-05-05 09:28 PM, wm4 wrote:

On Fri,  5 May 2017 20:55:05 -0400
Micah Galizia <micahgali...@gmail.com> wrote:


Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
  libavformat/hls.c | 12 ++--
  1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..bda9abecfa 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s, 
AVIOContext **pb, const char *url,

  ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
  if (ret >= 0) {
  // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (s->flags ^ AVFMT_FLAG_CUSTOM_IO)
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);

Did you mean & instead of ^?


No, the original code was structured to set *u to null (and thus did 
not copy cookies) iff AVFMT_FLAG_CUSTOM_IO was set in the flags.  So 
using ^ is logically equivalent -- cookies are copied only if 
AVFMT_FLAG_CUSTOM_IO is not set.



Did you find out yet what difference AVFMT_FLAG_CUSTOM_IO is supposed
to make in the existing code?
Yes, I wrote back about it a day or two ago... here is the reference 
to its original inclusion: 
https://lists.ffmpeg.org/pipermail/ffmpeg-trac/2013-February/013020.html. 
When the code was originally implemented we were using s->pb->opaque, 
which in FFMPEG we could assume was a URLContext with options (one of 
them possibly being "cookies").


Based on the email above, that wasn't true for other apps like 
mplayer, and could cause crashes trying to treat opaque as a 
URLContext. So that is the purpose of checking the 
AVFMT_FLAG_CUSTOM_IO flag (way back in 2013).


Now though, we don't seem to touch opaque at all. The options are 
stored in AVIOContext's av_class, which does have options.  Based on 
this I think both patches are safe: this version has less change, but 
the original gets rid of the check against AVFMT_FLAG_CUSTOM_IO that I 
don't think we need anymore.


I hope that clears things up.


Hi, is there anything further needed to get this fix committed?

Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-06 Thread Micah Galizia

On 2017-05-05 09:28 PM, wm4 wrote:

On Fri,  5 May 2017 20:55:05 -0400
Micah Galizia <micahgali...@gmail.com> wrote:


Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
  libavformat/hls.c | 12 ++--
  1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..bda9abecfa 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
  ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
  if (ret >= 0) {
  // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (s->flags ^ AVFMT_FLAG_CUSTOM_IO)
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);

Did you mean & instead of ^?


No, the original code was structured to set *u to null (and thus did not 
copy cookies) iff AVFMT_FLAG_CUSTOM_IO was set in the flags.  So using ^ 
is logically equivalent -- cookies are copied only if 
AVFMT_FLAG_CUSTOM_IO is not set.



Did you find out yet what difference AVFMT_FLAG_CUSTOM_IO is supposed
to make in the existing code?
Yes, I wrote back about it a day or two ago... here is the reference to 
its original inclusion: 
https://lists.ffmpeg.org/pipermail/ffmpeg-trac/2013-February/013020.html. 
When the code was originally implemented we were using s->pb->opaque, 
which in FFMPEG we could assume was a URLContext with options (one of 
them possibly being "cookies").


Based on the email above, that wasn't true for other apps like mplayer, 
and could cause crashes trying to treat opaque as a URLContext. So that 
is the purpose of checking the AVFMT_FLAG_CUSTOM_IO flag (way back in 2013).


Now though, we don't seem to touch opaque at all. The options are stored 
in AVIOContext's av_class, which does have options.  Based on this I 
think both patches are safe: this version has less change, but the 
original gets rid of the check against AVFMT_FLAG_CUSTOM_IO that I don't 
think we need anymore.


I hope that clears things up.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-05 Thread Micah Galizia
Hi,

This is a simpler version of the other patch that still observes 
AVFMT_FLAG_CUSTOM_IO.

Thanks in advance.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-05 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/hls.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..bda9abecfa 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,16 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
 if (ret >= 0) {
 // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+if (s->flags ^ AVFMT_FLAG_CUSTOM_IO)
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
 av_dict_set(, "cookies", c->cookies, 0);
 }
 
-- 
2.11.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-04 Thread Micah Galizia

On 2017-05-02 09:04 PM, wm4 wrote:

On Tue,  2 May 2017 20:47:06 -0400
Micah Galizia <micahgali...@gmail.com> wrote:


Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
  libavformat/hls.c | 12 +---
  1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..643d50e1da 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,14 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
  ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
  if (ret >= 0) {
  // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
  av_dict_set(, "cookies", c->cookies, 0);
  }
  
@@ -1608,7 +1614,7 @@ static int hls_close(AVFormatContext *s)
  
  static int hls_read_header(AVFormatContext *s)

  {
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
+void *u = s->pb;
  HLSContext *c = s->priv_data;
  int ret = 0, i;
  int highest_cur_seq_no = 0;

Not comfortable with this without knowing what the purpose of this
CUSTOM_IO check was.


Sorry, I misunderstood a prior email. Regarding why we check the custom 
IO flags, I was able to track down the following: 
https://lists.ffmpeg.org/pipermail/ffmpeg-trac/2013-February/013020.html 
for the hls_read_header. It was originally added in commit 
db6e2e848b21d988fb108995387a8c7836da4dc7 back in 2013.


After reading that, I think the problem it was trying to solve was about 
treating pb->opaque as a urlcontext -- but the code no longer does that, 
unless I've misunderstood all the casting in av_opt_get. What I believe 
it does now is call av_opt_get(*pb...), which eventually winds up in 
av_opt_find2 where it pulls options out the AVClass (av_class) contained 
in AVIOContext and starts reading its options. It doesn't seem to be 
touching opaque field in AVIOContext anymore.


Given this, I _think_ what I did is still ok. However, I can also change 
the patch to leave hls_read_header alone and add an if (s->flags ^ 
AVFMT_FLAG_CUSTOM_IO) before getting the new_cookies. This, effectively, 
fixes the bug without disregarding the check against 
AVFMT_FLAG_CUSTOM_IO -- best of both worlds and a smaller patch.


If nobody can confirm my analysis that opaque is now being left alone 
(thus, no longer requiring the check against the custom IO flag) then 
I'll just put the smaller patch up.


Thanks,

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavformat/hls: Observe Set-Cookie headers

2017-05-02 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/hls.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..643d50e1da 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,14 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
 if (ret >= 0) {
 // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
 av_dict_set(, "cookies", c->cookies, 0);
 }
 
@@ -1608,7 +1614,7 @@ static int hls_close(AVFormatContext *s)
 
 static int hls_read_header(AVFormatContext *s)
 {
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
+void *u = s->pb;
 HLSContext *c = s->priv_data;
 int ret = 0, i;
 int highest_cur_seq_no = 0;
-- 
2.11.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Observe Set-Cookie headers in HLS streams

2017-05-02 Thread Micah Galizia
Hi,

I was hoping to get this one in too so I've named the patch appropriately.

With this change, cookie authenticated streams (eg: Neulion) should play 
properly again.

Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-05-02 Thread Micah Galizia
Hello,

Same patch with corrected name.

Thanks in advance.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] libavformat/tests: Add http cookie tests cases to fate

2017-05-02 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/Makefile   |   1 +
 libavformat/tests/http.c   | 186 +
 tests/fate/libavformat.mak |   5 ++
 tests/ref/fate/http|  30 
 4 files changed, 222 insertions(+)
 create mode 100644 libavformat/tests/http.c
 create mode 100644 tests/ref/fate/http

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 6bdfbe6789..640a348c2f 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -598,6 +598,7 @@ SKIPHEADERS-$(CONFIG_NETWORK)+= network.h rtsp.h
 
 TESTPROGS = seek\
 url \
+http\
 #   async   \
 
 FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK)   += fifo_muxer
diff --git a/libavformat/tests/http.c b/libavformat/tests/http.c
new file mode 100644
index 00..76a70ae814
--- /dev/null
+++ b/libavformat/tests/http.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2017 Micah Galizia
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavformat/http.c"
+#include "libavformat/avio.h"
+
+typedef struct GetCookiesTestCase {
+const char *set_cookie;
+const char *cookie_str;
+const char *path;
+const char *domain;
+} GetCookiesTestCase;
+
+// Don't go past Tue, 19 Jan 2038 03:14:07 GMT or 32-bit time_t overflows
+GetCookiesTestCase get_cookies_tests[] = {
+/* Test good and expired cookie. Should be acceptable */
+{"first=\"good\"; Domain=.test.com; Path=/\nsecond=great; 
domain=.test.com; path=/; HttpOnly",
+ "first=\"good\"; second=great", "/hello", "cookie.test.com"},
+
+ /* Test good and expired cookie. Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01 Jan 1970 
00:00:10 GMT; Path=/\ngood=not_expired; domain=.test.com; path=/; expires=Tue, 
19 Jan 2038 03:14:07 GMT; HttpOnly",
+ "good=not_expired", "/hello", "cookie.test.com"},
+
+/* Test a good and expired cookie in the neulion format.
+ * Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01-Jan-1970 
00:00:10 GMT; Path=/\nneulion=not_expired; domain=.test.com; path=/; 
expires=Tue, 19-Jan-2038 03:14:07 GMT; HttpOnly",
+ "neulion=not_expired", "/hello", "cookie.test.com"},
+
+/* Test an expiry date without the day of week specified */
+{"no_day=still_ok; domain=.test.com; path=/; expires=19 Jan 2038 03:14:07 
GMT; HttpOnly",
+ "no_day=still_ok", "/hello", "cookie.test.com"},
+
+/* Test a date that cannot be parsed. Allow the cookie */
+{"unparsable_date=allow_cookie; domain=.test.com; path=/; expires=19 Jon 
2038 03:14:07 GMT; HttpOnly",
+ "unparsable_date=allow_cookie", "/hello", "cookie.test.com"},
+
+/* Test a cookie that has a different domain. Do not use the cookie */
+{"different_domain=exclude; domain=.nottest.com; path=/; expires=19 Jan 
2038 03:14:07 GMT; HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces */
+
{"no_spaces=no_big_deal;domain=.test.com;path=/;expires=Tue,19Jan203803:14:07GMT;HttpOnly",
+ "no_spaces=no_big_deal", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces and is expired. Excluded */
+
{"no_spaces_expired=not_ok;domain=.test.com;path=/;expires=Thu01Jan197010GMT;HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that is too long. */
+{"long=handled;domain=.test.com;path=/;expires=Tue, 19 Jan 2038 
03:14:07GMTGMTGMTGMTGMTGMT;HttpOnly",
+ "long=handled", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie wit

Re: [FFmpeg-devel] [PATCH] libavformat/http: Ignore expired cookies

2017-05-01 Thread Micah Galizia

On 2017-05-01 12:09 PM, Michael Niedermayer wrote:

On Sun, Apr 30, 2017 at 02:25:29PM -0400, Micah Galizia wrote:

Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
  libavformat/http.c | 213 +++--
  1 file changed, 156 insertions(+), 57 deletions(-)

applied

thx


TYVM. If I fix the name of on the second patch (for the unit tests) can 
I get that in too? I figure it can only help prevent future breaks.

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavformat/http: Ignore expired cookies

2017-04-30 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 213 +++--
 1 file changed, 156 insertions(+), 57 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7204..d06103ab6d 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY19
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -680,10 +683,112 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 return 0;
 }
 
+static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
+{
+char exp_buf[MAX_EXPIRY];
+int i, j, exp_buf_len = MAX_EXPIRY-1;
+char *expiry;
+
+// strip off any punctuation or whitespace
+for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
+if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
+(exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
+(exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
+exp_buf[j] = exp_str[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+expiry = exp_buf;
+
+// move the string beyond the day of week
+while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
+expiry++;
+
+return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : 
AVERROR(EINVAL);
+}
+
+static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
+{
+char *param, *next_param, *cstr, *back;
+
+if (!(cstr = av_strdup(set_cookie)))
+return AVERROR(EINVAL);
+
+// strip any trailing whitespace
+back = [strlen(cstr)-1];
+while (strchr(WHITESPACES, *back)) {
+*back='\0';
+back--;
+}
+
+next_param = cstr;
+while ((param = av_strtok(next_param, ";", _param))) {
+char *name, *value;
+param += strspn(param, WHITESPACES);
+if ((name = av_strtok(param, "=", ))) {
+if (av_dict_set(dict, name, value, 0) < 0) {
+av_free(cstr);
+return -1;
+}
+}
+}
+
+av_free(cstr);
+return 0;
+}
+
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
+AVDictionary *new_params = NULL;
+AVDictionaryEntry *e, *cookie_entry;
 char *eql, *name;
 
+// ensure the cookie is parsable
+if (parse_set_cookie(p, _params))
+return -1;
+
+// if there is no cookie value there is nothing to parse
+cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
+if (!cookie_entry || !cookie_entry->value) {
+av_dict_free(_params);
+return -1;
+}
+
+// ensure the cookie is not expired or older than an existing value
+if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
+struct tm new_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+AVDictionaryEntry *e2;
+
+// if the cookie has already expired ignore it
+if (av_timegm(_tm) < av_gettime() / 100) {
+av_dict_free(_params);
+return -1;
+}
+
+// only replace an older cookie with the same name
+e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
+if (e2 && e2->value) {
+AVDictionary *old_params = NULL;
+if (!parse_set_cookie(p, _params)) {
+e2 = av_dict_get(old_params, "expires", NULL, 0);
+if (e2 && e2->value) {
+struct tm old_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+if (av_timegm(_tm) < av_timegm(_tm)) {
+av_dict_free(_params);
+av_dict_free(_params);
+return -1;
+}
+}
+}
+}
+av_dict_free(_params);
+}
+}
+}
+
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
@@ -868,7 +973,7 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 // cookie strings will look like Set-Cookie header field values.  Multiple
 // Set-Cookie fields will result in mul

Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-04-30 Thread Micah Galizia
Hi,

This version fixes the cstr leak and explicitly frees tmp when allocating 
cookies fails. Freeing tmp also means we don't need to free *cookies when ret 
is less than zero.

I've also formatted the name properly, so it'll show up as a new thread.

Thanks in advance.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-04-26 Thread Micah Galizia
Thanks for the review, new fix checks av_dict_set return.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-04-26 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 212 +++--
 1 file changed, 155 insertions(+), 57 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7204..58fc3902ab 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY19
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -680,10 +683,110 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 return 0;
 }
 
+static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
+{
+char exp_buf[MAX_EXPIRY];
+int i, j, exp_buf_len = MAX_EXPIRY-1;
+char *expiry;
+
+// strip off any punctuation or whitespace
+for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
+if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
+(exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
+(exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
+exp_buf[j] = exp_str[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+expiry = exp_buf;
+
+// move the string beyond the day of week
+while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
+expiry++;
+
+return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : 
AVERROR(EINVAL);
+}
+
+static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
+{
+char *param, *next_param, *cstr, *back;
+
+if (!(cstr = av_strdup(set_cookie)))
+return AVERROR(EINVAL);
+
+// strip any trailing whitespace
+back = [strlen(cstr)-1];
+while (strchr(WHITESPACES, *back)) {
+*back='\0';
+back--;
+}
+
+next_param = cstr;
+while ((param = av_strtok(next_param, ";", _param))) {
+char *name, *value;
+param += strspn(param, WHITESPACES);
+if ((name = av_strtok(param, "=", ))) {
+if (av_dict_set(dict, name, value, 0) < 0)
+return -1;
+}
+}
+
+av_free(cstr);
+return 0;
+}
+
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
+AVDictionary *new_params = NULL;
+AVDictionaryEntry *e, *cookie_entry;
 char *eql, *name;
 
+// ensure the cookie is parsable
+if (parse_set_cookie(p, _params))
+return -1;
+
+// if there is no cookie value there is nothing to parse
+cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
+if (!cookie_entry || !cookie_entry->value) {
+av_dict_free(_params);
+return -1;
+}
+
+// ensure the cookie is not expired or older than an existing value
+if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
+struct tm new_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+AVDictionaryEntry *e2;
+
+// if the cookie has already expired ignore it
+if (av_timegm(_tm) < av_gettime() / 100) {
+av_dict_free(_params);
+return -1;
+}
+
+// only replace an older cookie with the same name
+e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
+if (e2 && e2->value) {
+AVDictionary *old_params = NULL;
+if (!parse_set_cookie(p, _params)) {
+e2 = av_dict_get(old_params, "expires", NULL, 0);
+if (e2 && e2->value) {
+struct tm old_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+if (av_timegm(_tm) < av_timegm(_tm)) {
+av_dict_free(_params);
+av_dict_free(_params);
+return -1;
+}
+}
+}
+}
+av_dict_free(_params);
+}
+}
+}
+
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
@@ -868,7 +971,7 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 // cookie strings will look like Set-Cookie header field values.  Multiple
 // Set-Cookie fields will result in multiple values delimited by a newline
 int ret

Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-04-24 Thread Micah Galizia

On 2017-04-08 09:05 PM, Micah Galizia wrote:



Is there something I can do to get this reviewed?

Thanks in advance.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-04-14 Thread Micah Galizia

On 2017-04-08 09:05 PM, Micah Galizia wrote:

Signed-off-by: Micah Galizia <micahgali...@gmail.com>




Hello,

Has anyone had a chance to review this? I was hoping to get the rework 
(if needed) done this weekend.


Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Observe Set-Cookie headers in HLS streams

2017-04-08 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/hls.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4350..643d50e1da 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,14 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
 if (ret >= 0) {
 // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
 av_dict_set(, "cookies", c->cookies, 0);
 }
 
@@ -1608,7 +1614,7 @@ static int hls_close(AVFormatContext *s)
 
 static int hls_read_header(AVFormatContext *s)
 {
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
+void *u = s->pb;
 HLSContext *c = s->priv_data;
 int ret = 0, i;
 int highest_cur_seq_no = 0;
-- 
2.11.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Observe Set-Cookie headers in HLS streams

2017-04-08 Thread Micah Galizia
Hi,

This one gets rid of the check against AVFMT_FLAG_CUSTOM_IO. Let me know if 
anything else needs changing.

Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/2] Ignore expired cookies

2017-04-08 Thread Micah Galizia
The original patch (possibly the implementation it replaced) had a bug that 
would include whitespace (eg: newline) when evaluating Set-Cookie values (eg: 
the domain).

This is corrected in the modified version of that patch.

Thanks
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-04-08 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 211 ++---
 1 file changed, 154 insertions(+), 57 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7204..425711aab5 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY19
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -680,10 +683,109 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 return 0;
 }
 
+static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
+{
+char exp_buf[MAX_EXPIRY];
+int i, j, exp_buf_len = MAX_EXPIRY-1;
+char *expiry;
+
+// strip off any punctuation or whitespace
+for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
+if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
+(exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
+(exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
+exp_buf[j] = exp_str[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+expiry = exp_buf;
+
+// move the string beyond the day of week
+while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
+expiry++;
+
+return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : 
AVERROR(EINVAL);
+}
+
+static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
+{
+char *param, *next_param, *cstr, *back;
+
+if (!(cstr = av_strdup(set_cookie)))
+return AVERROR(EINVAL);
+
+// strip any trailing whitespace
+back = [strlen(cstr)-1];
+while (strchr(WHITESPACES, *back)) {
+*back='\0';
+back--;
+}
+
+next_param = cstr;
+while ((param = av_strtok(next_param, ";", _param))) {
+char *name, *value;
+param += strspn(param, WHITESPACES);
+if ((name = av_strtok(param, "=", ))) {
+av_dict_set(dict, name, value, 0);
+}
+}
+
+av_free(cstr);
+return 0;
+}
+
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
+AVDictionary *new_params = NULL;
+AVDictionaryEntry *e, *cookie_entry;
 char *eql, *name;
 
+// ensure the cookie is parsable
+if (parse_set_cookie(p, _params))
+return -1;
+
+// if there is no cookie value there is nothing to parse
+cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
+if (!cookie_entry || !cookie_entry->value) {
+av_dict_free(_params);
+return -1;
+}
+
+// ensure the cookie is not expired or older than an existing value
+if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
+struct tm new_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+AVDictionaryEntry *e2;
+
+// if the cookie has already expired ignore it
+if (av_timegm(_tm) < av_gettime() / 100) {
+av_dict_free(_params);
+return -1;
+}
+
+// only replace an older cookie with the same name
+e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
+if (e2 && e2->value) {
+AVDictionary *old_params = NULL;
+if (!parse_set_cookie(p, _params)) {
+e2 = av_dict_get(old_params, "expires", NULL, 0);
+if (e2 && e2->value) {
+struct tm old_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+if (av_timegm(_tm) < av_timegm(_tm)) {
+av_dict_free(_params);
+av_dict_free(_params);
+return -1;
+}
+}
+}
+}
+av_dict_free(_params);
+}
+}
+}
+
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
@@ -868,7 +970,7 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 // cookie strings will look like Set-Cookie header field values.  Multiple
 // Set-Cookie fields will result in multiple values delimited by a newline
 int ret = 0;
-char *next, *cookie, *set_coo

Re: [FFmpeg-devel] [PATCH] Observe Set-Cookie headers in HLS streams

2017-04-07 Thread Micah Galizia


On 2017-04-07 02:48 AM, wm4 wrote:

On Thu,  6 Apr 2017 22:48:59 -0400
Micah Galizia<micahgali...@gmail.com> <mailto:micahgali...@gmail.com>  wrote:


Signed-off-by: Micah Galizia<micahgali...@gmail.com> 
<mailto:micahgali...@gmail.com>
---
  libavformat/hls.c | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4..ab81863 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,14 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
  ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
  if (ret >= 0) {
  // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
  av_dict_set(, "cookies", c->cookies, 0);
  }
  

So far, all code is doing the same thing by calling update_options()
on pb, or NULL if it's a custom IO context.

What you seem to change is always using the pb (even if it's a custom
context), duplicating the update_options() code (subtly changing some
corner case behavior), and, this is probably the important one, you use
*pb instead of s->pb.


True. But, the cookies option of *pb comes back NULL _unless_ they are 
updated, so we should check first before replacing. I could also update 
update_options, but that is probably overkill.  I haven't really chased 
down the reason why the cookies sometimes come back (if they get 
changed) and sometimes don't.



I suspect the latter is the only change that matters, and you probably
want:

void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : *pb;


Yes, but then IIRC the flag was always set and we would actually try to 
pull cookies from NULL, which you allude to below.  Also, without the 
ternary assignment, u is just *pb, so why create another variable?



Now I have no idea why it checks "s->flags & AVFMT_FLAG_CUSTOM_IO", or
what it means, but it feels very wrong. A common case is probably that
the main playlist is accessed through a custom AVIOContext, but further
nested playlists or actual .ts data probably use libavformat's code.

I'm thinking that all uses of AVFMT_FLAG_CUSTOM_IO anywhere are
probably bugs.


I'm happy to take it out the check for AVFMT_FLAG_CUSTOM_IO -- there are 
only two and on the streams I tested it had no effect. However, I was 
hoping someone could explain why its there. If someone wants to write 
back and explain I'd appreciate it, otherwise, I'll send a patch to get 
rid of it.


Thanks,
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Observe Set-Cookie headers in HLS streams

2017-04-06 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/hls.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index bac53a4..ab81863 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -630,8 +630,14 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 ret = s->io_open(s, pb, url, AVIO_FLAG_READ, );
 if (ret >= 0) {
 // update cookies on http response with setcookies.
-void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
-update_options(>cookies, "cookies", u);
+char *new_cookies = NULL;
+
+av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, 
(uint8_t**)_cookies);
+if (new_cookies) {
+av_free(c->cookies);
+c->cookies = new_cookies;
+}
+
 av_dict_set(, "cookies", c->cookies, 0);
 }
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Observe Set-Cookie headers in HLS streams

2017-04-06 Thread Micah Galizia
Hello,

I noticed some Set-Cookie headers are being ignored by the HLS demuxer. Patch 
attached fixes it.

Previously, the cookies wouldn't get updated from the right AVIOContext, or not 
at all if AVFMT_FLAG_CUSTOM_IO is set -- I'm not really sure why that was done 
so please let me know if I overlooked something.

Thanks in advance.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-04-05 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/Makefile   |   1 +
 libavformat/tests/http.c   | 186 +
 tests/fate/libavformat.mak |   5 ++
 tests/ref/fate/http|  30 
 4 files changed, 222 insertions(+)
 create mode 100644 libavformat/tests/http.c
 create mode 100644 tests/ref/fate/http

diff --git a/libavformat/Makefile b/libavformat/Makefile
index f56ef16..a4abd1b 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -597,6 +597,7 @@ SKIPHEADERS-$(CONFIG_NETWORK)+= network.h rtsp.h
 
 TESTPROGS = seek\
 url \
+http\
 #   async   \
 
 FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK)   += fifo_muxer
diff --git a/libavformat/tests/http.c b/libavformat/tests/http.c
new file mode 100644
index 000..76a70ae
--- /dev/null
+++ b/libavformat/tests/http.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2017 Micah Galizia
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavformat/http.c"
+#include "libavformat/avio.h"
+
+typedef struct GetCookiesTestCase {
+const char *set_cookie;
+const char *cookie_str;
+const char *path;
+const char *domain;
+} GetCookiesTestCase;
+
+// Don't go past Tue, 19 Jan 2038 03:14:07 GMT or 32-bit time_t overflows
+GetCookiesTestCase get_cookies_tests[] = {
+/* Test good and expired cookie. Should be acceptable */
+{"first=\"good\"; Domain=.test.com; Path=/\nsecond=great; 
domain=.test.com; path=/; HttpOnly",
+ "first=\"good\"; second=great", "/hello", "cookie.test.com"},
+
+ /* Test good and expired cookie. Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01 Jan 1970 
00:00:10 GMT; Path=/\ngood=not_expired; domain=.test.com; path=/; expires=Tue, 
19 Jan 2038 03:14:07 GMT; HttpOnly",
+ "good=not_expired", "/hello", "cookie.test.com"},
+
+/* Test a good and expired cookie in the neulion format.
+ * Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01-Jan-1970 
00:00:10 GMT; Path=/\nneulion=not_expired; domain=.test.com; path=/; 
expires=Tue, 19-Jan-2038 03:14:07 GMT; HttpOnly",
+ "neulion=not_expired", "/hello", "cookie.test.com"},
+
+/* Test an expiry date without the day of week specified */
+{"no_day=still_ok; domain=.test.com; path=/; expires=19 Jan 2038 03:14:07 
GMT; HttpOnly",
+ "no_day=still_ok", "/hello", "cookie.test.com"},
+
+/* Test a date that cannot be parsed. Allow the cookie */
+{"unparsable_date=allow_cookie; domain=.test.com; path=/; expires=19 Jon 
2038 03:14:07 GMT; HttpOnly",
+ "unparsable_date=allow_cookie", "/hello", "cookie.test.com"},
+
+/* Test a cookie that has a different domain. Do not use the cookie */
+{"different_domain=exclude; domain=.nottest.com; path=/; expires=19 Jan 
2038 03:14:07 GMT; HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces */
+
{"no_spaces=no_big_deal;domain=.test.com;path=/;expires=Tue,19Jan203803:14:07GMT;HttpOnly",
+ "no_spaces=no_big_deal", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces and is expired. Excluded */
+
{"no_spaces_expired=not_ok;domain=.test.com;path=/;expires=Thu01Jan197010GMT;HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that is too long. */
+{"long=handled;domain=.test.com;path=/;expires=Tue, 19 Jan 2038 
03:14:07GMTGMTGMTGMTGMTGMT;HttpOnly",
+ "long=handled", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that starts with t

[FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-04-05 Thread Micah Galizia
Hi,

I didn't realize there was a year 2038 problem -- dates beyond it overflow a 
32-bit time_t -- I've made the unit tests 32-bit compatible now.

Thank you!
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-04-02 Thread Micah Galizia
Hi,

No more passing null to strcmp -- hopefully this addresses the crash.

Thanks in advance.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-04-02 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/Makefile   |   1 +
 libavformat/tests/http.c   | 185 +
 tests/fate/libavformat.mak |   5 ++
 tests/ref/fate/http|  30 
 4 files changed, 221 insertions(+)
 create mode 100644 libavformat/tests/http.c
 create mode 100644 tests/ref/fate/http

diff --git a/libavformat/Makefile b/libavformat/Makefile
index f56ef16..a4abd1b 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -597,6 +597,7 @@ SKIPHEADERS-$(CONFIG_NETWORK)+= network.h rtsp.h
 
 TESTPROGS = seek\
 url \
+http\
 #   async   \
 
 FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK)   += fifo_muxer
diff --git a/libavformat/tests/http.c b/libavformat/tests/http.c
new file mode 100644
index 000..9652e71
--- /dev/null
+++ b/libavformat/tests/http.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2017 Micah Galizia
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavformat/http.c"
+#include "libavformat/avio.h"
+
+typedef struct GetCookiesTestCase {
+const char *set_cookie;
+const char *cookie_str;
+const char *path;
+const char *domain;
+} GetCookiesTestCase;
+
+GetCookiesTestCase get_cookies_tests[] = {
+/* Test good and expired cookie. Should be acceptable */
+{"first=\"good\"; Domain=.test.com; Path=/\nsecond=great; 
domain=.test.com; path=/; HttpOnly",
+ "first=\"good\"; second=great", "/hello", "cookie.test.com"},
+
+ /* Test good and expired cookie. Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01 Jan 1970 
00:00:10 GMT; Path=/\ngood=not_expired; domain=.test.com; path=/; expires=Fri, 
12 Mar 2117 02:53:03 GMT; HttpOnly",
+ "good=not_expired", "/hello", "cookie.test.com"},
+
+/* Test a good and expired cookie in the neulion format.
+ * Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01-Jan-1970 
00:00:10 GMT; Path=/\nneulion=not_expired; domain=.test.com; path=/; 
expires=Fri, 12-Mar-2117 02:53:03 GMT; HttpOnly",
+ "neulion=not_expired", "/hello", "cookie.test.com"},
+
+/* Test an expiry date without the day of week specified */
+{"no_day=still_ok; domain=.test.com; path=/; expires=12-Mar-2117 02:53:03 
GMT; HttpOnly",
+ "no_day=still_ok", "/hello", "cookie.test.com"},
+
+/* Test a date that cannot be parsed. Allow the cookie */
+{"unparsable_date=allow_cookie; domain=.test.com; path=/; 
expires=12-Mur-2117 02:53:03 GMT; HttpOnly",
+ "unparsable_date=allow_cookie", "/hello", "cookie.test.com"},
+
+/* Test a cookie that has a different domain. Do not use the cookie */
+{"different_domain=exclude; domain=.nottest.com; path=/; 
expires=12-Mar-2117 02:53:03 GMT; HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces */
+
{"no_spaces=no_big_deal;domain=.test.com;path=/;expires=Fri,12Mar211702:53:03GMT;HttpOnly",
+ "no_spaces=no_big_deal", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces and is expired. Excluded */
+
{"no_spaces_expired=not_ok;domain=.test.com;path=/;expires=Thu01Jan197010GMT;HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that is too long. */
+{"long=handled;domain=.test.com;path=/;expires=Fri, 12 Mar 2117 
02:53:03GMTGMTGMTGMTGMTGMT;HttpOnly",
+ "long=handled", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that starts with too many characters */
+{"bad_start=ok;domain=

Re: [FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-04-01 Thread Micah Galizia



On 2017-03-31 06:10 AM, Michael Niedermayer wrote:

On Thu, Mar 30, 2017 at 09:33:48PM -0400, Micah Galizia wrote:

Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
  libavformat/Makefile   |   1 +
  libavformat/tests/http.c   | 182 +
  tests/fate/libavformat.mak |   5 ++
  tests/ref/fate/http|  30 
  4 files changed, 218 insertions(+)
  create mode 100644 libavformat/tests/http.c
  create mode 100644 tests/ref/fate/http

the test segfaults

'good=not_expired; domain=.test.com; path=/; expires=Fri, 12 Mar 2117 02:53:03 
GMT; HttpOnly'->'expires'|'Fri, 12 Mar 2117 02:53:03 GMT'
'good=great'->'good'|'great'
0) 'first="good"; Domain=.test.com; Path=/
second=great; domain=.test.com; path=/; HttpOnly'=>'first="good"; second=great'

Unable to parse 'expired="really_old"; Domain=.test.com; Expires=Thu, 01 Jan 
1970 00:00:10 GMT; Path=/'
1) 'expired="really_old"; Domain=.test.com; Expires=Thu, 01 Jan 1970 00:00:10 
GMT; Path=/
good=not_expired; domain=.test.com; path=/; expires=Fri, 12 Mar 2117 02:53:03 GMT; 
HttpOnly'=>'good=not_expired'

Unable to parse 'expired="really_old"; Domain=.test.com; Expires=Thu, 
01-Jan-1970 00:00:10 GMT; Path=/'
2) 'expired="really_old"; Domain=.test.com; Expires=Thu, 01-Jan-1970 00:00:10 
GMT; Path=/
neulion=not_expired; domain=.test.com; path=/; expires=Fri, 12-Mar-2117 02:53:03 
GMT; HttpOnly'=>'neulion=not_expired'

3) 'no_day=still_ok; domain=.test.com; path=/; expires=12-Mar-2117 02:53:03 GMT; 
HttpOnly'=>'no_day=still_ok'

4) 'unparsable_date=allow_cookie; domain=.test.com; path=/; expires=12-Mur-2117 
02:53:03 GMT; HttpOnly'=>'unparsable_date=allow_cookie'

5) 'different_domain=exclude; domain=.nottest.com; path=/; expires=12-Mar-2117 
02:53:03 GMT; HttpOnly'=>'(null)'


Program received signal SIGSEGV, Segmentation fault.
0x75851166 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x75851166 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x0041197c in test_get_cookies () at libavformat/tests/http.c:97
#2  0x0041056b in main () at libavformat/tests/http.c:173

[...]

Thanks,

I'm trying to reproduce your results here without success -- I can't get 
it to crash on my system. I'm on the same architecture as you are 
(x86_64) too... based on the backtrace I'm guessing maybe strcmp doesn't 
like s2 being null, even though it works on my system -- I'll add an 
explicit case for when they're both null so we're not comparing two null 
strings and resubmit.


Thanks for running it/sorry for the crash. I'll try to send a fix today 
some time.

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] Ignore expired cookies

2017-03-30 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 204 ++---
 1 file changed, 147 insertions(+), 57 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7..a9f1b3f 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY19
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -680,10 +683,102 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 return 0;
 }
 
+static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
+{
+char exp_buf[MAX_EXPIRY];
+int i, j, exp_buf_len = MAX_EXPIRY-1;
+char *expiry;
+
+// strip off any punctuation or whitespace
+for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
+if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
+(exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
+(exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
+exp_buf[j] = exp_str[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+expiry = exp_buf;
+
+// move the string beyond the day of week
+while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
+expiry++;
+
+return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : 
AVERROR(EINVAL);
+}
+
+static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
+{
+char *param, *next_param, *cstr;
+
+if (!(cstr = av_strdup(set_cookie)))
+return AVERROR(EINVAL);
+
+next_param = cstr;
+while ((param = av_strtok(next_param, ";", _param))) {
+char *name, *value;
+param += strspn(param, WHITESPACES);
+if ((name = av_strtok(param, "=", ))) {
+av_dict_set(dict, name, value, 0);
+}
+}
+
+av_free(cstr);
+return 0;
+}
+
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
+AVDictionary *new_params = NULL;
+AVDictionaryEntry *e, *cookie_entry;
 char *eql, *name;
 
+// ensure the cookie is parsable
+if (parse_set_cookie(p, _params))
+return -1;
+
+// if there is no cookie value there is nothing to parse
+cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
+if (!cookie_entry || !cookie_entry->value) {
+av_dict_free(_params);
+return -1;
+}
+
+// ensure the cookie is not expired or older than an existing value
+if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
+struct tm new_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+AVDictionaryEntry *e2;
+
+// if the cookie has already expired ignore it
+if (av_timegm(_tm) < av_gettime() / 100) {
+av_dict_free(_params);
+return -1;
+}
+
+// only replace an older cookie with the same name
+e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
+if (e2 && e2->value) {
+AVDictionary *old_params = NULL;
+if (!parse_set_cookie(p, _params)) {
+e2 = av_dict_get(old_params, "expires", NULL, 0);
+if (e2 && e2->value) {
+struct tm old_tm = {0};
+if (!parse_set_cookie_expiry_time(e->value, _tm)) {
+if (av_timegm(_tm) < av_timegm(_tm)) {
+av_dict_free(_params);
+av_dict_free(_params);
+return -1;
+}
+}
+}
+}
+av_dict_free(_params);
+}
+}
+}
+
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
@@ -868,7 +963,7 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 // cookie strings will look like Set-Cookie header field values.  Multiple
 // Set-Cookie fields will result in multiple values delimited by a newline
 int ret = 0;
-char *next, *cookie, *set_cookies = av_strdup(s->cookies), *cset_cookies = 
set_cookies;
+char *cookie, *set_cookies = av_strdup(s->cookies), *next = set_cookies;
 
 if (!set_cookies) re

[FFmpeg-devel] [PATCH 2/2] Add http cookie tests cases to fate

2017-03-30 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/Makefile   |   1 +
 libavformat/tests/http.c   | 182 +
 tests/fate/libavformat.mak |   5 ++
 tests/ref/fate/http|  30 
 4 files changed, 218 insertions(+)
 create mode 100644 libavformat/tests/http.c
 create mode 100644 tests/ref/fate/http

diff --git a/libavformat/Makefile b/libavformat/Makefile
index f56ef16..a4abd1b 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -597,6 +597,7 @@ SKIPHEADERS-$(CONFIG_NETWORK)+= network.h rtsp.h
 
 TESTPROGS = seek\
 url \
+http\
 #   async   \
 
 FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK)   += fifo_muxer
diff --git a/libavformat/tests/http.c b/libavformat/tests/http.c
new file mode 100644
index 000..702cc86
--- /dev/null
+++ b/libavformat/tests/http.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017 Micah Galizia
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavformat/http.c"
+#include "libavformat/avio.h"
+
+typedef struct GetCookiesTestCase {
+const char *set_cookie;
+const char *cookie_str;
+const char *path;
+const char *domain;
+} GetCookiesTestCase;
+
+GetCookiesTestCase get_cookies_tests[] = {
+/* Test good and expired cookie. Should be acceptable */
+{"first=\"good\"; Domain=.test.com; Path=/\nsecond=great; 
domain=.test.com; path=/; HttpOnly",
+ "first=\"good\"; second=great", "/hello", "cookie.test.com"},
+
+ /* Test good and expired cookie. Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01 Jan 1970 
00:00:10 GMT; Path=/\ngood=not_expired; domain=.test.com; path=/; expires=Fri, 
12 Mar 2117 02:53:03 GMT; HttpOnly",
+ "good=not_expired", "/hello", "cookie.test.com"},
+
+/* Test a good and expired cookie in the neulion format.
+ * Should be acceptable */
+{"expired=\"really_old\"; Domain=.test.com; Expires=Thu, 01-Jan-1970 
00:00:10 GMT; Path=/\nneulion=not_expired; domain=.test.com; path=/; 
expires=Fri, 12-Mar-2117 02:53:03 GMT; HttpOnly",
+ "neulion=not_expired", "/hello", "cookie.test.com"},
+
+/* Test an expiry date without the day of week specified */
+{"no_day=still_ok; domain=.test.com; path=/; expires=12-Mar-2117 02:53:03 
GMT; HttpOnly",
+ "no_day=still_ok", "/hello", "cookie.test.com"},
+
+/* Test a date that cannot be parsed. Allow the cookie */
+{"unparsable_date=allow_cookie; domain=.test.com; path=/; 
expires=12-Mur-2117 02:53:03 GMT; HttpOnly",
+ "unparsable_date=allow_cookie", "/hello", "cookie.test.com"},
+
+/* Test a cookie that has a different domain. Do not use the cookie */
+{"different_domain=exclude; domain=.nottest.com; path=/; 
expires=12-Mar-2117 02:53:03 GMT; HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces */
+
{"no_spaces=no_big_deal;domain=.test.com;path=/;expires=Fri,12Mar211702:53:03GMT;HttpOnly",
+ "no_spaces=no_big_deal", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie that has no spaces and is expired. Excluded */
+
{"no_spaces_expired=not_ok;domain=.test.com;path=/;expires=Thu01Jan197010GMT;HttpOnly",
+ NULL, "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that is too long. */
+{"long=handled;domain=.test.com;path=/;expires=Fri, 12 Mar 2117 
02:53:03GMTGMTGMTGMTGMTGMT;HttpOnly",
+ "long=handled", "/hello", "cookie.test.com"},
+
+/* Test a set-cookie with a date that starts with too many characters */
+{"bad_start=ok;domain=

[FFmpeg-devel] [PATCH v2 0/2] Ignore expired cookies

2017-03-30 Thread Micah Galizia

Hello Again,

This is another attempt to get the http protocol not to send expired cookies 
_and_ prevent it from updating good cookie values with expired cookie values 
sent by misbehaving servers.

Previously its been recommended that we break each set-cookie into a dict to 
parse it properly; this version takes that approach and does refactor some of 
the older set-cookie parsing code. This time, I've also added unit tests in a 
second patch for the http protocol code I'm changing.

Thanks in advance for the review.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-30 Thread Micah Galizia
Thanks for those comments -- I'll get rid of the strlen in the
upcoming patch but, Nicolas, you lost me there.

Anyway, this patch only does half the job -- I have a new one that is
unfortunately larger, but has taken prior advice to break cookies into
dicts.

On Thu, Mar 30, 2017 at 4:12 PM, Nicolas George  wrote:
> Le decadi 10 germinal, an CCXXV, Alexander Strasser a écrit :
>> If expiry is zero terminated and you are going through it one byte at a time,
>> you could omit the strlen call and just check if expiry[i] is non zero.
>>
>> It's maybe the more common idiom too.
>
> On the other hand, code that does not need a 0-terminated string is more
> generic.
>
> I am thinking of the ideas I posted a few months ago about reworking the
> options system to avoid escaping hell. Parsers for various types must be
> able to work in the middle of strings with foreign delimiters. Code that
> is already capable of working in the middle of a string would be easier
> to integrate.
>
> Of course, all this is in the far future. I will not insist on all new
> code to be able to work like that, but I would like it nonetheless. And
> if it is already written that way, let us keep it.
>
> All in all, 0-terminated strings were a terrible terrible idea.
>
> Regards,
>
> --
>   Nicolas George
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>



-- 
"The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one."   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-29 Thread Micah Galizia
Hi,

I'm going to have to submit a v2 for this patch (hopefully soon) --
this version only accomplishes half the job: not sending expired
cookies. The change should also prevent storing them in the first
place.

Regardless, thanks for your help on this one.

On Sat, Mar 25, 2017 at 7:27 PM, Micah Galizia <micahgali...@gmail.com> wrote:
> Signed-off-by: Micah Galizia <micahgali...@gmail.com>
> ---
>  libavformat/http.c | 43 +++
>  1 file changed, 39 insertions(+), 4 deletions(-)
>
> diff --git a/libavformat/http.c b/libavformat/http.c
> index 293a8a7..53fae2a 100644
> --- a/libavformat/http.c
> +++ b/libavformat/http.c
> @@ -29,6 +29,7 @@
>  #include "libavutil/avstring.h"
>  #include "libavutil/opt.h"
>  #include "libavutil/time.h"
> +#include "libavutil/parseutils.h"
>
>  #include "avformat.h"
>  #include "http.h"
> @@ -48,6 +49,8 @@
>  #define MAX_REDIRECTS 8
>  #define HTTP_SINGLE   1
>  #define HTTP_MUTLI2
> +#define MAX_EXPIRY19
> +#define WHITESPACES " \n\t\r"
>  typedef enum {
>  LOWER_PROTO,
>  READ_HEADERS,
> @@ -877,15 +880,20 @@ static int get_cookies(HTTPContext *s, char **cookies, 
> const char *path,
>
>  *cookies = NULL;
>  while ((cookie = av_strtok(set_cookies, "\n", ))) {
> -int domain_offset = 0;
> +int domain_offset = 0, expired = 0;
>  char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = 
> NULL;
> +char exp_buf[MAX_EXPIRY];
>  set_cookies = NULL;
>
>  // store the cookie in a dict in case it is updated in the response
>  if (parse_cookie(s, cookie, >cookie_dict))
>  av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
>
> -while ((param = av_strtok(cookie, "; ", _param))) {
> +while ((param = av_strtok(cookie, ";", _param))) {
> +
> +// move past any leading whitespace
> +param += strspn(param, WHITESPACES);
> +
>  if (cookie) {
>  // first key-value pair is the actual cookie value
>  cvalue = av_strdup(param);
> @@ -899,6 +907,33 @@ static int get_cookies(HTTPContext *s, char **cookies, 
> const char *path,
>  int leading_dot = (param[7] == '.');
>  av_free(cdomain);
>  cdomain = av_strdup([7+leading_dot]);
> +} else if (!av_strncasecmp("expires=", param, 8)) {
> +int i, j, exp_len, exp_buf_len = MAX_EXPIRY-1;
> +struct tm tm_buf = {0};
> +char *expiry = [8];
> +
> +// strip off any punctuation or whitespace
> +exp_len = strlen(expiry);
> +for (i = 0, j = 0; i < exp_len && j < exp_buf_len; i++) {
> +if ((expiry[i] >= '0' && expiry[i] <= '9') ||
> +(expiry[i] >= 'A' && expiry[i] <= 'Z') ||
> +(expiry[i] >= 'a' && expiry[i] <= 'z')) {
> +exp_buf[j] = expiry[i];
> +j++;
> +}
> +}
> +exp_buf[j] = '\0';
> +expiry = exp_buf;
> +
> +// move the string beyond the day of week
> +while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
> +expiry++;
> +
> +if (av_small_strptime(expiry, "%d%b%Y%H%M%S", _buf)) {
> +time_t now = av_gettime() / 100;
> +if (av_timegm(_buf) < now)
> +expired = 1;
> +}
>  } else {
>  // ignore unknown attributes
>  }
> @@ -907,9 +942,9 @@ static int get_cookies(HTTPContext *s, char **cookies, 
> const char *path,
>  cdomain = av_strdup(domain);
>
>  // ensure all of the necessary values are valid
> -if (!cdomain || !cpath || !cvalue) {
> +if (expired || !cdomain || !cpath || !cvalue ) {
>  av_log(s, AV_LOG_WARNING,
> -   "Invalid cookie found, no value, path or domain 
> specified\n");
> +   "Invalid cookie found, expired or no value, path or 
> domain specified\n");
>  goto done_cookie;
>  }
>
> --
> 2.9.3
>



-- 
"The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one."   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-25 Thread Micah Galizia
On Sat, Mar 25, 2017 at 10:51 AM, wm4  wrote:



> This can overflow sizeof(exp_buf).

Sorry, new patch cleans that up.

>> +
>> +// move the string beyond the day of week
>> +i = 0;
>> +while ((exp_buf[i] < '0' || exp_buf[i] > '9') && (i < j))
>> +i++;
>> +
>> +if (av_small_strptime(_buf[i], "%d%b%Y%H%M%SGMT", 
>> _buf)) {
>> +time_t now = av_gettime() / 100;
>
> I don't know if av_gettime() has the same time base...

I had to double-check but I think it's correct as it is. The av_gettime() is 
based on the time since the epoch, which is already in GMT/UTC. The cookies 
timestamp is also expressed in GMT/UTC per the HTTP spec (and per av_timegm), 
so I believe these are comparable.

If you were not talking about the timezones when you said "same base", I'm not 
entirely sure what you're getting at. I tested on my system and 
av_gettime()/100 returns the same value as time(NULL).

Thanks again.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-25 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 43 +++
 1 file changed, 39 insertions(+), 4 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7..53fae2a 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY19
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -877,15 +880,20 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 
 *cookies = NULL;
 while ((cookie = av_strtok(set_cookies, "\n", ))) {
-int domain_offset = 0;
+int domain_offset = 0, expired = 0;
 char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = 
NULL;
+char exp_buf[MAX_EXPIRY];
 set_cookies = NULL;
 
 // store the cookie in a dict in case it is updated in the response
 if (parse_cookie(s, cookie, >cookie_dict))
 av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
 
-while ((param = av_strtok(cookie, "; ", _param))) {
+while ((param = av_strtok(cookie, ";", _param))) {
+
+// move past any leading whitespace
+param += strspn(param, WHITESPACES);
+
 if (cookie) {
 // first key-value pair is the actual cookie value
 cvalue = av_strdup(param);
@@ -899,6 +907,33 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 int leading_dot = (param[7] == '.');
 av_free(cdomain);
 cdomain = av_strdup([7+leading_dot]);
+} else if (!av_strncasecmp("expires=", param, 8)) {
+int i, j, exp_len, exp_buf_len = MAX_EXPIRY-1;
+struct tm tm_buf = {0};
+char *expiry = [8];
+
+// strip off any punctuation or whitespace
+exp_len = strlen(expiry);
+for (i = 0, j = 0; i < exp_len && j < exp_buf_len; i++) {
+if ((expiry[i] >= '0' && expiry[i] <= '9') ||
+(expiry[i] >= 'A' && expiry[i] <= 'Z') ||
+(expiry[i] >= 'a' && expiry[i] <= 'z')) {
+exp_buf[j] = expiry[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+expiry = exp_buf;
+
+// move the string beyond the day of week
+while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
+expiry++;
+
+if (av_small_strptime(expiry, "%d%b%Y%H%M%S", _buf)) {
+time_t now = av_gettime() / 100;
+if (av_timegm(_buf) < now)
+expired = 1;
+}
 } else {
 // ignore unknown attributes
 }
@@ -907,9 +942,9 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 cdomain = av_strdup(domain);
 
 // ensure all of the necessary values are valid
-if (!cdomain || !cpath || !cvalue) {
+if (expired || !cdomain || !cpath || !cvalue ) {
 av_log(s, AV_LOG_WARNING,
-   "Invalid cookie found, no value, path or domain 
specified\n");
+   "Invalid cookie found, expired or no value, path or domain 
specified\n");
 goto done_cookie;
 }
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-25 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 43 +++
 1 file changed, 39 insertions(+), 4 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7..f7d1925 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,8 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define MAX_EXPIRY30
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -877,15 +880,20 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 
 *cookies = NULL;
 while ((cookie = av_strtok(set_cookies, "\n", ))) {
-int domain_offset = 0;
+int domain_offset = 0, expired = 0;
 char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = 
NULL;
+char exp_buf[MAX_EXPIRY];
 set_cookies = NULL;
 
 // store the cookie in a dict in case it is updated in the response
 if (parse_cookie(s, cookie, >cookie_dict))
 av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
 
-while ((param = av_strtok(cookie, "; ", _param))) {
+while ((param = av_strtok(cookie, ";", _param))) {
+
+// move past any leading whitespace
+param += strspn(param, WHITESPACES);
+
 if (cookie) {
 // first key-value pair is the actual cookie value
 cvalue = av_strdup(param);
@@ -899,6 +907,33 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 int leading_dot = (param[7] == '.');
 av_free(cdomain);
 cdomain = av_strdup([7+leading_dot]);
+} else if (!av_strncasecmp("expires=", param, 8)) {
+int i, j, exp_len;
+struct tm tm_buf = {0};
+char *expiry = [8];
+
+// strip off any punctuation or whitespace
+exp_len = strlen(expiry);
+for (i = 0, j = 0; i < exp_len; i++) {
+if ((expiry[i] >= '0' && expiry[i] <= '9') ||
+(expiry[i] >= 'A' && expiry[i] <= 'Z') ||
+(expiry[i] >= 'a' && expiry[i] <= 'z')) {
+exp_buf[j] = expiry[i];
+j++;
+}
+}
+exp_buf[j] = '\0';
+
+// move the string beyond the day of week
+i = 0;
+while ((exp_buf[i] < '0' || exp_buf[i] > '9') && (i < j))
+i++;
+
+if (av_small_strptime(_buf[i], "%d%b%Y%H%M%SGMT", 
_buf)) {
+time_t now = av_gettime() / 100;
+if (av_timegm(_buf) < now)
+expired = 1;
+}
 } else {
 // ignore unknown attributes
 }
@@ -907,9 +942,9 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 cdomain = av_strdup(domain);
 
 // ensure all of the necessary values are valid
-if (!cdomain || !cpath || !cvalue) {
+if (expired || !cdomain || !cpath || !cvalue ) {
 av_log(s, AV_LOG_WARNING,
-   "Invalid cookie found, no value, path or domain 
specified\n");
+   "Invalid cookie found, expired or no value, path or domain 
specified\n");
 goto done_cookie;
 }
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-25 Thread Micah Galizia
On 2017-03-25 07:11 AM, wm4 wrote:



>> -while ((param = av_strtok(cookie, "; ", _param))) {
>> +while ((param = av_strtok(cookie, ";", _param))) {
>> +
>> +// move past any leading whitespace
>> +param += strspn(param, WHITESPACES);
>> +
> Not quite sure why this change is even needed, but seems ok.

Its just a little more flexible than expecting a single space and only a space 
between each delimited field of a cookie.

>>   if (cookie) {
>>   // first key-value pair is the actual cookie value
>>   cvalue = av_strdup(param);
>> @@ -899,6 +905,33 @@ static int get_cookies(HTTPContext *s, char **cookies, 
>> const char *path,
>>   int leading_dot = (param[7] == '.');
>>   av_free(cdomain);
>>   cdomain = av_strdup([7+leading_dot]);
>> +} else if (!av_strncasecmp("expires=", param, 8)) {
>> +int i = 0, j = 0;
>> +struct tm tm_buf = {0};
>> +char *expiry = av_strdup([8]);
> Unchecked memory allocation that could fail.

Thanks, resolved using the on-stack buffer described below.

>> +
>> +// strip off any punctuation or whitespace
>> +for (; i < strlen(expiry); i++) {
> A bit ugly stylistically: the i=0 initialization should be in here, and
> the strlen should be cached in a variable, instead of recomputing it on
> every loop.

Fixed.

>> +if ((expiry[i] >= '0' && expiry[i] <= '9') ||
>> +(expiry[i] >= 'A' && expiry[i] <= 'Z') ||
>> +(expiry[i] >= 'a' && expiry[i] <= 'z')) {
>> +expiry[j] = expiry[i];
>> +j++;
>> +}
>> +}
>> +expiry[j] = '\0';
> (To be honest I don't understand why the string is even strduped - you
> could just make it with a fixed-sized on-stack buffer. Just discard the
> remainder of the string if the buffer is unexpectedly too small - time
> strings probably have an upper size bound anyway.)

Changed.

>> +
>> +// move the string beyond the day of week
>> +i = 0;
>> +while ((expiry[i] < '0' || expiry[i] > '9') && (i < j))
>> +i++;
>> +
>> +if (av_small_strptime([i], "%d%b%Y%H%M%SGMT", 
>> _buf)) {
>> +if (av_timegm(_buf) < time(NULL))
>> +expired = 1;
> A bit unsure about this time() call. Also nervous about having this in
> library code.

I borrowed some code from parseutils to resolve this.

Thanks for the prompt review.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-24 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 41 +
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7..37bdacf 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,7 @@
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI2
+#define WHITESPACES " \n\t\r"
 typedef enum {
 LOWER_PROTO,
 READ_HEADERS,
@@ -877,7 +879,7 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 
 *cookies = NULL;
 while ((cookie = av_strtok(set_cookies, "\n", ))) {
-int domain_offset = 0;
+int domain_offset = 0, expired = 0;
 char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = 
NULL;
 set_cookies = NULL;
 
@@ -885,7 +887,11 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 if (parse_cookie(s, cookie, >cookie_dict))
 av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
 
-while ((param = av_strtok(cookie, "; ", _param))) {
+while ((param = av_strtok(cookie, ";", _param))) {
+
+// move past any leading whitespace
+param += strspn(param, WHITESPACES);
+
 if (cookie) {
 // first key-value pair is the actual cookie value
 cvalue = av_strdup(param);
@@ -899,6 +905,33 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 int leading_dot = (param[7] == '.');
 av_free(cdomain);
 cdomain = av_strdup([7+leading_dot]);
+} else if (!av_strncasecmp("expires=", param, 8)) {
+int i = 0, j = 0;
+struct tm tm_buf = {0};
+char *expiry = av_strdup([8]);
+
+// strip off any punctuation or whitespace
+for (; i < strlen(expiry); i++) {
+if ((expiry[i] >= '0' && expiry[i] <= '9') ||
+(expiry[i] >= 'A' && expiry[i] <= 'Z') ||
+(expiry[i] >= 'a' && expiry[i] <= 'z')) {
+expiry[j] = expiry[i];
+j++;
+}
+}
+expiry[j] = '\0';
+
+// move the string beyond the day of week
+i = 0;
+while ((expiry[i] < '0' || expiry[i] > '9') && (i < j))
+i++;
+
+if (av_small_strptime([i], "%d%b%Y%H%M%SGMT", _buf)) 
{
+if (av_timegm(_buf) < time(NULL))
+expired = 1;
+}
+
+av_free(expiry);
 } else {
 // ignore unknown attributes
 }
@@ -907,9 +940,9 @@ static int get_cookies(HTTPContext *s, char **cookies, 
const char *path,
 cdomain = av_strdup(domain);
 
 // ensure all of the necessary values are valid
-if (!cdomain || !cpath || !cvalue) {
+if (expired || !cdomain || !cpath || !cvalue ) {
 av_log(s, AV_LOG_WARNING,
-   "Invalid cookie found, no value, path or domain 
specified\n");
+   "Invalid cookie found, expired or no value, path or domain 
specified\n");
 goto done_cookie;
 }
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-03-24 Thread Micah Galizia
Hi,

This is my second attempt at fixing how we are handling expired cookies. As a 
reminder, on some authenticated Neulion streams, they send a cookie from the 
past, like so:

Set-Cookie: nlqptid=""; Domain=.neulion.com; Expires=Thu, 01-Jan-1970 00:00:10 
GMT; Path=/

These expired cookies are ignored by other systems (eg: android).

Please let me know if you want changes.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-26 Thread Micah Galizia
On Sun, Feb 26, 2017 at 11:12 AM, Michael Niedermayer
<mich...@niedermayer.cc> wrote:
> On Thu, Feb 23, 2017 at 09:34:28PM -0500, Micah Galizia wrote:
>> Hello,
>>
>> Is someone able to take a look at this and accept or reject it -- its
>> been a few days since I submitted.
>
> applied
>
> thx

Awesome -- thank you. On to the next one :)
-- 
"The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one."   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-23 Thread Micah Galizia
Hello,

Is someone able to take a look at this and accept or reject it -- its
been a few days since I submitted.

Sorry to pester -- thanks in advance.

On Mon, Feb 20, 2017 at 7:48 PM, Micah Galizia <micahgali...@gmail.com> wrote:
> Signed-off-by: Micah Galizia <micahgali...@gmail.com>
> ---
>  libavutil/parseutils.c   | 28 
>  libavutil/tests/parseutils.c |  7 +++
>  tests/ref/fate/parseutils|  7 +++
>  3 files changed, 42 insertions(+)
>
> diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
> index 86d3dac..7ca07b3 100644
> --- a/libavutil/parseutils.c
> +++ b/libavutil/parseutils.c
> @@ -140,6 +140,11 @@ static const VideoRateAbbr video_rate_abbrs[]= {
>  { "ntsc-film", { 24000, 1001 } },
>  };
>
> +static const char *months[12] = {
> +"january", "february", "march", "april", "may", "june", "july", "august",
> +"september", "october", "november", "december"
> +};
> +
>  int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
>  {
>  int i;
> @@ -466,6 +471,21 @@ static int date_get_num(const char **pp,
>  return val;
>  }
>
> +static int date_get_month(const char **pp) {
> +int i = 0;
> +for (; i < 12; i++) {
> +if (!av_strncasecmp(*pp, months[i], 3)) {
> +const char *mo_full = months[i] + 3;
> +int len = strlen(mo_full);
> +*pp += 3;
> +if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
> +*pp += len;
> +return i;
> +}
> +}
> +return -1;
> +}
> +
>  char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
>  {
>  int c, val;
> @@ -525,6 +545,14 @@ char *av_small_strptime(const char *p, const char *fmt, 
> struct tm *dt)
>  if (!p)
>  return NULL;
>  break;
> +case 'b':
> +case 'B':
> +case 'h':
> +val = date_get_month();
> +if (val == -1)
> +return NULL;
> +dt->tm_mon = val;
> +break;
>  case '%':
>  if (*p++ != '%')
>  return NULL;
> diff --git a/libavutil/tests/parseutils.c b/libavutil/tests/parseutils.c
> index 682b390..180f624 100644
> --- a/libavutil/tests/parseutils.c
> +++ b/libavutil/tests/parseutils.c
> @@ -138,6 +138,13 @@ static void test_av_small_strptime(void)
>  { "%Y - %m - %d","2012-12-21" },
>  { "%Y-%m-%d %H:%M:%S",   "2012-12-21 20:12:21" },
>  { "  %Y - %m - %d %H : %M : %S", "   2012 - 12 -  21   20 : 12 : 21" 
> },
> +{ "  %Y - %b - %d %H : %M : %S", "   2012 - nOV -  21   20 : 12 : 
> 21" },
> +{ "  %Y - %B - %d %H : %M : %S", "   2012 - nOVemBeR -  21   20 : 12 
> : 21" },
> +{ "  %Y - %B%d %H : %M : %S", "   2012 - may21   20 : 12 : 21" },
> +{ "  %Y - %B%d %H : %M : %S", "   2012 - mby21   20 : 12 : 21" },
> +{ "  %Y - %B - %d %H : %M : %S", "   2012 - JunE -  21   20 : 12 : 
> 21" },
> +{ "  %Y - %B - %d %H : %M : %S", "   2012 - Jane -  21   20 : 12 : 
> 21" },
> +{ "  %Y - %B - %d %H : %M : %S", "   2012 - January -  21   20 : 12 
> : 21" },
>  };
>
>  av_log_set_level(AV_LOG_DEBUG);
> diff --git a/tests/ref/fate/parseutils b/tests/ref/fate/parseutils
> index 1aad5ec..568b6d2 100644
> --- a/tests/ref/fate/parseutils
> +++ b/tests/ref/fate/parseutils
> @@ -68,6 +68,13 @@ fmt:'%Y-%m-%d' spec:'2012-12-21' -> 2012-12-21 00:00:00
>  fmt:'%Y - %m - %d' spec:'2012-12-21' -> 2012-12-21 00:00:00
>  fmt:'%Y-%m-%d %H:%M:%S' spec:'2012-12-21 20:12:21' -> 2012-12-21 20:12:21
>  fmt:'  %Y - %m - %d %H : %M : %S' spec:'   2012 - 12 -  21   20 : 12 : 21' 
> -> 2012-12-21 20:12:21
> +fmt:'  %Y - %b - %d %H : %M : %S' spec:'   2012 - nOV -  21   20 : 12 : 21' 
> -> 2012-11-21 20:12:21
> +fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - nOVemBeR -  21   20 : 12 : 
> 21' -> 2012-11-21 20:12:21
> +fmt:'  %Y - %B%d %H : %M : %S' spec:'   2012 - may21   20 : 12 : 21' -> 
> 2012-05-21 20:12:21
> +fmt:'  %Y - %B%d %H : %M : %S' spec:'   2012 - mby21   20 : 12 : 21' -> error
> +fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - JunE -  21   20 : 12 : 21' 
> -> 2012-06-21 20:12:21
> +fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - Jane -  21   20 : 12 : 21' 
> -> error
> +fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - January -  21   20 : 12 : 
> 21' -> 2012-01-21 20:12:21
>
>  Testing av_parse_time()
>  (now is 2012-03-17 09:14:13.2 +0100, local time is UTC+1)
> --
> 2.9.3
>



-- 
"The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one."   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-20 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavutil/parseutils.c   | 28 
 libavutil/tests/parseutils.c |  7 +++
 tests/ref/fate/parseutils|  7 +++
 3 files changed, 42 insertions(+)

diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index 86d3dac..7ca07b3 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -140,6 +140,11 @@ static const VideoRateAbbr video_rate_abbrs[]= {
 { "ntsc-film", { 24000, 1001 } },
 };
 
+static const char *months[12] = {
+"january", "february", "march", "april", "may", "june", "july", "august",
+"september", "october", "november", "december"
+};
+
 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
 {
 int i;
@@ -466,6 +471,21 @@ static int date_get_num(const char **pp,
 return val;
 }
 
+static int date_get_month(const char **pp) {
+int i = 0;
+for (; i < 12; i++) {
+if (!av_strncasecmp(*pp, months[i], 3)) {
+const char *mo_full = months[i] + 3;
+int len = strlen(mo_full);
+*pp += 3;
+if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
+*pp += len;
+return i;
+}
+}
+return -1;
+}
+
 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
 {
 int c, val;
@@ -525,6 +545,14 @@ char *av_small_strptime(const char *p, const char *fmt, 
struct tm *dt)
 if (!p)
 return NULL;
 break;
+case 'b':
+case 'B':
+case 'h':
+val = date_get_month();
+if (val == -1)
+return NULL;
+dt->tm_mon = val;
+break;
 case '%':
 if (*p++ != '%')
 return NULL;
diff --git a/libavutil/tests/parseutils.c b/libavutil/tests/parseutils.c
index 682b390..180f624 100644
--- a/libavutil/tests/parseutils.c
+++ b/libavutil/tests/parseutils.c
@@ -138,6 +138,13 @@ static void test_av_small_strptime(void)
 { "%Y - %m - %d","2012-12-21" },
 { "%Y-%m-%d %H:%M:%S",   "2012-12-21 20:12:21" },
 { "  %Y - %m - %d %H : %M : %S", "   2012 - 12 -  21   20 : 12 : 21" },
+{ "  %Y - %b - %d %H : %M : %S", "   2012 - nOV -  21   20 : 12 : 21" 
},
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - nOVemBeR -  21   20 : 12 : 
21" },
+{ "  %Y - %B%d %H : %M : %S", "   2012 - may21   20 : 12 : 21" },
+{ "  %Y - %B%d %H : %M : %S", "   2012 - mby21   20 : 12 : 21" },
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - JunE -  21   20 : 12 : 21" 
},
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - Jane -  21   20 : 12 : 21" 
},
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - January -  21   20 : 12 : 
21" },
 };
 
 av_log_set_level(AV_LOG_DEBUG);
diff --git a/tests/ref/fate/parseutils b/tests/ref/fate/parseutils
index 1aad5ec..568b6d2 100644
--- a/tests/ref/fate/parseutils
+++ b/tests/ref/fate/parseutils
@@ -68,6 +68,13 @@ fmt:'%Y-%m-%d' spec:'2012-12-21' -> 2012-12-21 00:00:00
 fmt:'%Y - %m - %d' spec:'2012-12-21' -> 2012-12-21 00:00:00
 fmt:'%Y-%m-%d %H:%M:%S' spec:'2012-12-21 20:12:21' -> 2012-12-21 20:12:21
 fmt:'  %Y - %m - %d %H : %M : %S' spec:'   2012 - 12 -  21   20 : 12 : 21' -> 
2012-12-21 20:12:21
+fmt:'  %Y - %b - %d %H : %M : %S' spec:'   2012 - nOV -  21   20 : 12 : 21' -> 
2012-11-21 20:12:21
+fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - nOVemBeR -  21   20 : 12 : 
21' -> 2012-11-21 20:12:21
+fmt:'  %Y - %B%d %H : %M : %S' spec:'   2012 - may21   20 : 12 : 21' -> 
2012-05-21 20:12:21
+fmt:'  %Y - %B%d %H : %M : %S' spec:'   2012 - mby21   20 : 12 : 21' -> error
+fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - JunE -  21   20 : 12 : 21' 
-> 2012-06-21 20:12:21
+fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - Jane -  21   20 : 12 : 21' 
-> error
+fmt:'  %Y - %B - %d %H : %M : %S' spec:'   2012 - January -  21   20 : 12 : 
21' -> 2012-01-21 20:12:21
 
 Testing av_parse_time()
 (now is 2012-03-17 09:14:13.2 +0100, local time is UTC+1)
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-20 Thread Micah Galizia
Sorry about that -- this actually makes sense now -- I thought it was a bit odd 
that the test program had no asserts or anything to validate the output...

I've addressed the fate issues in this patch -- thanks again for the review.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-20 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavutil/parseutils.c   | 28 
 libavutil/tests/parseutils.c |  7 +++
 2 files changed, 35 insertions(+)

diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index 86d3dac..7ca07b3 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -140,6 +140,11 @@ static const VideoRateAbbr video_rate_abbrs[]= {
 { "ntsc-film", { 24000, 1001 } },
 };
 
+static const char *months[12] = {
+"january", "february", "march", "april", "may", "june", "july", "august",
+"september", "october", "november", "december"
+};
+
 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
 {
 int i;
@@ -466,6 +471,21 @@ static int date_get_num(const char **pp,
 return val;
 }
 
+static int date_get_month(const char **pp) {
+int i = 0;
+for (; i < 12; i++) {
+if (!av_strncasecmp(*pp, months[i], 3)) {
+const char *mo_full = months[i] + 3;
+int len = strlen(mo_full);
+*pp += 3;
+if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
+*pp += len;
+return i;
+}
+}
+return -1;
+}
+
 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
 {
 int c, val;
@@ -525,6 +545,14 @@ char *av_small_strptime(const char *p, const char *fmt, 
struct tm *dt)
 if (!p)
 return NULL;
 break;
+case 'b':
+case 'B':
+case 'h':
+val = date_get_month();
+if (val == -1)
+return NULL;
+dt->tm_mon = val;
+break;
 case '%':
 if (*p++ != '%')
 return NULL;
diff --git a/libavutil/tests/parseutils.c b/libavutil/tests/parseutils.c
index 682b390..180f624 100644
--- a/libavutil/tests/parseutils.c
+++ b/libavutil/tests/parseutils.c
@@ -138,6 +138,13 @@ static void test_av_small_strptime(void)
 { "%Y - %m - %d","2012-12-21" },
 { "%Y-%m-%d %H:%M:%S",   "2012-12-21 20:12:21" },
 { "  %Y - %m - %d %H : %M : %S", "   2012 - 12 -  21   20 : 12 : 21" },
+{ "  %Y - %b - %d %H : %M : %S", "   2012 - nOV -  21   20 : 12 : 21" 
},
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - nOVemBeR -  21   20 : 12 : 
21" },
+{ "  %Y - %B%d %H : %M : %S", "   2012 - may21   20 : 12 : 21" },
+{ "  %Y - %B%d %H : %M : %S", "   2012 - mby21   20 : 12 : 21" },
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - JunE -  21   20 : 12 : 21" 
},
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - Jane -  21   20 : 12 : 21" 
},
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - January -  21   20 : 12 : 
21" },
 };
 
 av_log_set_level(AV_LOG_DEBUG);
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-19 Thread Micah Galizia
---
 libavutil/parseutils.c   | 31 +++
 libavutil/tests/parseutils.c |  5 +
 2 files changed, 36 insertions(+)

diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index 86d3dac..a273216 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -140,6 +140,12 @@ static const VideoRateAbbr video_rate_abbrs[]= {
 { "ntsc-film", { 24000, 1001 } },
 };
 
+static const char *mo_abr[] = { "jan", "feb", "mar", "apr", "may", "jun",
+   "jul", "aug", "sep", "oct", "nov", "dec" };
+
+static const char *mo_full[] = { "uary", "ruary", "ch", "il", NULL, "e", "y",
+"ust", "tember", "ober", "ember", "ember" };
+
 int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
 {
 int i;
@@ -466,6 +472,23 @@ static int date_get_num(const char **pp,
 return val;
 }
 
+static int date_get_month(const char **pp) {
+for (int i = 0; i < 12; i++) {
+if (!av_strncasecmp(*pp, mo_abr[i], 3)) {
+*pp += 3;
+if (mo_full[i] != NULL) {
+int len = strlen(mo_full[i]);
+if (!av_strncasecmp(*pp, mo_full[i], len)) {
+*pp += len;
+return i;
+}
+}
+return i;
+}
+}
+return -1;
+}
+
 char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
 {
 int c, val;
@@ -525,6 +548,14 @@ char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
 if (!p)
 return NULL;
 break;
+case 'b':
+case 'B':
+case 'h':
+val = date_get_month();
+if (val == -1)
+return NULL;
+dt->tm_mon = val;
+break;
 case '%':
 if (*p++ != '%')
 return NULL;
diff --git a/libavutil/tests/parseutils.c b/libavutil/tests/parseutils.c
index 682b390..e9b9599 100644
--- a/libavutil/tests/parseutils.c
+++ b/libavutil/tests/parseutils.c
@@ -138,6 +138,11 @@ static void test_av_small_strptime(void)
 { "%Y - %m - %d","2012-12-21" },
 { "%Y-%m-%d %H:%M:%S",   "2012-12-21 20:12:21" },
 { "  %Y - %m - %d %H : %M : %S", "   2012 - 12 -  21   20 : 12 : 21" },
+{ "  %Y - %b - %d %H : %M : %S", "   2012 - nOV -  21   20 : 12 : 21" },
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - nOVemBeR -  21   20 : 12 : 21" },
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - may -  21   20 : 12 : 21" },
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - JunE -  21   20 : 12 : 21" },
+{ "  %Y - %B - %d %H : %M : %S", "   2012 - January -  21   20 : 12 : 21" },
 };
 
 av_log_set_level(AV_LOG_DEBUG);
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] add locale month names to av_small_strptime

2017-02-19 Thread Micah Galizia
Hello,

In preparation for evaluating cookie expiry values, av_small_strptime needs to 
handle the month names. This patch adds said names (full and abbreviated).

Thanks in advance,

Micah
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Ignore expired cookies

2017-02-12 Thread Micah Galizia
On Sun, Feb 12, 2017 at 6:28 AM, Nicolas George <geo...@nsup.org> wrote:
> Thanks for the patch. See remarks below.
>
> Le tridi 23 pluviôse, an CCXXV, Micah Galizia a écrit :
>> On some authenticated Neulion streams, they send a cookie from the past,
>> like so:
>>
>> Set-Cookie: nlqptid=""; Domain=.neulion.com; Expires=Thu, 01-Jan-1970
>> 00:00:10 GMT; Path=/
>>
>> As a result, the good cookie value is overwritten and authentication breaks
>> immediately. I realise disqualifying a cookie over the date might open a
>> can of worms when it comes to date formatting used by different systems,
>
> In principle, I would be in favour of correctly heeding all elements of
> the protocol, and only on top of that provide users the option of
> ignoring certain elements. Parsing the expires field certainly enters
> this frame.
>
>> but I added Neulions wrong format and the http standard format.
>
> In that case, maybe ignoring the whole cookie because the date is
> invalid would be a better idea.

Maybe a more permissive approach would be better. Iff we _can_ parse
the date format _AND_ it's expired then and only then ignore that
cookie. This would maintain compatibility with how it works now, but
correct the specific bug I'm observing.

> Did you test to see how real browsers handle it?

Browsers, no, but the Android video player, yes. They ignore the new
cookie value if it shows up with an expiry in the past (well, at least
an expiry date in 1970) and use the value it had already. Here is a
charles dump if you want to see:
https://dl.dropboxusercontent.com/u/83154919/snnow_full2.chls

>> Please let me know if this is acceptable. I've run it against fate and
>> there were no problems.
>
> That is good practice. Unfortunately, FATE tests almost nothing about
> network protocols. If you did not, you need to check with a few web
> servers that currently work.

I tested it against the neulion stream I have access to. I don't have
a whole lot else but hopefully if I minimize the situations in which
cookies are ignored it wont matter. I'll also try to find a few other
stream sources.

> Now reviewing details of the latest version of the patch:
>
>> diff --git a/libavformat/http.c b/libavformat/http.c
>> index 944a6cf..24368aa 100644
>> --- a/libavformat/http.c
>> +++ b/libavformat/http.c
>> @@ -682,12 +682,46 @@ static int parse_icy(HTTPContext *s, const char *tag, 
>> const char *p)
>>
>>  static int parse_cookie(HTTPContext *s, const char *p, AVDictionary 
>> **cookies)
>>  {
>> -char *eql, *name;
>> +char *eql, *name, *expiry;
>>
>>  // duplicate the cookie name (dict will dupe the value)
>>  if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
>>  if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
>>
>> +// ensure the expiry is sane
>
>> +if ((expiry = strstr(eql, "Expires="))) {
>
> I believe this is not correct. First, AFAIK, all the structure elements
> in HTTP are case insensitive. Second, the string "Expires=" could
> legitimately be part of the cookie value itself.
>
> I suggest to parse the subfields of the set-cookie field correctly: it
> is a sequence of "key=value" pairs (with the "=value" part optional, but
> can be quoted) separated by semicolons and optional spaces. Furthermore,
> it would be useful for other fields too, such as content-type.
>
> I realize it is a little bit more work, but I think it is reasonable.

I think this was proposed last time I was adding cookies into the HLS
demuxer (years ago) but the problem is that you can't really pass
around complex data structures between demuxers (http, hls, etc).
AVOption was also quite restrictive last time I looked into doing
something more advanced like that.

One of the things Michael N. suggested back then was using a proper
cookie jar -- is there any reason I can't keep parsed cookies in an
in-memory global static variable scoped in http.c? Then we wouldn't
even need to pass the cookies as options around between demuxers
anymore since they'd have a perminant home in http.c, which should be
the only place they're used.

>> +struct tm tm_buf = {0};
>> +char *end;
>> +
>> +// get the start & the end of the expiry ('11 Feb 2017 09:41:35 
>> GMT')
>> +// this skips past the day of the week by finding the space 
>> following it
>
>> +expiry += 8 * sizeof(char);
>
> sizeof(char) = 1 by definition, thus writing it is always unnecessary,
> and rarely useful for readability.
>
>> +while (*expiry != ' ') expiry++;
>
> I suspect tabs and other 

[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-02-11 Thread Micah Galizia
---
 libavformat/http.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 944a6cf..24368aa 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -682,12 +682,46 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
-char *eql, *name;
+char *eql, *name, *expiry;
 
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
 
+// ensure the expiry is sane
+if ((expiry = strstr(eql, "Expires="))) {
+struct tm tm_buf = {0};
+char *end;
+
+// get the start & the end of the expiry ('11 Feb 2017 09:41:35 GMT')
+// this skips past the day of the week by finding the space following 
it
+expiry += 8 * sizeof(char);
+while (*expiry != ' ') expiry++;
+expiry++;
+end = expiry+1;
+while (*end != ';') end++;
+
+// ensure the time is parsable
+end = strptime(expiry, "%d %b %Y %H:%M:%S %Z", _buf);
+
+// ensure neulion's different format is parsable
+if (!end) end = strptime(expiry, "%d-%b-%Y %H:%M:%S %Z", _buf);
+
+// if the expire is specified but unparsable, this cookie is invalid
+if (!end) {
+av_log(s, AV_LOG_ERROR, "Unable to parse expiry for cookie 
'%s'\n", p);
+av_free(name);
+return AVERROR(EINVAL);
+}
+
+// no cookies from the past (neulion)
+if (mktime(_buf) < time(NULL)) {
+av_log(s, AV_LOG_ERROR, "Ignoring cookie from the past '%s'\n", p);
+av_free(name);
+return AVERROR(EINVAL);
+}
+}
+
 // add the cookie to the dictionary
 av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-02-11 Thread Micah Galizia
This one fixes the memory leak -- sorry for all the spam.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-02-11 Thread Micah Galizia
Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 34 +-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 944a6cf..e7b8ac3 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -682,12 +682,44 @@ static int parse_icy(HTTPContext *s, const char *tag, 
const char *p)
 
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
-char *eql, *name;
+char *eql, *name, *expiry;
 
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
 
+// ensure the expiry is sane
+if ((expiry = strstr(eql, "Expires="))) {
+struct tm tm_buf = {0};
+char *end;
+
+// get the start & the end of the expiry ('11 Feb 2017 09:41:35 GMT')
+// this skips past the day of the week by finding the space following 
it
+expiry += 8 * sizeof(char);
+while (*expiry != ' ') expiry++;
+expiry++;
+end = expiry+1;
+while (*end != ';') end++;
+
+// ensure the time is parsable
+end = strptime(expiry, "%d %b %Y %H:%M:%S %Z", _buf);
+
+// ensure neulion's different format is parsable
+if (!end) end = strptime(expiry, "%d-%b-%Y %H:%M:%S %Z", _buf);
+
+// if the expire is specified but unparsable, this cookie is invalid
+if (!end) {
+av_log(s, AV_LOG_ERROR, "Unable to parse expiry for cookie 
'%s'\n", p);
+return AVERROR(EINVAL);
+}
+
+// no cookies from the past (neulion)
+if (mktime(_buf) < time(NULL)) {
+av_log(s, AV_LOG_ERROR, "Ignoring cookie from the past '%s'\n", p);
+return AVERROR(EINVAL);
+}
+}
+
 // add the cookie to the dictionary
 av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-02-11 Thread Micah Galizia
Appologies, gmail screwed up the patch.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Ignore expired cookies

2017-02-11 Thread Micah Galizia
Hello,

On some authenticated Neulion streams, they send a cookie from the past,
like so:

Set-Cookie: nlqptid=""; Domain=.neulion.com; Expires=Thu, 01-Jan-1970
00:00:10 GMT; Path=/

As a result, the good cookie value is overwritten and authentication breaks
immediately. I realise disqualifying a cookie over the date might open a
can of worms when it comes to date formatting used by different systems,
but I added Neulions wrong format and the http standard format.

Please let me know if this is acceptable. I've run it against fate and
there were no problems.
-- 
"The mark of an immature man is that he wants to die nobly for a cause,
while the mark of the mature man is that he wants to live humbly for
one."   --W. Stekel
From 1fecda5a7a36b530208a9428b86eebda66b0 Mon Sep 17 00:00:00 2001
From: Micah Galizia <micahgali...@gmail.com>
Date: Sat, 11 Feb 2017 21:18:41 -0500
Subject: [PATCH] Ignore expired cookies

Signed-off-by: Micah Galizia <micahgali...@gmail.com>
---
 libavformat/http.c | 34 +-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 944a6cf..e7b8ac3 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -682,12 +682,44 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
 
 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
 {
-char *eql, *name;
+char *eql, *name, *expiry;
 
 // duplicate the cookie name (dict will dupe the value)
 if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
 if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
 
+// ensure the expiry is sane
+if ((expiry = strstr(eql, "Expires="))) {
+struct tm tm_buf = {0};
+char *end;
+
+// get the start & the end of the expiry ('11 Feb 2017 09:41:35 GMT')
+// this skips past the day of the week by finding the space following it
+expiry += 8 * sizeof(char);
+while (*expiry != ' ') expiry++;
+expiry++;
+end = expiry+1;
+while (*end != ';') end++;
+
+// ensure the time is parsable
+end = strptime(expiry, "%d %b %Y %H:%M:%S %Z", _buf);
+
+// ensure neulion's different format is parsable
+if (!end) end = strptime(expiry, "%d-%b-%Y %H:%M:%S %Z", _buf);
+
+// if the expire is specified but unparsable, this cookie is invalid
+if (!end) {
+av_log(s, AV_LOG_ERROR, "Unable to parse expiry for cookie '%s'\n", p);
+return AVERROR(EINVAL);
+}
+
+// no cookies from the past (neulion)
+if (mktime(_buf) < time(NULL)) {
+av_log(s, AV_LOG_ERROR, "Ignoring cookie from the past '%s'\n", p);
+return AVERROR(EINVAL);
+}
+}
+
 // add the cookie to the dictionary
 av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
 
-- 
2.9.3

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] hls merge cleanup

2015-08-01 Thread Micah Galizia
I've been watching an encrypted stream for the past 20 minutes and
everything seems to be working fine.

On Thu, Jul 30, 2015 at 1:10 PM, Michael Niedermayer
mich...@niedermayer.cc wrote:
 On Thu, Jul 30, 2015 at 12:39:53PM -0400, Micah Galizia wrote:
 Cookies and user agent stuff all look the same to me (I'll test with
 an encrypted stream this weekend).

 the Cookies  user agent stuff is still the code as it was previously

 best to look at the diff of the new code
 git show 0c73a5a53cc97f4291bbe9e1e68226edf6161744
 and what was actually changed
 git diff ba12ba859aabfa7153ba397d869db13acdaba340^ 
 ba12ba859aabfa7153ba397d869db13acdaba340


 and thanks alot for looking into this

 [...]
 --
 Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

 The misfortune of the wise is better than the prosperity of the fool.
 -- Epicurus



-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] hls merge cleanup

2015-07-30 Thread Micah Galizia
Cookies and user agent stuff all look the same to me (I'll test with
an encrypted stream this weekend).

Also, its cool that he added renditions.

On Thu, Jul 30, 2015 at 12:14 PM, Michael Niedermayer
mich...@niedermayer.cc wrote:
 Hi all

 luca has reimplemented some of the option handling in hls like
 cookies and user agent
 ive merged this in ba12ba859aabfa7153ba397d869db13acdaba340
 and used the new wraper functions where they fitted easily

 ive left the code using the previous tested and working option system

 Someone should look at the code and either drop the new avio_opts
 or the previous option fields like cookies. Or simplify it by any
 other means that seem appropriate

 I can also revert the merge if people prefer?

 Thanks

 --
 Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

 What does censorship reveal? It reveals fear. -- Julian Assange



-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] replace cookies with updated values instead of appending forever (backport to 2.6)

2015-03-27 Thread Micah Galizia
Hi,

One more -- backport code to replace cookie values instead appending
to the header forever.

-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From 629e9028f40cbf6f54c4b481a274aea5219d7c10 Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Tue, 17 Mar 2015 20:22:59 +1100
Subject: [PATCH 3/3] avformat/http: replace cookies with updated values
 instead of appending forever

Signed-off-by: Michael Niedermayer michae...@gmx.at
(cherry picked from commit c59654d67d1afde3fac24021ef0fd9d18cf38455)
Signed-off-by: Micah Galizia micahgali...@gmail.com
---
 libavformat/http.c | 65 +++---
 1 file changed, 52 insertions(+), 13 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 55dcb6e..f4ac90c 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -77,6 +77,8 @@ typedef struct HTTPContext {
 int is_akamai;
 int is_mediagateway;
 char *cookies;  /// holds newline (\n) delimited Set-Cookie header field values (without the Set-Cookie:  field name)
+/* A dictionary containing cookies keyed by cookie name */
+AVDictionary *cookie_dict;
 int icy;
 /* how much data was read since the last ICY metadata packet */
 int icy_data_read;
@@ -464,6 +466,43 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
 return 0;
 }
 
+static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
+{
+char *eql, *name;
+
+// duplicate the cookie name (dict will dupe the value)
+if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
+if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
+
+// add the cookie to the dictionary
+av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
+
+return 0;
+}
+
+static int cookie_string(AVDictionary *dict, char **cookies)
+{
+AVDictionaryEntry *e = NULL;
+int len = 1;
+
+// determine how much memory is needed for the cookies string
+while (e = av_dict_get(dict, , e, AV_DICT_IGNORE_SUFFIX))
+len += strlen(e-key) + strlen(e-value) + 1;
+
+// reallocate the cookies
+e = NULL;
+if (*cookies) av_free(*cookies);
+*cookies = av_malloc(len);
+if (!cookies) return AVERROR(ENOMEM);
+*cookies[0] = '\0';
+
+// write out the cookies
+while (e = av_dict_get(dict, , e, AV_DICT_IGNORE_SUFFIX))
+av_strlcatf(*cookies, len, %s%s\n, e-key, e-value);
+
+return 0;
+}
+
 static int process_line(URLContext *h, char *line, int line_count,
 int *new_location)
 {
@@ -535,19 +574,8 @@ static int process_line(URLContext *h, char *line, int line_count,
 av_free(s-mime_type);
 s-mime_type = av_strdup(p);
 } else if (!av_strcasecmp(tag, Set-Cookie)) {
-if (!s-cookies) {
-if (!(s-cookies = av_strdup(p)))
-return AVERROR(ENOMEM);
-} else {
-char *tmp = s-cookies;
-size_t str_size = strlen(tmp) + strlen(p) + 2;
-if (!(s-cookies = av_malloc(str_size))) {
-s-cookies = tmp;
-return AVERROR(ENOMEM);
-}
-snprintf(s-cookies, str_size, %s\n%s, tmp, p);
-av_free(tmp);
-}
+if (parse_cookie(s, p, s-cookie_dict))
+av_log(h, AV_LOG_WARNING, Unable to parse '%s'\n, p);
 } else if (!av_strcasecmp(tag, Icy-MetaInt)) {
 s-icy_metaint = strtoll(p, NULL, 10);
 } else if (!av_strncasecmp(tag, Icy-, 4)) {
@@ -578,12 +606,19 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
 
 if (!set_cookies) return AVERROR(EINVAL);
 
+// destroy any cookies in the dictionary.
+av_dict_free(s-cookie_dict);
+
 *cookies = NULL;
 while ((cookie = av_strtok(set_cookies, \n, next))) {
 int domain_offset = 0;
 char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = NULL;
 set_cookies = NULL;
 
+// store the cookie in a dict in case it is updated in the response
+if (parse_cookie(s, cookie, s-cookie_dict))
+av_log(s, AV_LOG_WARNING, Unable to parse '%s'\n, cookie);
+
 while ((param = av_strtok(cookie, ; , next_param))) {
 if (cookie) {
 // first key-value pair is the actual cookie value
@@ -691,6 +726,10 @@ static int http_read_header(URLContext *h, int *new_location)
 if (s-seekable == -1  s-is_mediagateway  s-filesize == 20)
 h-is_streamed = 1; /* we can in fact _not_ seek */
 
+// add any new cookies into the existing cookie string
+cookie_string(s-cookie_dict, s-cookies);
+av_dict_free(s-cookie_dict);
+
 return err;
 }
 
-- 
2.1.0

___
ffmpeg-devel

[FFmpeg-devel] [PATCH] Refactor repeated HLS option updates (Backport to 2.6)

2015-03-27 Thread Micah Galizia
Hi,

Backport code to refactor HLS option updates.

TIA
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From cd2beeadf124c495497e665e6b95265ca9fcb3a8 Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Mon, 16 Mar 2015 20:26:29 +1100
Subject: [PATCH 2/3] avformat/hls: refactor repeated HLS option updates

Signed-off-by: Michael Niedermayer michae...@gmx.at
(cherry picked from commit fca085187940a169b7a43d096009f7dac315f9ac)
Signed-off-by: Micah Galizia micahgali...@gmail.com
---
 libavformat/hls.c | 28 
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 5ed7a24..af890bd 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -903,6 +903,14 @@ static void intercept_id3(struct playlist *pls, uint8_t *buf,
 pls-is_id3_timestamped = (pls-id3_mpegts_timestamp != AV_NOPTS_VALUE);
 }
 
+static void update_options(char **dest, const char *name, void *src)
+{
+av_freep(dest);
+av_opt_get(src, name, 0, (uint8_t**)dest);
+if (*dest  !strlen(*dest))
+av_freep(dest);
+}
+
 static int open_input(HLSContext *c, struct playlist *pls)
 {
 AVDictionary *opts = NULL;
@@ -944,10 +952,7 @@ static int open_input(HLSContext *c, struct playlist *pls)
 av_log(NULL, AV_LOG_ERROR, Unable to read key file %s\n,
seg-key);
 }
-av_freep(c-cookies);
-av_opt_get(uc-priv_data, cookies, 0, (uint8_t**)(c-cookies));
-if (c-cookies  !strlen(c-cookies))
-av_freep(c-cookies);
+update_options(c-cookies, cookies, uc-priv_data);
 av_dict_set(opts, cookies, c-cookies, 0);
 ffurl_close(uc);
 } else {
@@ -1257,22 +1262,13 @@ static int hls_read_header(AVFormatContext *s)
 // if the URL context is good, read important options we must broker later
 if (u  u-prot-priv_data_class) {
 // get the previous user agent  set back to null if string size is zero
-av_freep(c-user_agent);
-av_opt_get(u-priv_data, user-agent, 0, (uint8_t**)(c-user_agent));
-if (c-user_agent  !strlen(c-user_agent))
-av_freep(c-user_agent);
+update_options(c-user_agent, user-agent, u-priv_data);
 
 // get the previous cookies  set back to null if string size is zero
-av_freep(c-cookies);
-av_opt_get(u-priv_data, cookies, 0, (uint8_t**)(c-cookies));
-if (c-cookies  !strlen(c-cookies))
-av_freep(c-cookies);
+update_options(c-cookies, cookies, u-priv_data);
 
 // get the previous headers  set back to null if string size is zero
-av_freep(c-headers);
-av_opt_get(u-priv_data, headers, 0, (uint8_t**)(c-headers));
-if (c-headers  !strlen(c-headers))
-av_freep(c-headers);
+update_options(c-headers, headers, u-priv_data);
 }
 
 if ((ret = parse_playlist(c, s-filename, NULL, s-pb))  0)
-- 
2.1.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Backport hls and cookie fixes to the 2.6 branch

2015-03-26 Thread Micah Galizia
Hi,

I'd like to backport my fixes from the main branch. Patch attached --
original commits were:

c59654d67d1afde3fac24021ef0fd9d18cf38455
fca085187940a169b7a43d096009f7dac315f9ac
7859618affe574c9de7f240d2ddc016f917c37bd

Thanks in advance!
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From dec8b5b1033c63906e7b1e783bd50a2be287d8d5 Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Thu, 26 Mar 2015 20:16:34 +1100
Subject: [PATCH] backport hls and cookie fixes

---
 libavformat/hls.c  | 25 +++--
 libavformat/http.c | 65 +++---
 2 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 5e8e1b2..af890bd 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -903,6 +903,14 @@ static void intercept_id3(struct playlist *pls, uint8_t *buf,
 pls-is_id3_timestamped = (pls-id3_mpegts_timestamp != AV_NOPTS_VALUE);
 }
 
+static void update_options(char **dest, const char *name, void *src)
+{
+av_freep(dest);
+av_opt_get(src, name, 0, (uint8_t**)dest);
+if (*dest  !strlen(*dest))
+av_freep(dest);
+}
+
 static int open_input(HLSContext *c, struct playlist *pls)
 {
 AVDictionary *opts = NULL;
@@ -944,6 +952,8 @@ static int open_input(HLSContext *c, struct playlist *pls)
 av_log(NULL, AV_LOG_ERROR, Unable to read key file %s\n,
seg-key);
 }
+update_options(c-cookies, cookies, uc-priv_data);
+av_dict_set(opts, cookies, c-cookies, 0);
 ffurl_close(uc);
 } else {
 av_log(NULL, AV_LOG_ERROR, Unable to open key file %s\n,
@@ -1252,22 +1262,13 @@ static int hls_read_header(AVFormatContext *s)
 // if the URL context is good, read important options we must broker later
 if (u  u-prot-priv_data_class) {
 // get the previous user agent  set back to null if string size is zero
-av_freep(c-user_agent);
-av_opt_get(u-priv_data, user-agent, 0, (uint8_t**)(c-user_agent));
-if (c-user_agent  !strlen(c-user_agent))
-av_freep(c-user_agent);
+update_options(c-user_agent, user-agent, u-priv_data);
 
 // get the previous cookies  set back to null if string size is zero
-av_freep(c-cookies);
-av_opt_get(u-priv_data, cookies, 0, (uint8_t**)(c-cookies));
-if (c-cookies  !strlen(c-cookies))
-av_freep(c-cookies);
+update_options(c-cookies, cookies, u-priv_data);
 
 // get the previous headers  set back to null if string size is zero
-av_freep(c-headers);
-av_opt_get(u-priv_data, headers, 0, (uint8_t**)(c-headers));
-if (c-headers  !strlen(c-headers))
-av_freep(c-headers);
+update_options(c-headers, headers, u-priv_data);
 }
 
 if ((ret = parse_playlist(c, s-filename, NULL, s-pb))  0)
diff --git a/libavformat/http.c b/libavformat/http.c
index 55dcb6e..f4ac90c 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -77,6 +77,8 @@ typedef struct HTTPContext {
 int is_akamai;
 int is_mediagateway;
 char *cookies;  /// holds newline (\n) delimited Set-Cookie header field values (without the Set-Cookie:  field name)
+/* A dictionary containing cookies keyed by cookie name */
+AVDictionary *cookie_dict;
 int icy;
 /* how much data was read since the last ICY metadata packet */
 int icy_data_read;
@@ -464,6 +466,43 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
 return 0;
 }
 
+static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
+{
+char *eql, *name;
+
+// duplicate the cookie name (dict will dupe the value)
+if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
+if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
+
+// add the cookie to the dictionary
+av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
+
+return 0;
+}
+
+static int cookie_string(AVDictionary *dict, char **cookies)
+{
+AVDictionaryEntry *e = NULL;
+int len = 1;
+
+// determine how much memory is needed for the cookies string
+while (e = av_dict_get(dict, , e, AV_DICT_IGNORE_SUFFIX))
+len += strlen(e-key) + strlen(e-value) + 1;
+
+// reallocate the cookies
+e = NULL;
+if (*cookies) av_free(*cookies);
+*cookies = av_malloc(len);
+if (!cookies) return AVERROR(ENOMEM);
+*cookies[0] = '\0';
+
+// write out the cookies
+while (e = av_dict_get(dict, , e, AV_DICT_IGNORE_SUFFIX))
+av_strlcatf(*cookies, len, %s%s\n, e-key, e-value);
+
+return 0;
+}
+
 static int process_line(URLContext *h, char *line, int line_count,
 int *new_location)
 {
@@ -535,19 +574,8 @@ static int

[FFmpeg-devel] Patches For 2.6 Branch

2015-03-21 Thread Micah Galizia
Hi,

I had some code accepted on the master branch and I was wondering if
they'd be suitable for inclusion in the 2.6 branch. I'd like them in
the next version of xmbc. The commits were:

c59654d67d1afde3fac24021ef0fd9d18cf38455
fca085187940a169b7a43d096009f7dac315f9ac
7859618affe574c9de7f240d2ddc016f917c37bd

Assuming they make sense (I'd view them as fixes, not features), do I
just merge them into the 2.6 branch and resubmit?
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] replace cookies with updated values

2015-03-17 Thread Micah Galizia
Hi,

The current Set-Cookie handling appends cookies to the string without
checking to see if a cookie with the same name should have its value
updated.

This is my second attempt to fix this issue -- last time it was a bit
of a string parsing nightmare. This time its a little less complex
(using a dictionary).

Before we start the the existing implementation sucks, change it
discussion I've looked into passing them around in their dictionary
form (an only using the string to initialize cookies from an external
source) but so far as I can tell, AVDictonary cannot be retrieved
using av_opt_get or av_opt_find right now.

Anyway, I hope this is sufficient for inclusion.

TIA
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From 18b00063d177965facd805d6b89eb96af371de94 Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Tue, 17 Mar 2015 20:22:59 +1100
Subject: [PATCH 3/3] replace cookies with updated values instead of appending
 forever

---
 libavformat/http.c | 65 +++---
 1 file changed, 52 insertions(+), 13 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 86380b2..da3c9be 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -77,6 +77,8 @@ typedef struct HTTPContext {
 int is_akamai;
 int is_mediagateway;
 char *cookies;  /// holds newline (\n) delimited Set-Cookie header field values (without the Set-Cookie:  field name)
+/* A dictionary containing cookies keyed by cookie name */
+AVDictionary *cookie_dict;
 int icy;
 /* how much data was read since the last ICY metadata packet */
 int icy_data_read;
@@ -466,6 +468,43 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
 return 0;
 }
 
+static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
+{
+char *eql, *name;
+
+// duplicate the cookie name (dict will dupe the value)
+if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
+if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
+
+// add the cookie to the dictionary
+av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
+
+return 0;
+}
+
+static int cookie_string(AVDictionary *dict, char **cookies)
+{
+AVDictionaryEntry *e = NULL;
+int len = 1;
+
+// determine how much memory is needed for the cookies string
+while (e = av_dict_get(dict, , e, AV_DICT_IGNORE_SUFFIX))
+len += strlen(e-key) + strlen(e-value) + 1;
+
+// reallocate the cookies
+e = NULL;
+if (*cookies) av_free(*cookies);
+*cookies = av_malloc(len);
+if (!cookies) return AVERROR(ENOMEM);
+*cookies[0] = '\0';
+
+// write out the cookies
+while (e = av_dict_get(dict, , e, AV_DICT_IGNORE_SUFFIX))
+av_strlcatf(*cookies, len, %s%s\n, e-key, e-value);
+
+return 0;
+}
+
 static int process_line(URLContext *h, char *line, int line_count,
 int *new_location)
 {
@@ -537,19 +576,8 @@ static int process_line(URLContext *h, char *line, int line_count,
 av_free(s-mime_type);
 s-mime_type = av_strdup(p);
 } else if (!av_strcasecmp(tag, Set-Cookie)) {
-if (!s-cookies) {
-if (!(s-cookies = av_strdup(p)))
-return AVERROR(ENOMEM);
-} else {
-char *tmp = s-cookies;
-size_t str_size = strlen(tmp) + strlen(p) + 2;
-if (!(s-cookies = av_malloc(str_size))) {
-s-cookies = tmp;
-return AVERROR(ENOMEM);
-}
-snprintf(s-cookies, str_size, %s\n%s, tmp, p);
-av_free(tmp);
-}
+if (parse_cookie(s, p, s-cookie_dict))
+av_log(h, AV_LOG_WARNING, Unable to parse '%s'\n, p);
 } else if (!av_strcasecmp(tag, Icy-MetaInt)) {
 s-icy_metaint = strtoll(p, NULL, 10);
 } else if (!av_strncasecmp(tag, Icy-, 4)) {
@@ -580,12 +608,19 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
 
 if (!set_cookies) return AVERROR(EINVAL);
 
+// destroy any cookies in the dictionary.
+av_dict_free(s-cookie_dict);
+
 *cookies = NULL;
 while ((cookie = av_strtok(set_cookies, \n, next))) {
 int domain_offset = 0;
 char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = NULL;
 set_cookies = NULL;
 
+// store the cookie in a dict in case it is updated in the response
+if (parse_cookie(s, cookie, s-cookie_dict))
+av_log(s, AV_LOG_WARNING, Unable to parse '%s'\n, cookie);
+
 while ((param = av_strtok(cookie, ; , next_param))) {
 if (cookie) {
 // first key-value pair is the actual cookie value
@@ -693,6 +728,10 @@ static int http_read_header(URLContext *h

Re: [FFmpeg-devel] [PATCH] Refactor repeated HLS option updates

2015-03-16 Thread Micah Galizia
Excellent. Thank you!

On Mon, Mar 16, 2015 at 11:02 PM, Michael Niedermayer michae...@gmx.at wrote:
 On Mon, Mar 16, 2015 at 08:34:24PM +1100, Micah Galizia wrote:
 Hi,

 Attached patch puts repeated code into a function.

 TIA
 --
 The mark of an immature man is that he wants to die nobly for a
 cause, while the mark of the mature man is that he wants to live
 humbly for one.   --W. Stekel

  hls.c |   28 
  1 file changed, 12 insertions(+), 16 deletions(-)
 b169e5c1a49fe7d16e0e44e897fdebe1e62f7d41  
 0002-refactor-repeated-HLS-option-updates.patch
 From 38b40bb622693f6b6f579092537aa9b7da28f9e1 Mon Sep 17 00:00:00 2001
 From: Micah Galizia micahgali...@gmail.com
 Date: Mon, 16 Mar 2015 20:26:29 +1100
 Subject: [PATCH 2/2] refactor repeated HLS option updates

 applied

 thanks

 [...]

 --
 Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

 Concerning the gods, I have no means of knowing whether they exist or not
 or of what sort they may be, because of the obscurity of the subject, and
 the brevity of human life -- Protagoras

 ___
 ffmpeg-devel mailing list
 ffmpeg-devel@ffmpeg.org
 http://ffmpeg.org/mailman/listinfo/ffmpeg-devel




-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Refactor repeated HLS option updates

2015-03-16 Thread Micah Galizia
Hi,

Attached patch puts repeated code into a function.

TIA
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From 38b40bb622693f6b6f579092537aa9b7da28f9e1 Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Mon, 16 Mar 2015 20:26:29 +1100
Subject: [PATCH 2/2] refactor repeated HLS option updates

---
 libavformat/hls.c | 28 
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 5ed7a24..af890bd 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -903,6 +903,14 @@ static void intercept_id3(struct playlist *pls, uint8_t *buf,
 pls-is_id3_timestamped = (pls-id3_mpegts_timestamp != AV_NOPTS_VALUE);
 }
 
+static void update_options(char **dest, const char *name, void *src)
+{
+av_freep(dest);
+av_opt_get(src, name, 0, (uint8_t**)dest);
+if (*dest  !strlen(*dest))
+av_freep(dest);
+}
+
 static int open_input(HLSContext *c, struct playlist *pls)
 {
 AVDictionary *opts = NULL;
@@ -944,10 +952,7 @@ static int open_input(HLSContext *c, struct playlist *pls)
 av_log(NULL, AV_LOG_ERROR, Unable to read key file %s\n,
seg-key);
 }
-av_freep(c-cookies);
-av_opt_get(uc-priv_data, cookies, 0, (uint8_t**)(c-cookies));
-if (c-cookies  !strlen(c-cookies))
-av_freep(c-cookies);
+update_options(c-cookies, cookies, uc-priv_data);
 av_dict_set(opts, cookies, c-cookies, 0);
 ffurl_close(uc);
 } else {
@@ -1257,22 +1262,13 @@ static int hls_read_header(AVFormatContext *s)
 // if the URL context is good, read important options we must broker later
 if (u  u-prot-priv_data_class) {
 // get the previous user agent  set back to null if string size is zero
-av_freep(c-user_agent);
-av_opt_get(u-priv_data, user-agent, 0, (uint8_t**)(c-user_agent));
-if (c-user_agent  !strlen(c-user_agent))
-av_freep(c-user_agent);
+update_options(c-user_agent, user-agent, u-priv_data);
 
 // get the previous cookies  set back to null if string size is zero
-av_freep(c-cookies);
-av_opt_get(u-priv_data, cookies, 0, (uint8_t**)(c-cookies));
-if (c-cookies  !strlen(c-cookies))
-av_freep(c-cookies);
+update_options(c-cookies, cookies, u-priv_data);
 
 // get the previous headers  set back to null if string size is zero
-av_freep(c-headers);
-av_opt_get(u-priv_data, headers, 0, (uint8_t**)(c-headers));
-if (c-headers  !strlen(c-headers))
-av_freep(c-headers);
+update_options(c-headers, headers, u-priv_data);
 }
 
 if ((ret = parse_playlist(c, s-filename, NULL, s-pb))  0)
-- 
2.1.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] store cookies returned in HLS key responses

2015-03-15 Thread Micah Galizia
Excellent, thank you -- patch to refactor that repeated
free/opt_get/free code (it happens four times) will be submitted
shortly...

On Mon, Mar 16, 2015 at 12:00 PM, Michael Niedermayer michae...@gmx.at wrote:
 On Sun, Mar 15, 2015 at 10:00:38AM +1100, Micah Galizia wrote:
 Hello,

 Neulion has added Set-Cookie fields in the response headers of their
 HLS key files. Those cookie values must be echoed back in the next key
 request or authentication on the subsequent key will fail.

 This fix will exacerbate the existing bug where the cookie field of
 ffmpeg requests keeps getting larger (since cookies are append when
 they should be replaced). However, those streams will fail sooner
 without this fix. Also, I have a fix for that bug too, but I'll start
 with this.

 Thanks in advance!
 --
 The mark of an immature man is that he wants to die nobly for a
 cause, while the mark of the mature man is that he wants to live
 humbly for one.   --W. Stekel

  hls.c |5 +
  1 file changed, 5 insertions(+)
 0105a89eff5edb6fbc2751a369447dd743496476  
 0001-store-cookies-returned-in-HLS-key-response.patch
 From 7f2db07b91407a970b99655da96c8c2532e2c1ad Mon Sep 17 00:00:00 2001
 From: Micah Galizia micahgali...@gmail.com
 Date: Sun, 15 Mar 2015 09:31:59 +1100
 Subject: [PATCH] store cookies returned in HLS key response

 applied

 thanks

 [...]

 --
 Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

 I know you won't believe me, but the highest form of Human Excellence is
 to question oneself and others. -- Socrates

 ___
 ffmpeg-devel mailing list
 ffmpeg-devel@ffmpeg.org
 http://ffmpeg.org/mailman/listinfo/ffmpeg-devel




-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] store cookies returned in HLS key responses

2015-03-14 Thread Micah Galizia
Hello,

Neulion has added Set-Cookie fields in the response headers of their
HLS key files. Those cookie values must be echoed back in the next key
request or authentication on the subsequent key will fail.

This fix will exacerbate the existing bug where the cookie field of
ffmpeg requests keeps getting larger (since cookies are append when
they should be replaced). However, those streams will fail sooner
without this fix. Also, I have a fix for that bug too, but I'll start
with this.

Thanks in advance!
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From 7f2db07b91407a970b99655da96c8c2532e2c1ad Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Sun, 15 Mar 2015 09:31:59 +1100
Subject: [PATCH] store cookies returned in HLS key response

---
 libavformat/hls.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 5e8e1b2..5ed7a24 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -944,6 +944,11 @@ static int open_input(HLSContext *c, struct playlist *pls)
 av_log(NULL, AV_LOG_ERROR, Unable to read key file %s\n,
seg-key);
 }
+av_freep(c-cookies);
+av_opt_get(uc-priv_data, cookies, 0, (uint8_t**)(c-cookies));
+if (c-cookies  !strlen(c-cookies))
+av_freep(c-cookies);
+av_dict_set(opts, cookies, c-cookies, 0);
 ffurl_close(uc);
 } else {
 av_log(NULL, AV_LOG_ERROR, Unable to open key file %s\n,
-- 
2.1.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] Reorganizing Cookies (was Re: [PATCH] Replace old cookies with new cookies of the same name)

2014-09-28 Thread Micah Galizia

On 18/08/14 21:36, Nicolas George wrote:

Le primidi 1er fructidor, an CCXXII, Micah Galizia a écrit :

Yes  no. I agree its not an ideal implementation (it actually was
mine to begin with) to just use a string full of cookies. But we can't
pass around complex structures through avopts, which is where we would
really see the benefit. As you  Mark pointed out, we need to maintain
compatibility with the current format, so why why go through parsing
the cookie list each time if 1 in 100 requests actually sends back an
updated cookie, and even then you'd have to dump it back out to a
string and parse it again to pass it between http requests all
this considered, I'd say I'm definitely leaning to no unless there
is something I've overlooked.


First, a small nitpick: if you read the option to get the updated values of
the cookies after the request, then you are abusing the API, as the option
does not have AV_OPT_FLAG_EXPORT. But for the sake of discussion we can
assume it should be there and always was.

But that does not mean that the string must be the authoritative value used
internally. A lot of your code is spent updating the middle of the string
while keeping the prefix and suffix constant. That makes a lot of tricky
code, with reallocations and possible integer overflows everywhere.

I am convinced that parsing the string as a whole, manipulating an internal
data structure and rebuilding the string as a whole would give much simpler
code. The parsing is needed for the actual Set-Cookie header; line-splitting
is relatively easy. As for the rebuilding of the string, we have utilities
that can take care of the reallocations and integer overflow for you; I
think especially of AVBPrint. Here is a snippet of code:

 av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED);
 for (i = 0; i  http-nb_cookies; i++) {
Cookie *c = http-cookie[i];
if (i)
av_bprintf(bp, \n);
av_bprintf(bp, %s=%s, c-name, c-value);
if (c-domain)
av_bprintf(bp, ; domain=%s, c-domain);
if (c-path)
av_bprintf(bp, ; path=%s, c-path);
if (c-extra)
av_bprintf(bp, ; %s, c-extra);
 }
 if (!av_bprint_is_complete(bp))
return AVERROR(ENOMEM);
 return av_bprint_finalize(bp, http-cookies);


Another point: I believe that having a callback on some options values may
also be quite useful. That could be done as AV_OPT_FLAG_CALLBACK with a
function pointer in AVClass. In this particular case, the callback could
parse the string on the fly and re-generate it only when necessary.


You lost me on the callback bit. I'm not sure I get how it'd really help.


What do people think about that?


I'd like to reorganize the cookies. Where I come up short is how to 
store them once they're parsed. Ideally, whatever their structure, they 
should be tied into the AVOption array for http so hls can copy them 
back and forth. That doesn't really leave me with a lot of choice for 
data structures -- and I'd rather not create a new AV_OPT_TYPE.


Using what is available now I could keep the existing cookies option 
(newline delimited string) to allow external apps to set the cookies 
initially. After they are passed in I could break them into a second 
dictionary option (with the export flag) keyed by cookie name so at 
least replacement is easier. I'd probably unset the original cookie 
string too once they're broken into a dict so that there is no ambiguity 
over where they are stored. Then, hls (or any other code) could pass 
around the dict option instead of the string.


I'm open to suggestions if I've overlooked an obvious way to tie generic 
structs into the AVOptions though. Alternatively, if the dictionary 
method is enough of an improvement I'll put in patchs to get it done 
that way.


--
Micah
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] Replace old cookies with new cookies of the same name

2014-08-18 Thread Micah Galizia
On Sun, Aug 17, 2014 at 9:29 PM, Nicolas George geo...@nsup.org wrote:
 Le decadi 30 thermidor, an CCXXII, Micah Galizia a écrit :
 When new cookie values (with the same name as an existing cookie) are
 returned in an HLS stream, the current implementation will append the
 new cookie to the list of cookies. This causes FFMPEG to send multiple
 cookie values for the same cookie and in some cases exceed the http
 header size in some cases.

 The patch attached resolves the issue.

 Thanks for the patch. Below are a few technical remarks. But before that, a
 general remark:

 char *cookies;  /// holds newline (\n) delimited Set-Cookie header field
  values (without the Set-Cookie:  field name)

 Well, this is just awful. This is obviously not your fault, this is existing
 code, but it is no way of building anything: it can do for a quick-and-dirty
 first implementation to get things working, but it makes a very bad ground
 to build upon.

 It seems to me that most of your patch is there to deal with that awful data
 structure. A large part of the existing code too, for that matter.

 IMHO, it would be much better to rework the current code to use a proper
 data structure. A dynarray of structures with name, value, path and domain
 already split seems like the best option.

 I suspect it would even be simpler to do that than making sure your patch is
 correct in its current form.

 Are you interested in that?

Yes  no. I agree its not an ideal implementation (it actually was
mine to begin with) to just use a string full of cookies. But we can't
pass around complex structures through avopts, which is where we would
really see the benefit. As you  Mark pointed out, we need to maintain
compatibility with the current format, so why why go through parsing
the cookie list each time if 1 in 100 requests actually sends back an
updated cookie, and even then you'd have to dump it back out to a
string and parse it again to pass it between http requests all
this considered, I'd say I'm definitely leaning to no unless there
is something I've overlooked.

I'll follow up separately on the issues in the patch.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] Replace old cookies with new cookies of the same name

2014-08-17 Thread Micah Galizia
When new cookie values (with the same name as an existing cookie) are
returned in an HLS stream, the current implementation will append the
new cookie to the list of cookies. This causes FFMPEG to send multiple
cookie values for the same cookie and in some cases exceed the http
header size in some cases.

The patch attached resolves the issue.
-- 
The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one.   --W. Stekel
From ad65b070a7b49698e623f08365ec7e751d0bae08 Mon Sep 17 00:00:00 2001
From: Micah Galizia micahgali...@gmail.com
Date: Sun, 17 Aug 2014 20:50:02 +1000
Subject: [PATCH] Replace old cookies with new cookies of the same name

---
 libavformat/http.c | 86 +-
 1 file changed, 73 insertions(+), 13 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 7480834..f1b9c34 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -444,6 +444,77 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
 return 0;
 }
 
+static int update_cookies(URLContext *h, char **cookies, char *new_cookie) {
+
+int prefix, offset, suffix, new_cookie_len = strlen(new_cookie);
+char *name, *cookie, *next;
+
+// if the existing cookies are empty then just set it and forget it
+if (!*cookies) {
+if (!(*cookies = av_strdup(new_cookie)))
+return AVERROR(ENOMEM);
+return 0;
+}
+
+// get the new cookies name
+if (!(cookie = av_strdup(new_cookie)))
+return AVERROR(ENOMEM);
+
+// if the new cookie format isnt valid just return (without error)
+if (!(name = av_strtok(cookie, =, next))) {
+av_log(h, AV_LOG_INFO, Invalid new cookie format.);
+return 0;
+}
+
+// copy the name and then free the copy of the cookies
+name = av_asprintf(%s=, name);
+av_free(cookie);
+
+// find the offset and free the name (we don't need it anymore)
+next = av_stristr(*cookies, name);
+av_free(name);
+
+// if no substring is found, just append
+if (!next) {
+cookie = av_asprintf(%s\n%s, *cookies, new_cookie);
+av_free(*cookies);
+*cookies = cookie;
+return 0;
+}
+
+prefix = next - *cookies;
+
+// no subsequent newline means this is the last cookie
+if (!(next = av_stristr(next, \n))) {
+
+// old and new cookie plus null terminate
+if (!(cookie = av_malloc(prefix + new_cookie_len + 1)))
+return AVERROR(ENOMEM);
+
+strncpy(cookie, *cookies, prefix);
+sprintf(cookie[prefix], %s, new_cookie);
+av_free(*cookies);
+*cookies = cookie;
+return 0;
+}
+
+offset = next - *cookies;
+suffix = strlen(*cookies) - offset;
+
+if (!(cookie = av_malloc(prefix + suffix + new_cookie_len + 2)))
+return AVERROR(ENOMEM);
+
+// copy in the prefix, new cookie, and suffix if they exist
+if (prefix) strncpy(cookie, *cookies, prefix);
+sprintf(cookie[prefix], %s, new_cookie);
+if (suffix) strncpy(cookie[prefix + new_cookie_len], ((*cookies)[offset]), suffix);
+
+av_free(*cookies);
+*cookies = cookie;
+
+return 0;
+}
+
 static int process_line(URLContext *h, char *line, int line_count,
 int *new_location)
 {
@@ -515,19 +586,8 @@ static int process_line(URLContext *h, char *line, int line_count,
 av_free(s-mime_type);
 s-mime_type = av_strdup(p);
 } else if (!av_strcasecmp(tag, Set-Cookie)) {
-if (!s-cookies) {
-if (!(s-cookies = av_strdup(p)))
-return AVERROR(ENOMEM);
-} else {
-char *tmp = s-cookies;
-size_t str_size = strlen(tmp) + strlen(p) + 2;
-if (!(s-cookies = av_malloc(str_size))) {
-s-cookies = tmp;
-return AVERROR(ENOMEM);
-}
-snprintf(s-cookies, str_size, %s\n%s, tmp, p);
-av_free(tmp);
-}
+update_cookies(h, s-cookies, p);
+av_log(h, AV_LOG_VERBOSE, Cookies set to '%s'\n, s-cookies);
 } else if (!av_strcasecmp(tag, Icy-MetaInt)) {
 s-icy_metaint = strtoll(p, NULL, 10);
 } else if (!av_strncasecmp(tag, Icy-, 4)) {
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel