31 #include <QNetworkRequest>
32 #include <QNetworkReply>
33 #include <QNetworkCookie>
43 #include <xmlsettingsdialog/basesettingsmanager.h>
53 QUrl URLFromClientID (
const QString&
id,
const QStringList& scope)
55 auto url = QUrl::fromEncoded (
"https://oauth.vk.com/authorize?redirect_uri=http%3A%2F%2Foauth.vk.com%2Fblank.html&response_type=token&state=");
58 (
"scope", scope.join (
","));
64 const QString&
id,
const QStringList& scope,
69 , AccountHR_ (accName)
70 , AuthNAM_ (new QNetworkAccessManager (this))
74 , IsRequesting_ (false)
76 , URL_ (URLFromClientID (ID_, scope))
77 , IsRequestScheduled_ (false)
78 , ScheduleTimer_ (new QTimer (this))
80 AuthNAM_->setCookieJar (Cookies_);
81 Cookies_->
Load (cookies);
83 ScheduleTimer_->setSingleShot (
true);
84 connect (ScheduleTimer_,
87 SLOT (execScheduledRequest ()));
92 return !Token_.isEmpty () &&
93 (!ValidFor_ || ReceivedAt_.secsTo (QDateTime::currentDateTime ()) < ValidFor_);
98 return !Token_.isEmpty () || !Cookies_->allCookies ().isEmpty ();
103 const auto& newUrl = URLFromClientID (ID_, scope);
109 ReceivedAt_ = QDateTime ();
117 PrioManagedQueues_.clear ();
118 ManagedQueues_.clear ();
128 InvokeQueues (Token_);
136 qWarning () << Q_FUNC_INFO
137 <<
"cannot manage request queue if queue manager wasn't set";
141 ManagedQueues_ << queue;
150 qWarning () << Q_FUNC_INFO
151 <<
"cannot manage request queue if queue manager wasn't set";
155 PrioManagedQueues_ << queue;
162 SilentMode_ = silent;
165 void VkAuthManager::InvokeQueues (
const QString& token)
167 ScheduleTrack (token);
169 for (
auto queue : PrioManagedQueues_)
170 while (!queue->isEmpty ())
172 const auto& pair = queue->takeFirst ();
173 const auto& f = pair.first;
174 Queue_->
Schedule ([f, token] { f (token); },
nullptr, pair.second);
177 for (
auto queue : ManagedQueues_)
178 while (!queue->isEmpty ())
180 const auto& f = queue->takeFirst ();
181 Queue_->
Schedule ([f, token] { f (token); });
185 void VkAuthManager::RequestURL (
const QUrl& url)
187 qDebug () << Q_FUNC_INFO << url;
188 auto reply = AuthNAM_->get (QNetworkRequest (url));
190 SIGNAL (finished ()),
192 SLOT (handleGotForm ()));
195 void VkAuthManager::RequestAuthKey ()
197 if (IsRequestScheduled_ && ScheduleTimer_->isActive ())
198 ScheduleTimer_->stop ();
204 IsRequesting_ =
true;
207 bool VkAuthManager::CheckReply (QUrl location)
209 if (location.path () !=
"/blank.html")
210 return CheckError (location);
212 location = QUrl::fromEncoded (location.toEncoded ().replace (
'#',
'?'));
213 #if QT_VERSION < 0x050000
214 Token_ = location.queryItemValue (
"access_token");
215 ValidFor_ = location.queryItemValue (
"expires_in").toInt ();
217 const QUrlQuery query { location };
218 Token_ = query.queryItemValue (
"access_token");
219 ValidFor_ = query.queryItemValue (
"expires_in").toInt ();
221 ReceivedAt_ = QDateTime::currentDateTime ();
222 qDebug () << Q_FUNC_INFO << Token_ << ValidFor_;
223 IsRequesting_ =
false;
225 InvokeQueues (Token_);
232 bool VkAuthManager::CheckError (
const QUrl& url)
234 if (url.path () !=
"/error")
237 #if QT_VERSION < 0x050000
238 const auto errNum = url.queryItemValue (
"err").toInt ();
240 const auto errNum = QUrlQuery { url }.queryItemValue (
"err").toInt ();
243 IsRequesting_ =
false;
245 qWarning () << Q_FUNC_INFO
257 tr (
"VK.com authentication for %1 failed because of error %2. "
258 "Report upstream please.")
262 Proxy_->GetEntityManager ()->HandleEntity (e);
267 void VkAuthManager::ScheduleTrack (
const QString& key)
272 if (!Proxy_->GetSettingsManager ()->property (
"TrackVK").toBool ())
277 QUrl url {
"https://api.vk.com/method/stats.trackVisitor" };
278 Util::UrlOperator { url }
279 (
"access_token", key);
281 auto reply = AuthNAM_->get (QNetworkRequest { url });
283 SIGNAL (finished ()),
285 SLOT (deleteLater ()));
292 ReceivedAt_ = QDateTime ();
298 class CloseEventFilter :
public QObject
302 CloseEventFilter (
const std::function<
void ()>& handler, QObject *handlee)
303 : QObject { handlee }
306 handlee->installEventFilter (
this);
309 bool eventFilter (QObject*, QEvent *event)
320 auto view =
new QWebView;
321 view->setWindowTitle (tr (
"VK.com authentication for %1")
324 view->resize (800, 600);
325 view->page ()->setNetworkAccessManager (AuthNAM_);
331 SIGNAL (urlChanged (QUrl)),
333 SLOT (handleViewUrlChanged (QUrl)));
335 new CloseEventFilter ([
this] { emit
authCanceled (); }, view);
338 void VkAuthManager::execScheduledRequest ()
340 IsRequestScheduled_ =
false;
345 void VkAuthManager::handleGotForm ()
347 auto reply = qobject_cast<QNetworkReply*> (sender ());
348 reply->deleteLater ();
350 if (reply->error () != QNetworkReply::NoError)
352 qWarning () << Q_FUNC_INFO
354 << reply->errorString ();
356 IsRequesting_ =
false;
358 if (!IsRequestScheduled_)
360 IsRequestScheduled_ =
true;
361 ScheduleTimer_->start (30000);
367 const auto& location = reply->header (QNetworkRequest::LocationHeader).toUrl ();
368 if (location.isEmpty ())
374 if (CheckReply (location))
377 RequestURL (location);
380 void VkAuthManager::handleViewUrlChanged (
const QUrl& url)
382 if (!CheckReply (url))
386 sender ()->deleteLater ();
void UpdateScope(const QStringList &)
void gotAuthKey(const QString &)
std::shared_ptr< ICoreProxy > ICoreProxy_ptr
Manipulates query part of an QUrl object.
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
void Schedule(std::function< void()> functor, QObject *dependent=0, QueuePriority prio=QueuePriority::Normal)
Adds the given functor.
bool HadAuthentication() const
ScheduleGuard_t Q_REQUIRED_RESULT ManageQueue(RequestQueue_ptr)
Entity MakeNotification(const QString &header, const QString &text, Priority priority)
An utility function to make a Entity with notification.
A simple scheduling manager for a queue of functors.
bool IsAuthenticated() const
void cookiesChanged(const QByteArray &)
VkAuthManager(const QString &accountName, const QString &clientId, const QStringList &scope, const QByteArray &cookies, ICoreProxy_ptr, QueueManager *=nullptr, QObject *=nullptr)
A customized cookie jar with additional features.
const std::function< void()> Handler_
void Load(const QByteArray &data)