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 | |
38 | class QSettings; |
39 | class QNetworkReply; |
40 | class QUrl; |
41 | class QNetworkAccessManager; |
42 | |
43 | namespace OCC { |
44 | |
45 | class AbstractCredentials; |
46 | class Account; |
47 | typedef QSharedPointer<Account> AccountPtr; |
48 | class QuotaInfo; |
49 | class AccessManager; |
50 | class SimpleNetworkJob; |
51 | |
52 | |
53 | /** |
54 | * @brief Reimplement this to handle SSL errors from libsync |
55 | * @ingroup libsync |
56 | */ |
57 | class AbstractSslErrorHandler |
58 | { |
59 | public: |
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 | */ |
71 | class OWNCLOUDSYNC_EXPORT Account : public QObject |
72 | { |
73 | Q_OBJECT |
74 | public: |
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 | |
236 | public slots: |
237 | /// Used when forgetting credentials |
238 | void clearQNAMCache(); |
239 | void slotHandleSslErrors(QNetworkReply *, QList<QSslError>); |
240 | |
241 | signals: |
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 | |
262 | protected Q_SLOTS: |
263 | void slotCredentialsFetched(); |
264 | void slotCredentialsAsked(); |
265 | |
266 | private: |
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 | |
308 | Q_DECLARE_METATYPE(OCC::AccountPtr) |
309 | |
310 | #endif //SERVERCONNECTION_H |
311 | |