On Wed, Apr 26, 2017 at 09:48:09PM -0400, Micah Galizia wrote: > 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_MUTLI 2 > +#define MAX_EXPIRY 19 > +#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 = &cstr[strlen(cstr)-1]; > + while (strchr(WHITESPACES, *back)) { > + *back='\0'; > + back--; > + } > + > + next_param = cstr; > + while ((param = av_strtok(next_param, ";", &next_param))) { > + char *name, *value; > + param += strspn(param, WHITESPACES); > + if ((name = av_strtok(param, "=", &value))) { > + if (av_dict_set(dict, name, value, 0) < 0) > + return -1; this leaks cstr [...] > @@ -876,87 +979,82 @@ static int get_cookies(HTTPContext *s, char **cookies, > const char *path, > 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; > + while ((cookie = av_strtok(next, "\n", &next))) { > + AVDictionary *cookie_params = NULL; > + AVDictionaryEntry *cookie_entry, *e; > > // 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 > - cvalue = av_strdup(param); > - cookie = NULL; > - } else if (!av_strncasecmp("path=", param, 5)) { > - av_free(cpath); > - cpath = av_strdup(¶m[5]); > - } else if (!av_strncasecmp("domain=", param, 7)) { > - // if the cookie specifies a sub-domain, skip the leading > dot thereby > - // supporting URLs that point to sub-domains and the master > domain > - int leading_dot = (param[7] == '.'); > - av_free(cdomain); > - cdomain = av_strdup(¶m[7+leading_dot]); > - } else { > - // ignore unknown attributes > - } > + // continue on to the next cookie if this one cannot be parsed > + if (parse_set_cookie(cookie, &cookie_params)) > + continue; > + > + // if the cookie has no value, skip it > + cookie_entry = av_dict_get(cookie_params, "", NULL, > AV_DICT_IGNORE_SUFFIX); > + if (!cookie_entry || !cookie_entry->value) { > + av_dict_free(&cookie_params); > + continue; > } > - if (!cdomain) > - cdomain = av_strdup(domain); > - > - // ensure all of the necessary values are valid > - if (!cdomain || !cpath || !cvalue) { > - av_log(s, AV_LOG_WARNING, > - "Invalid cookie found, no value, path or domain > specified\n"); > - goto done_cookie; > + > + // if the cookie has expired, don't add it > + if ((e = av_dict_get(cookie_params, "expires", NULL, 0)) && > e->value) { > + struct tm tm_buf = {0}; > + if (!parse_set_cookie_expiry_time(e->value, &tm_buf)) { > + if (av_timegm(&tm_buf) < av_gettime() / 1000000) { > + av_dict_free(&cookie_params); > + continue; > + } > + } > } > > - // check if the request path matches the cookie path > - if (av_strncasecmp(path, cpath, strlen(cpath))) > - goto done_cookie; > + // if no domain in the cookie assume it appied to this request > + if ((e = av_dict_get(cookie_params, "domain", NULL, 0)) && e->value) > { > + // find the offset comparison is on the min domain (b.com, not > a.b.com) > + int domain_offset = strlen(domain) - strlen(e->value); > + if (domain_offset < 0) { > + av_dict_free(&cookie_params); > + continue; > + } > > - // the domain should be at least the size of our cookie domain > - domain_offset = strlen(domain) - strlen(cdomain); > - if (domain_offset < 0) > - goto done_cookie; > + // match the cookie domain > + if (av_strcasecmp(&domain[domain_offset], e->value)) { > + av_dict_free(&cookie_params); > + continue; > + } > + } > > - // match the cookie domain > - if (av_strcasecmp(&domain[domain_offset], cdomain)) > - goto done_cookie; > + // ensure this cookie matches the path > + e = av_dict_get(cookie_params, "path", NULL, 0); > + if (!e || av_strncasecmp(path, e->value, strlen(e->value))) { > + av_dict_free(&cookie_params); > + continue; > + } > > // cookie parameters match, so copy the value > if (!*cookies) { > - if (!(*cookies = av_strdup(cvalue))) { > + if (!(*cookies = av_asprintf("%s=%s", cookie_entry->key, > cookie_entry->value))) { > ret = AVERROR(ENOMEM); > - goto done_cookie; > + break; > } > } else { > char *tmp = *cookies; > - size_t str_size = strlen(cvalue) + strlen(*cookies) + 3; > + size_t str_size = strlen(cookie_entry->key) + > strlen(cookie_entry->value) + strlen(*cookies) + 4; > if (!(*cookies = av_malloc(str_size))) { > ret = AVERROR(ENOMEM); > - goto done_cookie; > + break; This looks like it was already there but tmp leaks here i think feel free to ignore or fix in a seperate patch as its unrelated to this patch [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Those who would give up essential Liberty, to purchase a little temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin
signature.asc
Description: Digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel