1 /*
2  *  Kaidan - A user-friendly XMPP client for every device!
3  *
4  *  Copyright (C) 2016-2021 Kaidan developers and contributors
5  *  (see the LICENSE file for a full list of copyright authors)
6  *
7  *  Kaidan is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  In addition, as a special exception, the author of Kaidan gives
13  *  permission to link the code of its release with the OpenSSL
14  *  project's "OpenSSL" library (or with modified versions of it that
15  *  use the same license as the "OpenSSL" library), and distribute the
16  *  linked executables. You must obey the GNU General Public License in
17  *  all respects for all of the code used other than "OpenSSL". If you
18  *  modify this file, you may extend this exception to your version of
19  *  the file, but you are not obligated to do so.  If you do not wish to
20  *  do so, delete this exception statement from your version.
21  *
22  *  Kaidan is distributed in the hope that it will be useful,
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  *  GNU General Public License for more details.
26  *
27  *  You should have received a copy of the GNU General Public License
28  *  along with Kaidan.  If not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 #pragma once
32 
33 // Qt
34 // QXmpp
35 #include <QXmppClient.h>
36 // Kaidan
37 #include "Enums.h"
38 
39 class AccountManager;
40 class AvatarFileStorage;
41 class DiscoveryManager;
42 class DownloadManager;
43 class LogHandler;
44 class MessageHandler;
45 class MessageModel;
46 class PresenceCache;
47 class RegistrationManager;
48 class RosterManager;
49 class RosterModel;
50 class ServerFeaturesCache;
51 class TransferCache;
52 class UploadManager;
53 class VCardCache;
54 class VCardManager;
55 class VersionManager;
56 class QSettings;
57 
58 /**
59  * The ClientWorker is used as a QObject-based worker on the ClientThread.
60  */
61 class ClientWorker : public QObject
62 {
63 	Q_OBJECT
64 
65 	Q_PROPERTY(RegistrationManager* registrationManager READ registrationManager CONSTANT)
66 	Q_PROPERTY(VCardManager* vCardManager READ vCardManager CONSTANT)
67 	Q_PROPERTY(RosterManager* rosterManager READ rosterManager CONSTANT)
68 	Q_PROPERTY(MessageHandler* messageHandler READ messageHandler CONSTANT)
69 	Q_PROPERTY(DiscoveryManager* discoveryManager READ discoveryManager CONSTANT)
70 	Q_PROPERTY(UploadManager* uploadManager READ uploadManager CONSTANT)
71 	Q_PROPERTY(DownloadManager* downloadManager READ downloadManager CONSTANT)
72 	Q_PROPERTY(VersionManager* versionManager READ versionManager CONSTANT)
73 
74 public:
75 	/**
76 	 * enumeration of possible connection errors
77 	 */
78 	enum ConnectionError {
79 		NoError,
80 		AuthenticationFailed,
81 		NotConnected,
82 		TlsFailed,
83 		TlsNotAvailable,
84 		DnsError,
85 		ConnectionRefused,
86 		NoSupportedAuth,
87 		KeepAliveError,
88 		NoNetworkPermission,
89 		RegistrationUnsupported
90 	};
91 	Q_ENUM(ConnectionError)
92 
93 	struct Caches {
94 		Caches(QObject *parent = nullptr);
95 		~Caches();
96 
97 		QSettings *settings;
98 		VCardCache *vCardCache;
99 		AccountManager *accountManager;
100 		MessageModel *msgModel;
101 		RosterModel *rosterModel;
102 		AvatarFileStorage *avatarStorage;
103 		ServerFeaturesCache *serverFeaturesCache;
104 		PresenceCache *presCache;
105 		TransferCache* transferCache;
106 	};
107 
108 	/**
109 	 * @param caches All caches running in the main thread for communication with the UI.
110 	 * @param enableLogging If logging of the XMPP stream should be done.
111 	 * @param parent Optional QObject-based parent.
112 	 */
113 	ClientWorker(Caches *caches, bool enableLogging, QObject *parent = nullptr);
114 
115 	/**
116 	 * Initializes this client worker as soon as it runs in a separate thread.
117 	 */
118 	void initialize();
119 
registrationManager()120 	RegistrationManager *registrationManager() const
121 	{
122 		return m_registrationManager;
123 	}
124 
vCardManager()125 	VCardManager *vCardManager() const
126 	{
127 		return m_vCardManager;
128 	}
129 
rosterManager()130 	RosterManager *rosterManager() const
131 	{
132 		return m_rosterManager;
133 	}
134 
messageHandler()135 	MessageHandler *messageHandler() const
136 	{
137 		return m_messageHandler;
138 	}
139 
discoveryManager()140 	DiscoveryManager *discoveryManager() const
141 	{
142 		return m_discoveryManager;
143 	}
144 
uploadManager()145 	UploadManager *uploadManager() const
146 	{
147 		return m_uploadManager;
148 	}
149 
downloadManager()150 	DownloadManager *downloadManager() const
151 	{
152 		return m_downloadManager;
153 	}
154 
versionManager()155 	VersionManager *versionManager() const
156 	{
157 		return m_versionManager;
158 	}
159 
caches()160 	Caches *caches() const
161 	{
162 		return m_caches;
163 	}
164 
165 	/**
166 	 * Starts or enqueues a task which will be executed after successful login (e.g. a
167 	 * nickname change).
168 	 *
169 	 * This method is called by managers which must call "finishTask()" as soon as the
170 	 * task is completed.
171 	 *
172 	 * If the user is logged out when this method is called, a login is triggered, the
173 	 * task is started and a logout is triggered afterwards. However, if this method is
174 	 * called before a login with new credentials (e.g. during account registration), the
175 	 * task is started after the subsequent login.
176 	 *
177 	 * @param task task which is run directly if the user is logged in or enqueued to be
178 	 * run after an automatic login
179 	 */
180 	void startTask(const std::function<void ()> task);
181 
182 	/**
183 	 * Finishes a task started by "startTask()".
184 	 *
185 	 * This must be called after a possible completion of a pending task.
186 	 *
187 	 * A logout is triggered when this method is called after the second login with the
188 	 * same credentials or later. That means, a logout is not triggered after a login with
189 	 * new credentials (e.g. after a registration).
190 	 */
191 	void finishTask();
192 
193 public slots:
194 	/**
195 	 * Connects to the server and logs in with all needed configuration variables.
196 	 */
197 	void logIn();
198 
199 	/**
200 	 * Connects to the server and requests a data form for account registration.
201 	 */
202 	void connectToRegister();
203 
204 	/**
205 	 * Connects to the server with a minimal configuration.
206 	 *
207 	 * Some additional configuration variables can be set by passing a configuration.
208 	 *
209 	 * @param config configuration with additional variables for connecting to the server
210 	 * or nothing if only the minimal configuration should be used
211 	 */
212 	void connectToServer(QXmppConfiguration config = QXmppConfiguration());
213 
214 	/**
215 	 * Logs out of the server if the client is not already logged out.
216 	 *
217 	 * @param isApplicationBeingClosed true if the application will be terminated directly after logging out, false otherwise
218 	 */
219 	void logOut(bool isApplicationBeingClosed = false);
220 
221 	/**
222 	 * Deletes the account data from the client and server.
223 	 */
224 	void deleteAccountFromClientAndServer();
225 
226 	/**
227 	 * Deletes the account data from the configuration file and database.
228 	 */
229 	void deleteAccountFromClient();
230 
231 	/**
232 	 * Called when the account is deleted from the server.
233 	 */
234 	void handleAccountDeletedFromServer();
235 
236 	/**
237 	 * Called when the account could not be deleted from the server.
238 	 *
239 	 * @param error error of the failed account deletion
240 	 */
241 	void handleAccountDeletionFromServerFailed(const QXmppStanza::Error &error);
242 
243 signals:
244 	/**
245 	 * Emitted when an authenticated connection to the server is established with new
246 	 * credentials for the first time.
247 	 *
248 	 * The client will be in connected state when this is emitted.
249 	 */
250 	void loggedInWithNewCredentials();
251 
252 	/**
253 	 * Emitted when the client's connection state changed.
254 	 *
255 	 * @param connectionState new connection state
256 	 */
257 	void connectionStateChanged(Enums::ConnectionState connectionState);
258 
259 	/**
260 	 * Emitted when the client failed to connect to the server.
261 	 *
262 	 * @param error new connection error
263 	 */
264 	void connectionErrorChanged(ClientWorker::ConnectionError error);
265 
266 private slots:
267 	/**
268 	 * Called when an authenticated connection to the server is established.
269 	 */
270 	void onConnected();
271 
272 	/**
273 	 * Called when the connection to the server is closed.
274 	 */
275 	void onDisconnected();
276 
277 	/**
278 	 * Handles the change of the connection state.
279 	 *
280 	 * @param connectionState new connection state
281 	 */
282 	void onConnectionStateChanged(QXmppClient::State connectionState);
283 
284 	/**
285 	 * Handles a connection error.
286 	 *
287 	 * @param error new connection error
288 	 */
289 	void onConnectionError(QXmppClient::Error error);
290 
291 private:
292 	/**
293 	 * Starts a pending (enqueued) task (e.g. a password change) if the variable (e.g. a
294 	 * password) could not be changed on the server before because the client was not
295 	 * logged in.
296 	 *
297 	 * @return true if at least one pending task is started on the second login with the
298 	 * same credentials or later, otherwise false
299 	 */
300 	bool startPendingTasks();
301 
302 	Caches *m_caches;
303 	QXmppClient *m_client;
304 	LogHandler *m_logger;
305 	bool m_enableLogging;
306 
307 	RegistrationManager *const m_registrationManager;
308 	VCardManager *const m_vCardManager;
309 	RosterManager *const m_rosterManager;
310 	MessageHandler *const m_messageHandler;
311 	DiscoveryManager *const m_discoveryManager;
312 	UploadManager *const m_uploadManager;
313 	DownloadManager *const m_downloadManager;
314 	VersionManager *const m_versionManager;
315 
316 	QList<std::function<void ()>> m_pendingTasks;
317 	uint m_activeTasks = 0;
318 
319 	bool m_isFirstLoginAfterStart = true;
320 	bool m_isReconnecting = false;
321 	bool m_isDisconnecting = false;
322 	QXmppConfiguration m_configToBeUsedOnNextConnect;
323 
324 	// These variables are used for checking the state of an ongoing account deletion.
325 	bool m_isAccountToBeDeletedFromClient = false;
326 	bool m_isAccountToBeDeletedFromClientAndServer = false;
327 	bool m_isAccountDeletedFromServer = false;
328 	bool m_isClientConnectedBeforeAccountDeletionFromServer = true;
329 };
330