Changeset View
Changeset View
Standalone View
Standalone View
src/job/gravatarresolvurljob.cpp
Show All 13 Lines | 1 | /* | |||
---|---|---|---|---|---|
14 | You should have received a copy of the GNU Library General Public License | 14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this library; see the file COPYING.LIB. If not, write to | 15 | along with this library; see the file COPYING.LIB. If not, write to | ||
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301, USA. | 17 | Boston, MA 02110-1301, USA. | ||
18 | */ | 18 | */ | ||
19 | 19 | | |||
20 | #include "gravatarresolvurljob.h" | 20 | #include "gravatarresolvurljob.h" | ||
21 | #include "misc/gravatarcache.h" | 21 | #include "misc/gravatarcache.h" | ||
22 | #include "misc/hash.h" | ||||
22 | #include "gravatar_debug.h" | 23 | #include "gravatar_debug.h" | ||
23 | #include <PimCommon/NetworkManager> | 24 | #include <PimCommon/NetworkManager> | ||
24 | 25 | | |||
25 | #include <QCoreApplication> | 26 | #include <QCoreApplication> | ||
26 | #include <QCryptographicHash> | 27 | #include <QCryptographicHash> | ||
27 | #include <QPixmap> | 28 | #include <QPixmap> | ||
28 | #include <QUrlQuery> | 29 | #include <QUrlQuery> | ||
29 | #include <QNetworkConfigurationManager> | 30 | #include <QNetworkConfigurationManager> | ||
30 | 31 | | |||
31 | using namespace Gravatar; | 32 | using namespace Gravatar; | ||
32 | 33 | | |||
33 | class Gravatar::GravatarResolvUrlJobPrivate | 34 | class Gravatar::GravatarResolvUrlJobPrivate | ||
34 | { | 35 | { | ||
35 | public: | 36 | public: | ||
36 | GravatarResolvUrlJobPrivate() | 37 | GravatarResolvUrlJobPrivate() | ||
37 | : mNetworkAccessManager(nullptr) | 38 | : mNetworkAccessManager(nullptr) | ||
38 | , mSize(80) | 39 | , mSize(80) | ||
40 | , mBackends(Gravatar) | ||||
39 | , mHasGravatar(false) | 41 | , mHasGravatar(false) | ||
40 | , mUseDefaultPixmap(false) | 42 | , mUseDefaultPixmap(false) | ||
41 | , mUseLibravatar(false) | | |||
42 | , mFallbackGravatar(true) | | |||
43 | , mFallbackDone(false) | | |||
44 | { | 43 | { | ||
45 | } | 44 | } | ||
46 | 45 | | |||
47 | QPixmap mPixmap; | 46 | QPixmap mPixmap; | ||
48 | QString mEmail; | 47 | QString mEmail; | ||
49 | QString mCalculatedHash; | 48 | Hash mCalculatedHash; | ||
50 | QNetworkAccessManager *mNetworkAccessManager; | 49 | QNetworkAccessManager *mNetworkAccessManager; | ||
51 | int mSize; | 50 | int mSize; | ||
51 | | ||||
52 | enum Backend { | ||||
53 | None = 0x0, | ||||
54 | Libravatar = 0x1, | ||||
55 | Gravatar = 0x2 | ||||
56 | }; | ||||
57 | int mBackends; | ||||
58 | | ||||
52 | bool mHasGravatar; | 59 | bool mHasGravatar; | ||
53 | bool mUseDefaultPixmap; | 60 | bool mUseDefaultPixmap; | ||
54 | bool mUseLibravatar; | | |||
55 | bool mFallbackGravatar; | | |||
56 | bool mFallbackDone; | | |||
57 | }; | 61 | }; | ||
58 | 62 | | |||
59 | GravatarResolvUrlJob::GravatarResolvUrlJob(QObject *parent) | 63 | GravatarResolvUrlJob::GravatarResolvUrlJob(QObject *parent) | ||
60 | : QObject(parent) | 64 | : QObject(parent) | ||
61 | , d(new Gravatar::GravatarResolvUrlJobPrivate) | 65 | , d(new Gravatar::GravatarResolvUrlJobPrivate) | ||
62 | { | 66 | { | ||
63 | } | 67 | } | ||
64 | 68 | | |||
Show All 18 Lines | |||||
83 | 87 | | |||
84 | bool GravatarResolvUrlJob::hasGravatar() const | 88 | bool GravatarResolvUrlJob::hasGravatar() const | ||
85 | { | 89 | { | ||
86 | return d->mHasGravatar; | 90 | return d->mHasGravatar; | ||
87 | } | 91 | } | ||
88 | 92 | | |||
89 | void GravatarResolvUrlJob::startNetworkManager(const QUrl &url) | 93 | void GravatarResolvUrlJob::startNetworkManager(const QUrl &url) | ||
90 | { | 94 | { | ||
91 | if (PimCommon::NetworkManager::self()->networkConfigureManager()->isOnline()) { | | |||
92 | if (!d->mNetworkAccessManager) { | 95 | if (!d->mNetworkAccessManager) { | ||
93 | d->mNetworkAccessManager = new QNetworkAccessManager(this); | 96 | d->mNetworkAccessManager = new QNetworkAccessManager(this); | ||
94 | connect(d->mNetworkAccessManager, &QNetworkAccessManager::finished, this, &GravatarResolvUrlJob::slotFinishLoadPixmap); | 97 | connect(d->mNetworkAccessManager, &QNetworkAccessManager::finished, this, &GravatarResolvUrlJob::slotFinishLoadPixmap); | ||
95 | } | 98 | } | ||
96 | QNetworkReply *reply = d->mNetworkAccessManager->get(QNetworkRequest(url)); | 99 | d->mNetworkAccessManager->get(QNetworkRequest(url)); | ||
97 | connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); | | |||
98 | } else { | | |||
99 | qCDebug(GRAVATAR_LOG) << " network is not connected"; | | |||
100 | deleteLater(); | | |||
101 | return; | | |||
102 | } | | |||
103 | } | 100 | } | ||
104 | 101 | | |||
105 | void GravatarResolvUrlJob::start() | 102 | void GravatarResolvUrlJob::start() | ||
106 | { | 103 | { | ||
104 | if (d->mBackends == GravatarResolvUrlJobPrivate::None) | ||||
105 | d->mBackends = GravatarResolvUrlJobPrivate::Gravatar; // default is Gravatar if nothing else is selected | ||||
106 | | ||||
107 | d->mHasGravatar = false; | 107 | d->mHasGravatar = false; | ||
108 | d->mFallbackDone = false; | | |||
109 | if (canStart()) { | 108 | if (canStart()) { | ||
110 | d->mCalculatedHash.clear(); | 109 | processNextBackend(); | ||
111 | const QUrl url = createUrl(d->mUseLibravatar); | | |||
112 | Q_EMIT resolvUrl(url); | | |||
113 | if (!cacheLookup(d->mCalculatedHash)) | | |||
114 | startNetworkManager(url); | | |||
115 | } else { | 110 | } else { | ||
116 | qCDebug(GRAVATAR_LOG) << "Gravatar can not start"; | 111 | qCDebug(GRAVATAR_LOG) << "Gravatar can not start"; | ||
117 | deleteLater(); | 112 | deleteLater(); | ||
118 | } | 113 | } | ||
119 | } | 114 | } | ||
120 | 115 | | |||
116 | void GravatarResolvUrlJob::processNextBackend() | ||||
117 | { | ||||
118 | if (d->mHasGravatar || d->mBackends == GravatarResolvUrlJobPrivate::None) { | ||||
119 | Q_EMIT finished(this); | ||||
120 | deleteLater(); | ||||
121 | return; | ||||
122 | } | ||||
123 | | ||||
124 | QUrl url; | ||||
125 | if (d->mBackends & GravatarResolvUrlJobPrivate::Libravatar) { | ||||
126 | d->mBackends &= ~GravatarResolvUrlJobPrivate::Libravatar; | ||||
127 | url = createUrl(true); | ||||
128 | } else if (d->mBackends & GravatarResolvUrlJobPrivate::Gravatar) { | ||||
129 | d->mBackends &= ~GravatarResolvUrlJobPrivate::Gravatar; | ||||
130 | url = createUrl(false); | ||||
131 | } | ||||
132 | | ||||
133 | Q_EMIT resolvUrl(url); | ||||
134 | if (!cacheLookup(d->mCalculatedHash)) | ||||
135 | startNetworkManager(url); | ||||
136 | else | ||||
137 | processNextBackend(); | ||||
138 | } | ||||
139 | | ||||
121 | void GravatarResolvUrlJob::slotFinishLoadPixmap(QNetworkReply *reply) | 140 | void GravatarResolvUrlJob::slotFinishLoadPixmap(QNetworkReply *reply) | ||
122 | { | 141 | { | ||
123 | if (reply->error() == QNetworkReply::NoError) { | 142 | if (reply->error() == QNetworkReply::NoError) { | ||
124 | d->mPixmap.loadFromData(reply->readAll()); | 143 | d->mPixmap.loadFromData(reply->readAll()); | ||
125 | d->mHasGravatar = true; | 144 | d->mHasGravatar = true; | ||
126 | //For the moment don't use cache other we will store a lot of pixmap | 145 | //For the moment don't use cache other we will store a lot of pixmap | ||
127 | if (!d->mUseDefaultPixmap) { | 146 | if (!d->mUseDefaultPixmap) { | ||
128 | GravatarCache::self()->saveGravatarPixmap(d->mCalculatedHash, d->mPixmap); | 147 | GravatarCache::self()->saveGravatarPixmap(d->mCalculatedHash, d->mPixmap); | ||
129 | } | 148 | } | ||
130 | } else if (d->mUseLibravatar && d->mFallbackGravatar && !d->mFallbackDone) { | 149 | } else { | ||
131 | d->mFallbackDone = true; | 150 | if (reply->error() == QNetworkReply::ContentNotFoundError) | ||
132 | d->mCalculatedHash.clear(); | 151 | GravatarCache::self()->saveMissingGravatar(d->mCalculatedHash); | ||
133 | const QUrl url = createUrl(false); | 152 | else | ||
134 | Q_EMIT resolvUrl(url); | 153 | qCDebug(GRAVATAR_LOG) << "Network error:" << reply->request().url() << reply->errorString(); | ||
135 | if (!cacheLookup(d->mCalculatedHash)) | | |||
136 | startNetworkManager(url); | | |||
137 | return; | | |||
138 | } | | |||
139 | reply->deleteLater(); | | |||
140 | Q_EMIT finished(this); | | |||
141 | deleteLater(); | | |||
142 | } | 154 | } | ||
143 | 155 | | |||
144 | void GravatarResolvUrlJob::slotError(QNetworkReply::NetworkError error) | 156 | processNextBackend(); | ||
145 | { | | |||
146 | if (error == QNetworkReply::ContentNotFoundError) { | | |||
147 | d->mHasGravatar = false; | | |||
148 | } | | |||
149 | } | 157 | } | ||
150 | 158 | | |||
151 | QString GravatarResolvUrlJob::email() const | 159 | QString GravatarResolvUrlJob::email() const | ||
152 | { | 160 | { | ||
153 | return d->mEmail; | 161 | return d->mEmail; | ||
154 | } | 162 | } | ||
155 | 163 | | |||
156 | void GravatarResolvUrlJob::setEmail(const QString &email) | 164 | void GravatarResolvUrlJob::setEmail(const QString &email) | ||
157 | { | 165 | { | ||
158 | d->mEmail = email; | 166 | d->mEmail = email; | ||
159 | } | 167 | } | ||
160 | 168 | | |||
161 | QString GravatarResolvUrlJob::calculateHash(bool useLibravator) | 169 | Hash GravatarResolvUrlJob::calculateHash(bool useLibravator) | ||
162 | { | 170 | { | ||
163 | QCryptographicHash hash(useLibravator ? QCryptographicHash::Sha256 : QCryptographicHash::Md5); | 171 | const auto email = d->mEmail.toLower().toUtf8(); | ||
164 | hash.addData(d->mEmail.toLower().toUtf8()); | 172 | if (useLibravator) | ||
165 | return QString::fromUtf8(hash.result().toHex()); | 173 | return Hash(QCryptographicHash::hash(email, QCryptographicHash::Sha256), Hash::Sha256); | ||
174 | return Hash(QCryptographicHash::hash(email, QCryptographicHash::Md5), Hash::Md5); | ||||
166 | } | 175 | } | ||
167 | 176 | | |||
168 | bool GravatarResolvUrlJob::fallbackGravatar() const | 177 | bool GravatarResolvUrlJob::fallbackGravatar() const | ||
169 | { | 178 | { | ||
170 | return d->mFallbackGravatar; | 179 | return d->mBackends & GravatarResolvUrlJobPrivate::Gravatar; | ||
171 | } | 180 | } | ||
172 | 181 | | |||
173 | void GravatarResolvUrlJob::setFallbackGravatar(bool fallbackGravatar) | 182 | void GravatarResolvUrlJob::setFallbackGravatar(bool fallbackGravatar) | ||
174 | { | 183 | { | ||
175 | d->mFallbackGravatar = fallbackGravatar; | 184 | if (fallbackGravatar) | ||
185 | d->mBackends |= GravatarResolvUrlJobPrivate::Gravatar; | ||||
186 | else | ||||
187 | d->mBackends &= ~GravatarResolvUrlJobPrivate::Gravatar; | ||||
176 | } | 188 | } | ||
177 | 189 | | |||
178 | bool GravatarResolvUrlJob::useLibravatar() const | 190 | bool GravatarResolvUrlJob::useLibravatar() const | ||
179 | { | 191 | { | ||
180 | return d->mUseLibravatar; | 192 | return d->mBackends & GravatarResolvUrlJobPrivate::Libravatar; | ||
181 | } | 193 | } | ||
182 | 194 | | |||
183 | void GravatarResolvUrlJob::setUseLibravatar(bool useLibravatar) | 195 | void GravatarResolvUrlJob::setUseLibravatar(bool useLibravatar) | ||
184 | { | 196 | { | ||
185 | d->mUseLibravatar = useLibravatar; | 197 | if (useLibravatar) | ||
198 | d->mBackends |= GravatarResolvUrlJobPrivate::Libravatar; | ||||
199 | else | ||||
200 | d->mBackends &= ~GravatarResolvUrlJobPrivate::Libravatar; | ||||
186 | } | 201 | } | ||
187 | 202 | | |||
188 | bool GravatarResolvUrlJob::useDefaultPixmap() const | 203 | bool GravatarResolvUrlJob::useDefaultPixmap() const | ||
189 | { | 204 | { | ||
190 | return d->mUseDefaultPixmap; | 205 | return d->mUseDefaultPixmap; | ||
191 | } | 206 | } | ||
192 | 207 | | |||
193 | void GravatarResolvUrlJob::setUseDefaultPixmap(bool useDefaultPixmap) | 208 | void GravatarResolvUrlJob::setUseDefaultPixmap(bool useDefaultPixmap) | ||
Show All 16 Lines | 224 | { | |||
210 | if (size <= 0) { | 225 | if (size <= 0) { | ||
211 | size = 80; | 226 | size = 80; | ||
212 | } else if (size > 2048) { | 227 | } else if (size > 2048) { | ||
213 | size = 2048; | 228 | size = 2048; | ||
214 | } | 229 | } | ||
215 | d->mSize = size; | 230 | d->mSize = size; | ||
216 | } | 231 | } | ||
217 | 232 | | |||
218 | QString GravatarResolvUrlJob::calculatedHash() const | 233 | Hash GravatarResolvUrlJob::calculatedHash() const | ||
219 | { | 234 | { | ||
220 | return d->mCalculatedHash; | 235 | return d->mCalculatedHash; | ||
221 | } | 236 | } | ||
222 | 237 | | |||
223 | QUrl GravatarResolvUrlJob::createUrl(bool useLibravatar) | 238 | QUrl GravatarResolvUrlJob::createUrl(bool useLibravatar) | ||
224 | { | 239 | { | ||
225 | QUrl url; | 240 | QUrl url; | ||
226 | d->mCalculatedHash.clear(); | 241 | d->mCalculatedHash = Hash(); | ||
227 | if (!canStart()) { | 242 | if (!canStart()) { | ||
228 | return url; | 243 | return url; | ||
229 | } | 244 | } | ||
230 | QUrlQuery query; | 245 | QUrlQuery query; | ||
231 | if (!d->mUseDefaultPixmap) { | 246 | if (!d->mUseDefaultPixmap) { | ||
232 | //Add ?d=404 | 247 | //Add ?d=404 | ||
233 | query.addQueryItem(QStringLiteral("d"), QStringLiteral("404")); | 248 | query.addQueryItem(QStringLiteral("d"), QStringLiteral("404")); | ||
234 | } | 249 | } | ||
235 | if (d->mSize != 80) { | 250 | if (d->mSize != 80) { | ||
236 | query.addQueryItem(QStringLiteral("s"), QString::number(d->mSize)); | 251 | query.addQueryItem(QStringLiteral("s"), QString::number(d->mSize)); | ||
237 | } | 252 | } | ||
238 | url.setScheme(QStringLiteral("https")); | 253 | url.setScheme(QStringLiteral("https")); | ||
239 | if (useLibravatar) { | 254 | if (useLibravatar) { | ||
240 | url.setHost(QStringLiteral("seccdn.libravatar.org")); | 255 | url.setHost(QStringLiteral("seccdn.libravatar.org")); | ||
241 | } else { | 256 | } else { | ||
242 | url.setHost(QStringLiteral("secure.gravatar.com")); | 257 | url.setHost(QStringLiteral("secure.gravatar.com")); | ||
243 | } | 258 | } | ||
244 | url.setPort(443); | 259 | url.setPort(443); | ||
245 | d->mCalculatedHash = calculateHash(useLibravatar); | 260 | d->mCalculatedHash = calculateHash(useLibravatar); | ||
246 | url.setPath(QLatin1String("/avatar/") + d->mCalculatedHash); | 261 | url.setPath(QLatin1String("/avatar/") + d->mCalculatedHash.hexString()); | ||
247 | url.setQuery(query); | 262 | url.setQuery(query); | ||
248 | return url; | 263 | return url; | ||
249 | } | 264 | } | ||
250 | 265 | | |||
251 | bool GravatarResolvUrlJob::cacheLookup(const QString &hash) | 266 | bool GravatarResolvUrlJob::cacheLookup(const Hash &hash) | ||
252 | { | 267 | { | ||
253 | bool haveStoredPixmap = false; | 268 | bool haveStoredPixmap = false; | ||
254 | const QPixmap pix = GravatarCache::self()->loadGravatarPixmap(hash, haveStoredPixmap); | 269 | const QPixmap pix = GravatarCache::self()->loadGravatarPixmap(hash, haveStoredPixmap); | ||
255 | if (haveStoredPixmap && !pix.isNull()) { | 270 | if (haveStoredPixmap && !pix.isNull()) { // we know a Gravatar for this hash | ||
256 | d->mPixmap = pix; | 271 | d->mPixmap = pix; | ||
257 | d->mHasGravatar = true; | 272 | d->mHasGravatar = true; | ||
258 | Q_EMIT finished(this); | 273 | Q_EMIT finished(this); | ||
259 | deleteLater(); | 274 | deleteLater(); | ||
260 | return true; | 275 | return true; | ||
261 | } | 276 | } | ||
262 | return false; | 277 | return haveStoredPixmap; | ||
263 | } | 278 | } |