* Create a string containing cookie values for use as a HTTP cookie header * field value for a particular path and domain from the cookie values stored in * the HTTP protocol context. The cookie string is stored in *cookies, and may * be NULL if there are no valid cookies. * * @return a negative value if an error condition occurred, 0 otherwise */
| 1344 | * @return a negative value if an error condition occurred, 0 otherwise |
| 1345 | */ |
| 1346 | static int get_cookies(HTTPContext *s, char **cookies, const char *path, |
| 1347 | const char *domain) |
| 1348 | { |
| 1349 | // cookie strings will look like Set-Cookie header field values. Multiple |
| 1350 | // Set-Cookie fields will result in multiple values delimited by a newline |
| 1351 | int ret = 0; |
| 1352 | char *cookie, *set_cookies, *next; |
| 1353 | char *saveptr = NULL; |
| 1354 | |
| 1355 | // destroy any cookies in the dictionary. |
| 1356 | av_dict_free(&s->cookie_dict); |
| 1357 | |
| 1358 | if (!s->cookies) |
| 1359 | return 0; |
| 1360 | |
| 1361 | next = set_cookies = av_strdup(s->cookies); |
| 1362 | if (!next) |
| 1363 | return AVERROR(ENOMEM); |
| 1364 | |
| 1365 | *cookies = NULL; |
| 1366 | while ((cookie = av_strtok(next, "\n", &saveptr)) && !ret) { |
| 1367 | AVDictionary *cookie_params = NULL; |
| 1368 | const AVDictionaryEntry *cookie_entry, *e; |
| 1369 | |
| 1370 | next = NULL; |
| 1371 | // store the cookie in a dict in case it is updated in the response |
| 1372 | if (parse_cookie(s, cookie, &s->cookie_dict)) |
| 1373 | av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie); |
| 1374 | |
| 1375 | // continue on to the next cookie if this one cannot be parsed |
| 1376 | if (parse_set_cookie(cookie, &cookie_params)) |
| 1377 | goto skip_cookie; |
| 1378 | |
| 1379 | // if the cookie has no value, skip it |
| 1380 | cookie_entry = av_dict_iterate(cookie_params, NULL); |
| 1381 | if (!cookie_entry || !cookie_entry->value) |
| 1382 | goto skip_cookie; |
| 1383 | |
| 1384 | // if the cookie has expired, don't add it |
| 1385 | if ((e = av_dict_get(cookie_params, "expires", NULL, 0)) && e->value) { |
| 1386 | struct tm tm_buf = {0}; |
| 1387 | if (!parse_http_date(e->value, &tm_buf)) { |
| 1388 | if (av_timegm(&tm_buf) < av_gettime() / 1000000) |
| 1389 | goto skip_cookie; |
| 1390 | } |
| 1391 | } |
| 1392 | |
| 1393 | // if no domain in the cookie assume it applied to this request |
| 1394 | if ((e = av_dict_get(cookie_params, "domain", NULL, 0)) && e->value) { |
| 1395 | // find the offset comparison is on the min domain (b.com, not a.b.com) |
| 1396 | int domain_offset = strlen(domain) - strlen(e->value); |
| 1397 | if (domain_offset < 0) |
| 1398 | goto skip_cookie; |
| 1399 | |
| 1400 | // match the cookie domain |
| 1401 | if (av_strcasecmp(&domain[domain_offset], e->value)) |
| 1402 | goto skip_cookie; |
| 1403 | } |
no test coverage detected