1/*
2 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
3 * Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16#ifndef NETWORKJOBS_H
17#define NETWORKJOBS_H
18
19#include "abstractnetworkjob.h"
20#include <QUrlQuery>
21#include <functional>
22
23class QUrl;
24class QJsonObject;
25
26namespace OCC {
27
28/**
29 * @brief The EntityExistsJob class
30 * @ingroup libsync
31 */
32class OWNCLOUDSYNC_EXPORT EntityExistsJob : public AbstractNetworkJob
33{
34 Q_OBJECT
35public:
36 explicit EntityExistsJob(AccountPtr account, const QString &path, QObject *parent = 0);
37 void start() Q_DECL_OVERRIDE;
38
39signals:
40 void exists(QNetworkReply *);
41
42private slots:
43 virtual bool finished() Q_DECL_OVERRIDE;
44};
45
46/**
47 * @brief The LsColJob class
48 * @ingroup libsync
49 */
50class OWNCLOUDSYNC_EXPORT LsColXMLParser : public QObject
51{
52 Q_OBJECT
53public:
54 explicit LsColXMLParser();
55
56 bool parse(const QByteArray &xml, QHash<QString, qint64> *sizes, const QString &expectedPath);
57
58signals:
59 void directoryListingSubfolders(const QStringList &items);
60 void directoryListingIterated(const QString &name, const QMap<QString, QString> &properties);
61 void finishedWithError(QNetworkReply *reply);
62 void finishedWithoutError();
63};
64
65class OWNCLOUDSYNC_EXPORT LsColJob : public AbstractNetworkJob
66{
67 Q_OBJECT
68public:
69 explicit LsColJob(AccountPtr account, const QString &path, QObject *parent = 0);
70 explicit LsColJob(AccountPtr account, const QUrl &url, QObject *parent = 0);
71 void start() Q_DECL_OVERRIDE;
72 QHash<QString, qint64> _sizes;
73
74 /**
75 * Used to specify which properties shall be retrieved.
76 *
77 * The properties can
78 * - contain no colon: they refer to a property in the DAV: namespace
79 * - contain a colon: and thus specify an explicit namespace,
80 * e.g. "ns:with:colons:bar", which is "bar" in the "ns:with:colons" namespace
81 */
82 void setProperties(QList<QByteArray> properties);
83 QList<QByteArray> properties() const;
84
85signals:
86 void directoryListingSubfolders(const QStringList &items);
87 void directoryListingIterated(const QString &name, const QMap<QString, QString> &properties);
88 void finishedWithError(QNetworkReply *reply);
89 void finishedWithoutError();
90
91private slots:
92 virtual bool finished() Q_DECL_OVERRIDE;
93
94private:
95 QList<QByteArray> _properties;
96 QUrl _url; // Used instead of path() if the url is specified in the constructor
97};
98
99/**
100 * @brief The PropfindJob class
101 *
102 * Setting the desired properties with setProperties() is mandatory.
103 *
104 * Note that this job is only for querying one item.
105 * There is also the LsColJob which can be used to list collections
106 *
107 * @ingroup libsync
108 */
109class OWNCLOUDSYNC_EXPORT PropfindJob : public AbstractNetworkJob
110{
111 Q_OBJECT
112public:
113 explicit PropfindJob(AccountPtr account, const QString &path, QObject *parent = 0);
114 void start() Q_DECL_OVERRIDE;
115
116 /**
117 * Used to specify which properties shall be retrieved.
118 *
119 * The properties can
120 * - contain no colon: they refer to a property in the DAV: namespace
121 * - contain a colon: and thus specify an explicit namespace,
122 * e.g. "ns:with:colons:bar", which is "bar" in the "ns:with:colons" namespace
123 */
124 void setProperties(QList<QByteArray> properties);
125 QList<QByteArray> properties() const;
126
127signals:
128 void result(const QVariantMap &values);
129 void finishedWithError(QNetworkReply *reply = 0);
130
131private slots:
132 virtual bool finished() Q_DECL_OVERRIDE;
133
134private:
135 QList<QByteArray> _properties;
136};
137
138#ifndef TOKEN_AUTH_ONLY
139/**
140 * @brief Retrieves the account users avatar from the server using a GET request.
141 *
142 * If the server does not have the avatar, the result Pixmap is empty.
143 *
144 * @ingroup libsync
145 */
146class OWNCLOUDSYNC_EXPORT AvatarJob : public AbstractNetworkJob
147{
148 Q_OBJECT
149public:
150 /**
151 * @param userId The user for which to obtain the avatar
152 * @param size The size of the avatar (square so size*size)
153 */
154 explicit AvatarJob(AccountPtr account, const QString &userId, int size, QObject *parent = 0);
155
156 void start() Q_DECL_OVERRIDE;
157
158 /** The retrieved avatar images don't have the circle shape by default */
159 static QImage makeCircularAvatar(const QImage &baseAvatar);
160
161signals:
162 /**
163 * @brief avatarPixmap - returns either a valid pixmap or not.
164 */
165
166 void avatarPixmap(const QImage &);
167
168private slots:
169 virtual bool finished() Q_DECL_OVERRIDE;
170
171private:
172 QUrl _avatarUrl;
173};
174#endif
175
176/**
177 * @brief Send a Proppatch request
178 *
179 * Setting the desired properties with setProperties() is mandatory.
180 *
181 * WARNING: Untested!
182 *
183 * @ingroup libsync
184 */
185class OWNCLOUDSYNC_EXPORT ProppatchJob : public AbstractNetworkJob
186{
187 Q_OBJECT
188public:
189 explicit ProppatchJob(AccountPtr account, const QString &path, QObject *parent = 0);
190 void start() Q_DECL_OVERRIDE;
191
192 /**
193 * Used to specify which properties shall be set.
194 *
195 * The property keys can
196 * - contain no colon: they refer to a property in the DAV: namespace
197 * - contain a colon: and thus specify an explicit namespace,
198 * e.g. "ns:with:colons:bar", which is "bar" in the "ns:with:colons" namespace
199 */
200 void setProperties(QMap<QByteArray, QByteArray> properties);
201 QMap<QByteArray, QByteArray> properties() const;
202
203signals:
204 void success();
205 void finishedWithError();
206
207private slots:
208 virtual bool finished() Q_DECL_OVERRIDE;
209
210private:
211 QMap<QByteArray, QByteArray> _properties;
212};
213
214/**
215 * @brief The MkColJob class
216 * @ingroup libsync
217 */
218class OWNCLOUDSYNC_EXPORT MkColJob : public AbstractNetworkJob
219{
220 Q_OBJECT
221 QUrl _url; // Only used if the constructor taking a url is taken.
222 QMap<QByteArray, QByteArray> _extraHeaders;
223
224public:
225 explicit MkColJob(AccountPtr account, const QString &path, QObject *parent = 0);
226 explicit MkColJob(AccountPtr account, const QUrl &url,
227 const QMap<QByteArray, QByteArray> &extraHeaders, QObject *parent = 0);
228 void start() Q_DECL_OVERRIDE;
229
230signals:
231 void finished(QNetworkReply::NetworkError);
232
233private slots:
234 virtual bool finished() Q_DECL_OVERRIDE;
235};
236
237/**
238 * @brief The CheckServerJob class
239 * @ingroup libsync
240 */
241class OWNCLOUDSYNC_EXPORT CheckServerJob : public AbstractNetworkJob
242{
243 Q_OBJECT
244public:
245 explicit CheckServerJob(AccountPtr account, QObject *parent = 0);
246 void start() Q_DECL_OVERRIDE;
247
248 static QString version(const QJsonObject &info);
249 static QString versionString(const QJsonObject &info);
250 static bool installed(const QJsonObject &info);
251
252signals:
253 /** Emitted when a status.php was successfully read.
254 *
255 * \a url see _serverStatusUrl (does not include "/status.php")
256 * \a info The status.php reply information
257 */
258 void instanceFound(const QUrl &url, const QJsonObject &info);
259
260 /** Emitted on invalid status.php reply.
261 *
262 * \a reply is never null
263 */
264 void instanceNotFound(QNetworkReply *reply);
265
266 /** A timeout occurred.
267 *
268 * \a url The specific url where the timeout happened.
269 */
270 void timeout(const QUrl &url);
271
272private:
273 bool finished() Q_DECL_OVERRIDE;
274 void onTimedOut() Q_DECL_OVERRIDE;
275private slots:
276 virtual void metaDataChangedSlot();
277 virtual void encryptedSlot();
278 void slotRedirected(QNetworkReply *reply, const QUrl &targetUrl, int redirectCount);
279
280private:
281 bool _subdirFallback;
282
283 /** The permanent-redirect adjusted account url.
284 *
285 * Note that temporary redirects or a permanent redirect behind a temporary
286 * one do not affect this url.
287 */
288 QUrl _serverUrl;
289
290 /** Keep track of how many permanent redirect were applied. */
291 int _permanentRedirects;
292};
293
294
295/**
296 * @brief The RequestEtagJob class
297 */
298class OWNCLOUDSYNC_EXPORT RequestEtagJob : public AbstractNetworkJob
299{
300 Q_OBJECT
301public:
302 explicit RequestEtagJob(AccountPtr account, const QString &path, QObject *parent = 0);
303 void start() Q_DECL_OVERRIDE;
304
305signals:
306 void etagRetreived(const QString &etag);
307
308private slots:
309 virtual bool finished() Q_DECL_OVERRIDE;
310};
311
312/**
313 * @brief Job to check an API that return JSON
314 *
315 * Note! you need to be in the connected state before calling this because of a server bug:
316 * https://github.com/owncloud/core/issues/12930
317 *
318 * To be used like this:
319 * \code
320 * _job = new JsonApiJob(account, QLatin1String("ocs/v1.php/foo/bar"), this);
321 * connect(job, SIGNAL(jsonReceived(QJsonDocument)), ...)
322 * The received QVariantMap is null in case of error
323 * \encode
324 *
325 * @ingroup libsync
326 */
327class OWNCLOUDSYNC_EXPORT JsonApiJob : public AbstractNetworkJob
328{
329 Q_OBJECT
330public:
331 explicit JsonApiJob(const AccountPtr &account, const QString &path, QObject *parent = 0);
332
333 /**
334 * @brief addQueryParams - add more parameters to the ocs call
335 * @param params: list pairs of strings containing the parameter name and the value.
336 *
337 * All parameters from the passed list are appended to the query. Note
338 * that the format=json parameter is added automatically and does not
339 * need to be set this way.
340 *
341 * This function needs to be called before start() obviously.
342 */
343 void addQueryParams(const QUrlQuery &params);
344
345public slots:
346 void start() Q_DECL_OVERRIDE;
347
348protected:
349 bool finished() Q_DECL_OVERRIDE;
350signals:
351
352 /**
353 * @brief jsonReceived - signal to report the json answer from ocs
354 * @param json - the parsed json document
355 * @param statusCode - the OCS status code: 100 (!) for success
356 */
357 void jsonReceived(const QJsonDocument &json, int statusCode);
358
359private:
360 QUrlQuery _additionalParams;
361};
362
363/**
364 * @brief Checks with auth type to use for a server
365 * @ingroup libsync
366 */
367class OWNCLOUDSYNC_EXPORT DetermineAuthTypeJob : public QObject
368{
369 Q_OBJECT
370public:
371 enum AuthType {
372 Basic, // also the catch-all fallback for backwards compatibility reasons
373 OAuth,
374 Shibboleth
375 };
376
377 explicit DetermineAuthTypeJob(AccountPtr account, QObject *parent = 0);
378 void start();
379signals:
380 void authType(AuthType);
381
382private:
383 void checkBothDone();
384
385 AccountPtr _account;
386 AuthType _resultGet = Basic;
387 AuthType _resultPropfind = Basic;
388 bool _getDone = false;
389 bool _propfindDone = false;
390};
391
392/**
393 * @brief A basic job around a network request without extra funtionality
394 * @ingroup libsync
395 *
396 * Primarily adds timeout and redirection handling.
397 */
398class OWNCLOUDSYNC_EXPORT SimpleNetworkJob : public AbstractNetworkJob
399{
400 Q_OBJECT
401public:
402 explicit SimpleNetworkJob(AccountPtr account, QObject *parent = 0);
403
404 QNetworkReply *startRequest(const QByteArray &verb, const QUrl &url,
405 QNetworkRequest req = QNetworkRequest(),
406 QIODevice *requestBody = 0);
407
408signals:
409 void finishedSignal(QNetworkReply *reply);
410private slots:
411 bool finished() Q_DECL_OVERRIDE;
412};
413
414/**
415 * @brief Runs a PROPFIND to figure out the private link url
416 *
417 * The numericFileId is used only to build the deprecatedPrivateLinkUrl
418 * locally as a fallback. If it's empty and the PROPFIND fails, targetFun
419 * will be called with an empty string.
420 *
421 * The job and signal connections are parented to the target QObject.
422 *
423 * Note: targetFun is guaranteed to be called only through the event
424 * loop and never directly.
425 */
426void OWNCLOUDSYNC_EXPORT fetchPrivateLinkUrl(
427 AccountPtr account, const QString &remotePath,
428 const QByteArray &numericFileId, QObject *target,
429 std::function<void(const QString &url)> targetFun);
430
431} // namespace OCC
432
433#endif // NETWORKJOBS_H
434