LeechCraft 0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
customcookiejar.cpp
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#include "customcookiejar.h"
10#include <set>
11#include <algorithm>
12#include <QNetworkCookie>
13#include <QtDebug>
14#include <QDateTime>
15#include <QtConcurrentRun>
16#include <util/sll/util.h>
18
19namespace LC::Util
20{
22 : QNetworkCookieJar (parent)
23 {
24 }
25
27 {
28 FilterTrackingCookies_ = filter;
29 }
30
32 {
33 Enabled_ = enabled;
34 }
35
37 {
38 MatchDomainExactly_ = enabled;
39 }
40
42 {
43 WL_ = list;
44 }
45
47 {
48 BL_ = list;
49 }
50
52 {
53 auto cookies = allCookies ();
55 for (const auto& cookie : cookies)
56 {
57 result += cookie.toRawForm ();
58 result += "\n";
59 }
60 return result;
61 }
62
63 namespace
64 {
65 bool IsExpired (const QNetworkCookie& cookie, const QDateTime& now)
66 {
67 return !cookie.isSessionCookie () && cookie.expirationDate () < now;
68 }
69 }
70
72 {
74 for (const auto& ba : data.split ('\n'))
75 cookies << QNetworkCookie::parseCookies (ba);
76
77 const auto& now = QDateTime::currentDateTime ();
78 for (const auto& cookie : cookies)
79 {
80 if (FilterTrackingCookies_ &&
81 cookie.name ().startsWith ("__utm"))
82 continue;
83
84 if (IsExpired (cookie, now))
85 continue;
86
88 }
91 }
92
94 {
95 const auto& cookies = allCookies ();
97 const auto& now = QDateTime::currentDateTime ();
98 for (const auto& cookie : cookies)
99 {
100 if (IsExpired (cookie, now))
101 continue;
102
103 if (result.contains (cookie))
104 continue;
105
106 result << cookie;
107 }
108 qDebug () << Q_FUNC_INFO << cookies.size () << result.size ();
110 }
111
113 {
114 if (!Enabled_)
115 return {};
116
118 for (const auto& cookie : QNetworkCookieJar::cookiesForUrl (url))
119 if (!filtered.contains (cookie))
120 filtered << cookie;
121 return filtered;
122 }
123
124 namespace
125 {
127 {
128 auto normalize = [] (QStringView s)
129 {
130 return s.startsWith ('.') ? s.mid (1) : s;
131 };
132 const auto& domain = normalize (rawDomain);
133 const auto& cookieDomain = normalize (rawCookieDomain);
134
135 if (domain == cookieDomain)
136 return true;
137
138 const auto idx = domain.indexOf (cookieDomain);
139 return idx > 0 && domain.at (idx - 1) == '.';
140 }
141
142 bool Check (const QList<QRegExp>& list, const QString& str)
143 {
144 return std::any_of (list.begin (), list.end (),
145 [&str] (const auto& rx) { return str == rx.pattern () || rx.exactMatch (str); });
146 }
147
148 struct CookiesDiff
149 {
152 };
153
154 auto CookieToTuple (const QNetworkCookie& c)
155 {
156 return std::make_tuple (c.isHttpOnly (),
157 c.isSecure (),
158 c.isSessionCookie (),
159 c.name (),
160 c.domain (),
161 c.path (),
162 c.value (),
163 c.expirationDate ());
164 }
165
166 struct CookieLess
167 {
168 bool operator() (const QNetworkCookie& left, const QNetworkCookie& right) const
169 {
171 }
172 };
173
176 {
177 using Set_t = std::set<QNetworkCookie, CookieLess>;
178 Set_t previous { previousList.begin (), previousList.end () };
179 Set_t current { currentList.begin (), currentList.end () };
180
181 CookiesDiff diff;
182 std::set_difference (previous.begin (), previous.end (),
183 current.begin (), current.end (),
184 std::back_inserter (diff.Removed_),
185 CookieLess {});
186 std::set_difference (current.begin (), current.end (),
187 previous.begin (), previous.end (),
188 std::back_inserter (diff.Added_),
189 CookieLess {});
190 return diff;
191 }
192 }
193
195 {
196 if (!Enabled_)
197 return false;
198
200 filtered.reserve (cookieList.size ());
201 for (auto cookie : cookieList)
202 {
203 if (cookie.domain ().isEmpty ())
204 cookie.setDomain (url.host ());
205
206 bool checkWhitelist = false;
207 const auto wlGuard = Util::MakeScopeGuard ([&]
208 {
209 if (checkWhitelist && Check (WL_, cookie.domain ()))
210 filtered << cookie;
211 });
212
213 if (MatchDomainExactly_ && !MatchDomain (url.host (), cookie.domain ()))
214 {
215 checkWhitelist = true;
216 continue;
217 }
218
219 if (FilterTrackingCookies_ &&
220 cookie.name ().startsWith ("__utm"))
221 {
222 checkWhitelist = true;
223 continue;
224 }
225
226 if (!Check (BL_, cookie.domain ()))
227 filtered << cookie;
228 }
229
230 const auto& existing = cookiesForUrl (url);
231 if (existing.isEmpty ())
233 else
234 Util::Sequence (this, QtConcurrent::run (CheckDifferences, existing, filtered)) >>
235 [this] (const CookiesDiff& diff)
236 {
237 if (!diff.Removed_.isEmpty ())
238 emit cookiesRemoved (diff.Removed_);
239 if (!diff.Added_.isEmpty ())
240 emit cookiesAdded (diff.Added_);
241 };
242
243 return QNetworkCookieJar::setCookiesFromUrl (filtered, url);
244 }
245}
QList< QNetworkCookie > Added_
QList< QNetworkCookie > Removed_
Container< T > Filter(const Container< T > &c, F f)
Definition prelude.h:118
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
Definition util.h:155