| 70 | } |
| 71 | |
| 72 | Cookie Cookie::Parse(std::string_view cookie_header_value) { |
| 73 | // Parse the cookie string. If the cookie has an expiration, record it. |
| 74 | // If the cookie has a max-age, calculate the current time + max_age and set that as |
| 75 | // the expiration. |
| 76 | Cookie cookie; |
| 77 | cookie.has_expiry_ = false; |
| 78 | std::string cookie_value_str(cookie_header_value); |
| 79 | |
| 80 | // There should always be a first match which should be the name and value of the |
| 81 | // cookie. |
| 82 | std::string::size_type pos = 0; |
| 83 | CookiePair cookie_pair = ParseCookieAttribute(cookie_value_str, &pos); |
| 84 | if (!cookie_pair.has_value()) { |
| 85 | // No cookie found. Mark the output cookie as expired. |
| 86 | cookie.has_expiry_ = true; |
| 87 | cookie.expiration_time_ = std::chrono::system_clock::now(); |
| 88 | } else { |
| 89 | cookie.cookie_name_ = cookie_pair.value().first; |
| 90 | cookie.cookie_value_ = cookie_pair.value().second; |
| 91 | } |
| 92 | |
| 93 | while (pos < cookie_value_str.size()) { |
| 94 | cookie_pair = ParseCookieAttribute(cookie_value_str, &pos); |
| 95 | if (!cookie_pair.has_value()) { |
| 96 | break; |
| 97 | } |
| 98 | |
| 99 | std::string cookie_attr_value_str = cookie_pair.value().second; |
| 100 | if (arrow::internal::AsciiEqualsCaseInsensitive(cookie_pair.value().first, |
| 101 | "max-age")) { |
| 102 | // Note: max-age takes precedence over expires. We don't really care about other |
| 103 | // attributes and will arbitrarily take the first max-age. We can stop the loop |
| 104 | // here. |
| 105 | cookie.has_expiry_ = true; |
| 106 | int max_age = -1; |
| 107 | try { |
| 108 | max_age = std::stoi(cookie_attr_value_str); |
| 109 | } catch (...) { |
| 110 | // stoi throws an exception when it fails, just ignore and leave max_age as -1. |
| 111 | } |
| 112 | |
| 113 | if (max_age <= 0) { |
| 114 | // Force expiration. |
| 115 | cookie.expiration_time_ = std::chrono::system_clock::now(); |
| 116 | } else { |
| 117 | // Max-age is in seconds. |
| 118 | cookie.expiration_time_ = |
| 119 | std::chrono::system_clock::now() + std::chrono::seconds(max_age); |
| 120 | } |
| 121 | break; |
| 122 | } else if (arrow::internal::AsciiEqualsCaseInsensitive(cookie_pair.value().first, |
| 123 | "expires")) { |
| 124 | cookie.has_expiry_ = true; |
| 125 | int64_t seconds = 0; |
| 126 | ConvertCookieDate(&cookie_attr_value_str); |
| 127 | if (arrow::internal::ParseTimestampStrptime( |
| 128 | cookie_attr_value_str.c_str(), cookie_attr_value_str.size(), |
| 129 | kCookieExpiresFormat, false, true, arrow::TimeUnit::SECOND, &seconds)) { |
nothing calls this directly
no test coverage detected