1/*
2 * Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15
16#ifndef SERVERCONNECTION_H
17#define SERVERCONNECTION_H
18
19#include <QByteArray>
20#include <QUrl>
21#include <QNetworkCookie>
22#include <QNetworkRequest>
23#include <QSslSocket>
24#include <QSslCertificate>
25#include <QSslConfiguration>
26#include <QSslCipher>
27#include <QSslError>
28#include <QSharedPointer>
29
30#ifndef TOKEN_AUTH_ONLY
31#include <QPixmap>
32#endif
33
34#include "common/utility.h"
35#include <memory>
36#include "capabilities.h"
37
38class QSettings;
39class QNetworkReply;
40class QUrl;
41class QNetworkAccessManager;
42
43namespace OCC {
44
45class AbstractCredentials;
46class Account;
47typedef QSharedPointer<Account> AccountPtr;
48class QuotaInfo;
49class AccessManager;
50class SimpleNetworkJob;
51
52
53/**
54 * @brief Reimplement this to handle SSL errors from libsync
55 * @ingroup libsync
56 */
57class AbstractSslErrorHandler
58{
59public:
60 virtual ~AbstractSslErrorHandler() {}
61 virtual bool handleErrors(QList<QSslError>, const QSslConfiguration &conf, QList<QSslCertificate> *, AccountPtr) = 0;
62};
63
64/**
65 * @brief The Account class represents an account on an ownCloud Server
66 * @ingroup libsync
67 *
68 * The Account has a name and url. It also has information about credentials,
69 * SSL errors and certificates.
70 */
71class OWNCLOUDSYNC_EXPORT Account : public QObject
72{
73 Q_OBJECT
74public:
75 static AccountPtr create();
76 ~Account();
77
78 AccountPtr sharedFromThis();
79
80 /**
81 * The user that can be used in dav url.
82 *
83 * This can very well be different frome the login user that's
84 * stored in credentials()->user().
85 */
86 QString davUser() const;
87 void setDavUser(const QString &newDavUser);
88
89 QString davDisplayName() const;
90 void setDavDisplayName(const QString &newDisplayName);
91
92#ifndef TOKEN_AUTH_ONLY
93 QImage avatar() const;
94 void setAvatar(const QImage &img);
95#endif
96
97 /// The name of the account as shown in the toolbar
98 QString displayName() const;
99
100 /// The internal id of the account.
101 QString id() const;
102
103 /** Server url of the account */
104 void setUrl(const QUrl &url);
105 QUrl url() const { return _url; }
106
107 /// Adjusts _userVisibleUrl once the host to use is discovered.
108 void setUserVisibleHost(const QString &host);
109
110 /**
111 * @brief The possibly themed dav path for the account. It has
112 * a trailing slash.
113 * @returns the (themeable) dav path for the account.
114 */
115 QString davPath() const;
116 void setDavPath(const QString &s) { _davPath = s; }
117 void setNonShib(bool nonShib);
118
119 /** Returns webdav entry URL, based on url() */
120 QUrl davUrl() const;
121
122 /** Returns the legacy permalink url for a file.
123 *
124 * This uses the old way of manually building the url. New code should
125 * use the "privatelink" property accessible via PROPFIND.
126 */
127 QUrl deprecatedPrivateLinkUrl(const QByteArray &numericFileId) const;
128
129 /** Holds the accounts credentials */
130 AbstractCredentials *credentials() const;
131 void setCredentials(AbstractCredentials *cred);
132
133 /** Create a network request on the account's QNAM.
134 *
135 * Network requests in AbstractNetworkJobs are created through
136 * this function. Other places should prefer to use jobs or
137 * sendRequest().
138 */
139 QNetworkReply *sendRawRequest(const QByteArray &verb,
140 const QUrl &url,
141 QNetworkRequest req = QNetworkRequest(),
142 QIODevice *data = 0);
143
144 /** Create and start network job for a simple one-off request.
145 *
146 * More complicated requests typically create their own job types.
147 */
148 SimpleNetworkJob *sendRequest(const QByteArray &verb,
149 const QUrl &url,
150 QNetworkRequest req = QNetworkRequest(),
151 QIODevice *data = 0);
152
153 /** The ssl configuration during the first connection */
154 QSslConfiguration getOrCreateSslConfig();
155 QSslConfiguration sslConfiguration() const { return _sslConfiguration; }
156 void setSslConfiguration(const QSslConfiguration &config);
157 // Because of bugs in Qt, we use this to store info needed for the SSL Button
158 QSslCipher _sessionCipher;
159 QByteArray _sessionTicket;
160 QList<QSslCertificate> _peerCertificateChain;
161
162
163 /** The certificates of the account */
164 QList<QSslCertificate> approvedCerts() const { return _approvedCerts; }
165 void setApprovedCerts(const QList<QSslCertificate> certs);
166 void addApprovedCerts(const QList<QSslCertificate> certs);
167
168 // Usually when a user explicitly rejects a certificate we don't
169 // ask again. After this call, a dialog will again be shown when
170 // the next unknown certificate is encountered.
171 void resetRejectedCertificates();
172
173 // pluggable handler
174 void setSslErrorHandler(AbstractSslErrorHandler *handler);
175
176 // To be called by credentials only, for storing username and the like
177 QVariant credentialSetting(const QString &key) const;
178 void setCredentialSetting(const QString &key, const QVariant &value);
179
180 /** Assign a client certificate */
181 void setCertificate(const QByteArray certficate = QByteArray(), const QString privateKey = QString());
182
183 /** Access the server capabilities */
184 const Capabilities &capabilities() const;
185 void setCapabilities(const QVariantMap &caps);
186
187 /** Access the server version
188 *
189 * For servers >= 10.0.0, this can be the empty string until capabilities
190 * have been received.
191 */
192 QString serverVersion() const;
193
194 /** Server version for easy comparison.
195 *
196 * Example: serverVersionInt() >= makeServerVersion(11, 2, 3)
197 *
198 * Will be 0 if the version is not available yet.
199 */
200 int serverVersionInt() const;
201
202 static int makeServerVersion(int majorVersion, int minorVersion, int patchVersion);
203 void setServerVersion(const QString &version);
204
205 /** Whether the server is too old.
206 *
207 * Not supporting server versions is a gradual process. There's a hard
208 * compatibility limit (see ConnectionValidator) that forbids connecting
209 * to extremely old servers. And there's a weak "untested, not
210 * recommended, potentially dangerous" limit, that users might want
211 * to go beyond.
212 *
213 * This function returns true if the server is beyond the weak limit.
214 */
215 bool serverVersionUnsupported() const;
216
217 // Fixed from 8.1 https://github.com/owncloud/client/issues/3730
218 /** Detects a specific bug in older server versions */
219 bool rootEtagChangesNotOnlySubFolderEtags();
220
221 /** True when the server connection is using HTTP2 */
222 bool isHttp2Supported() { return _http2Supported; }
223 void setHttp2Supported(bool value) { _http2Supported = value; }
224
225 void clearCookieJar();
226 void lendCookieJarTo(QNetworkAccessManager *guest);
227 QString cookieJarPath();
228
229 void resetNetworkAccessManager();
230 QNetworkAccessManager *networkAccessManager();
231 QSharedPointer<QNetworkAccessManager> sharedNetworkAccessManager();
232
233 /// Called by network jobs on credential errors, emits invalidCredentials()
234 void handleInvalidCredentials();
235
236public slots:
237 /// Used when forgetting credentials
238 void clearQNAMCache();
239 void slotHandleSslErrors(QNetworkReply *, QList<QSslError>);
240
241signals:
242 /// Emitted whenever there's network activity
243 void propagatorNetworkActivity();
244
245 /// Triggered by handleInvalidCredentials()
246 void invalidCredentials();
247
248 void credentialsFetched(AbstractCredentials *credentials);
249 void credentialsAsked(AbstractCredentials *credentials);
250
251 /// Forwards from QNetworkAccessManager::proxyAuthenticationRequired().
252 void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *);
253
254 // e.g. when the approved SSL certificates changed
255 void wantsAccountSaved(Account *acc);
256
257 void serverVersionChanged(Account *account, const QString &newVersion, const QString &oldVersion);
258
259 void accountChangedAvatar();
260 void accountChangedDisplayName();
261
262protected Q_SLOTS:
263 void slotCredentialsFetched();
264 void slotCredentialsAsked();
265
266private:
267 Account(QObject *parent = 0);
268 void setSharedThis(AccountPtr sharedThis);
269
270 QWeakPointer<Account> _sharedThis;
271 QString _id;
272 QString _davUser;
273 QString _displayName;
274#ifndef TOKEN_AUTH_ONLY
275 QImage _avatarImg;
276#endif
277 QMap<QString, QVariant> _settingsMap;
278 QUrl _url;
279
280 /** If url to use for any user-visible urls.
281 *
282 * If the server configures overwritehost this can be different from
283 * the connection url in _url. We retrieve the visible host through
284 * the ocs/v1.php/config endpoint in ConnectionValidator.
285 */
286 QUrl _userVisibleUrl;
287
288 QList<QSslCertificate> _approvedCerts;
289 QSslConfiguration _sslConfiguration;
290 Capabilities _capabilities;
291 QString _serverVersion;
292 QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
293 QuotaInfo *_quotaInfo;
294 QSharedPointer<QNetworkAccessManager> _am;
295 QScopedPointer<AbstractCredentials> _credentials;
296 bool _http2Supported = false;
297
298 /// Certificates that were explicitly rejected by the user
299 QList<QSslCertificate> _rejectedCertificates;
300
301 static QString _configFileName;
302
303 QString _davPath; // defaults to value from theme, might be overwritten in brandings
304 friend class AccountManager;
305};
306}
307
308Q_DECLARE_METATYPE(OCC::AccountPtr)
309
310#endif //SERVERCONNECTION_H
311