12 #include <QNetworkCookie>
15 #include <QtConcurrentRun>
22 : QNetworkCookieJar (parent)
26 void CustomCookieJar::SetFilterTrackingCookies (
bool filter)
28 FilterTrackingCookies_ = filter;
31 void CustomCookieJar::SetEnabled (
bool enabled)
36 void CustomCookieJar::SetExactDomainMatch (
bool enabled)
38 MatchDomainExactly_ = enabled;
51 QByteArray CustomCookieJar::Save ()
const
53 auto cookies = allCookies ();
55 for (
const auto& cookie : cookies)
57 result += cookie.toRawForm ();
65 bool IsExpired (
const QNetworkCookie& cookie,
const QDateTime& now)
67 return !cookie.isSessionCookie () && cookie.expirationDate () < now;
71 void CustomCookieJar::Load (
const QByteArray& data)
74 for (
const auto& ba : data.split (
'\n'))
75 cookies << QNetworkCookie::parseCookies (ba);
77 const auto& now = QDateTime::currentDateTime ();
78 for (
const auto& cookie : cookies)
80 if (FilterTrackingCookies_ &&
81 cookie.name ().startsWith (
"__utm"))
84 if (IsExpired (cookie, now))
87 filteredCookies << cookie;
89 emit cookiesAdded (filteredCookies);
90 setAllCookies (filteredCookies);
93 void CustomCookieJar::CollectGarbage ()
95 const auto& cookies = allCookies ();
97 const auto& now = QDateTime::currentDateTime ();
98 for (
const auto& cookie : cookies)
100 if (IsExpired (cookie, now))
103 if (result.contains (cookie))
108 qDebug () << Q_FUNC_INFO << cookies.size () << result.size ();
109 setAllCookies (result);
118 for (
const auto& cookie : QNetworkCookieJar::cookiesForUrl (url))
119 if (!filtered.contains (cookie))
126 bool MatchDomain (
const QString& rawDomain,
const QString& rawCookieDomain)
128 auto normalize = [] (QStringView s)
130 return s.startsWith (
'.') ? s.mid (1) : s;
132 const auto& domain = normalize (rawDomain);
133 const auto& cookieDomain = normalize (rawCookieDomain);
135 if (domain == cookieDomain)
138 const auto idx = domain.indexOf (cookieDomain);
139 return idx > 0 && domain.at (idx - 1) ==
'.';
144 return std::any_of (list.begin (), list.end (),
145 [&str] (
const auto& rx) { return str == rx.pattern () || rx.exactMatch (str); });
154 auto CookieToTuple (
const QNetworkCookie& c)
156 return std::make_tuple (c.isHttpOnly (),
158 c.isSessionCookie (),
163 c.expirationDate ());
168 bool operator() (
const QNetworkCookie& left,
const QNetworkCookie& right)
const
170 return CookieToTuple (left) < CookieToTuple (right);
177 using Set_t = std::set<QNetworkCookie, CookieLess>;
178 Set_t previous { previousList.begin (), previousList.end () };
179 Set_t current { currentList.begin (), currentList.end () };
182 std::set_difference (previous.begin (), previous.end (),
183 current.begin (), current.end (),
184 std::back_inserter (diff.Removed_),
186 std::set_difference (current.begin (), current.end (),
187 previous.begin (), previous.end (),
188 std::back_inserter (diff.Added_),
200 filtered.reserve (cookieList.size ());
201 for (
auto cookie : cookieList)
203 if (cookie.domain ().isEmpty ())
204 cookie.setDomain (url.host ());
206 bool checkWhitelist =
false;
209 if (checkWhitelist && Check (WL_, cookie.domain ()))
213 if (MatchDomainExactly_ && !MatchDomain (url.host (), cookie.domain ()))
215 checkWhitelist =
true;
219 if (FilterTrackingCookies_ &&
220 cookie.name ().startsWith (
"__utm"))
222 checkWhitelist =
true;
226 if (!Check (BL_, cookie.domain ()))
230 const auto& existing = cookiesForUrl (url);
231 if (existing.isEmpty ())
232 emit cookiesAdded (filtered);
234 Util::Sequence (
this, QtConcurrent::run (CheckDifferences, existing, filtered)) >>
235 [
this] (
const CookiesDiff& diff)
237 if (!diff.Removed_.isEmpty ())
238 emit cookiesRemoved (diff.Removed_);
239 if (!diff.Added_.isEmpty ())
240 emit cookiesAdded (diff.Added_);
243 return QNetworkCookieJar::setCookiesFromUrl (filtered, url);