1 | /* |
2 | SPDX-License-Identifier: LGPL-2.0-or-later |
3 | SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> |
4 | SPDX-FileCopyrightText: 2019-2022 Harald Sitter <sitter@kde.org> |
5 | */ |
6 | |
7 | #ifndef WORKERBASE_H |
8 | #define WORKERBASE_H |
9 | |
10 | // lib |
11 | #include "global.h" |
12 | #include "job_base.h" // for KIO::JobFlags |
13 | #include "udsentry.h" |
14 | // Qt |
15 | #include <QByteArray> |
16 | // Std |
17 | #include <memory> |
18 | |
19 | class KConfigGroup; |
20 | class KRemoteEncoding; |
21 | |
22 | class QHostInfo; |
23 | |
24 | namespace KIO |
25 | { |
26 | class AuthInfo; |
27 | |
28 | class WorkerBasePrivate; |
29 | class WorkerResultPrivate; |
30 | |
31 | /** |
32 | * @brief The result of a worker call |
33 | * When using the Result type always mark the function Q_REQUIRED_RESULT to enforce handling of the Result. |
34 | */ |
35 | class KIOCORE_EXPORT WorkerResult |
36 | { |
37 | public: |
38 | /// Use fail() or pass(); |
39 | WorkerResult() = delete; |
40 | ~WorkerResult(); |
41 | WorkerResult(const WorkerResult &); |
42 | WorkerResult &operator=(const WorkerResult &); |
43 | WorkerResult(WorkerResult &&) noexcept; |
44 | WorkerResult &operator=(WorkerResult &&) noexcept; |
45 | |
46 | /// Whether or not the result was a success. |
47 | bool success() const; |
48 | /// The error code (or ERR_UNKNOWN) of the result. |
49 | int error() const; |
50 | /// The localized error description if applicable. |
51 | QString errorString() const; |
52 | |
53 | /// Constructs a failure results. |
54 | Q_REQUIRED_RESULT static WorkerResult fail(int _error = KIO::ERR_UNKNOWN, const QString &_errorString = QString()); |
55 | /// Constructs a success result. |
56 | Q_REQUIRED_RESULT static WorkerResult pass(); |
57 | |
58 | private: |
59 | KIOCORE_NO_EXPORT explicit WorkerResult(std::unique_ptr<WorkerResultPrivate> &&dptr); |
60 | std::unique_ptr<WorkerResultPrivate> d; |
61 | }; |
62 | |
63 | /** |
64 | * @class KIO::WorkerBase workerbase.h <KIO/WorkerBase> |
65 | * |
66 | * WorkerBase is the class to use to implement a worker - simply inherit WorkerBase in your worker. |
67 | * |
68 | * A call to foo() results in a call to slotFoo() on the other end. |
69 | * |
70 | * Note that a kioworker doesn't have a Qt event loop. When idle, it's waiting for a command |
71 | * on the socket that connects it to the application. So don't expect a kioworker to react |
72 | * to D-Bus signals for instance. KIOWorkers are short-lived anyway, so any kind of watching |
73 | * or listening for notifications should be done elsewhere, for instance in a kded module |
74 | * (see kio_desktop's desktopnotifier.cpp for an example). |
75 | * |
76 | * If a kioworker needs a Qt event loop within the implementation of one method, e.g. to |
77 | * wait for an asynchronous operation to finish, that is possible, using QEventLoop. |
78 | * |
79 | * @since 5.96 |
80 | */ |
81 | class KIOCORE_EXPORT WorkerBase |
82 | { |
83 | public: |
84 | WorkerBase(const QByteArray &protocol, const QByteArray &poolSocket, const QByteArray &appSocket); |
85 | virtual ~WorkerBase(); |
86 | |
87 | /** |
88 | * @internal |
89 | * Terminate the worker by calling the destructor and then ::exit() |
90 | */ |
91 | void exit(); |
92 | |
93 | /** |
94 | * @internal |
95 | */ |
96 | void dispatchLoop(); |
97 | |
98 | /////////// |
99 | // Message Signals to send to the job |
100 | /////////// |
101 | |
102 | /** |
103 | * Sends data in the worker to the job (i.e.\ in get). |
104 | * |
105 | * To signal end of data, simply send an empty |
106 | * QByteArray(). |
107 | * |
108 | * @param data the data read by the worker |
109 | */ |
110 | void data(const QByteArray &data); |
111 | |
112 | /** |
113 | * Asks for data from the job. |
114 | * @see readData |
115 | */ |
116 | void dataReq(); |
117 | |
118 | /** |
119 | * Used to report the status of the worker. |
120 | * @param host the worker is currently connected to. (Should be |
121 | * empty if not connected) |
122 | * @param connected Whether an actual network connection exists. |
123 | **/ |
124 | void workerStatus(const QString &host, bool connected); |
125 | |
126 | /** |
127 | * Call this from stat() to express details about an object, the |
128 | * UDSEntry customarily contains the atoms describing file name, size, |
129 | * MIME type, etc. |
130 | * @param _entry The UDSEntry containing all of the object attributes. |
131 | */ |
132 | void statEntry(const UDSEntry &_entry); |
133 | |
134 | /** |
135 | * Call this in listDir, each time you have a bunch of entries |
136 | * to report. |
137 | * @param _entry The UDSEntry containing all of the object attributes. |
138 | */ |
139 | void listEntries(const UDSEntryList &_entry); |
140 | |
141 | /** |
142 | * Call this at the beginning of put(), to give the size of the existing |
143 | * partial file, if there is one. The @p offset argument notifies the |
144 | * other job (the one that gets the data) about the offset to use. |
145 | * In this case, the boolean returns whether we can indeed resume or not |
146 | * (we can't if the protocol doing the get() doesn't support setting an offset) |
147 | */ |
148 | bool canResume(KIO::filesize_t offset); |
149 | |
150 | /** |
151 | * Call this at the beginning of get(), if the "range-start" metadata was set |
152 | * and returning byte ranges is implemented by this protocol. |
153 | */ |
154 | void canResume(); |
155 | |
156 | /////////// |
157 | // Info Signals to send to the job |
158 | /////////// |
159 | |
160 | /** |
161 | * Call this in get and copy, to give the total size |
162 | * of the file. |
163 | */ |
164 | void totalSize(KIO::filesize_t _bytes); |
165 | /** |
166 | * Call this during get and copy, once in a while, |
167 | * to give some info about the current state. |
168 | * Don't emit it in listDir, listEntries speaks for itself. |
169 | */ |
170 | void processedSize(KIO::filesize_t _bytes); |
171 | |
172 | void position(KIO::filesize_t _pos); |
173 | |
174 | void written(KIO::filesize_t _bytes); |
175 | |
176 | void truncated(KIO::filesize_t _length); |
177 | |
178 | /** |
179 | * Call this in get and copy, to give the current transfer |
180 | * speed, but only if it can't be calculated out of the size you |
181 | * passed to processedSize (in most cases you don't want to call it) |
182 | */ |
183 | void speed(unsigned long _bytes_per_second); |
184 | |
185 | /** |
186 | * Call this to signal a redirection. |
187 | * The job will take care of going to that url. |
188 | */ |
189 | void redirection(const QUrl &_url); |
190 | |
191 | /** |
192 | * Tell that we will only get an error page here. |
193 | * This means: the data you'll get isn't the data you requested, |
194 | * but an error page (usually HTML) that describes an error. |
195 | */ |
196 | void errorPage(); |
197 | |
198 | /** |
199 | * Call this in mimetype() and in get(), when you know the MIME type. |
200 | * See mimetype() about other ways to implement it. |
201 | */ |
202 | void mimeType(const QString &_type); |
203 | |
204 | /** |
205 | * Call to signal a warning, to be displayed in a dialog box. |
206 | */ |
207 | void warning(const QString &msg); |
208 | |
209 | /** |
210 | * Call to signal a message, to be displayed if the application wants to, |
211 | * for instance in a status bar. Usual examples are "connecting to host xyz", etc. |
212 | */ |
213 | void infoMessage(const QString &msg); |
214 | |
215 | /** |
216 | * Type of message box. Should be kept in sync with KMessageBox::DialogType. |
217 | */ |
218 | enum MessageBoxType { |
219 | QuestionTwoActions = 1, ///< @since 5.100 |
220 | WarningTwoActions = 2, ///< @since 5.100 |
221 | WarningContinueCancel = 3, |
222 | WarningTwoActionsCancel = 4, ///< @since 5.100 |
223 | Information = 5, |
224 | // In KMessageBox::DialogType; <unused> = 7, Error = 8, |
225 | // QuestionTwoActionsCancel = 9 |
226 | WarningContinueCancelDetailed = 10, |
227 | }; |
228 | |
229 | /** |
230 | * Button codes. Should be kept in sync with KMessageBox::ButtonCode |
231 | */ |
232 | enum ButtonCode { |
233 | Ok = 1, |
234 | Cancel = 2, |
235 | PrimaryAction = 3, ///< @since 5.100 |
236 | SecondaryAction = 4, ///< @since 5.100 |
237 | Continue = 5, |
238 | }; |
239 | |
240 | /** |
241 | * Call this to show a message box from the worker |
242 | * @param type type of message box |
243 | * @param text Message string. May contain newlines. |
244 | * @param title Message box title. |
245 | * @param primaryActionText the text for the first button. |
246 | * Ignored for @p type Information. |
247 | * @param secondaryActionText the text for the second button. |
248 | * Ignored for @p type WarningContinueCancel, WarningContinueCancelDetailed, |
249 | * Information. |
250 | * @return a button code, as defined in ButtonCode, or 0 on communication error. |
251 | */ |
252 | int messageBox(MessageBoxType type, |
253 | const QString &text, |
254 | const QString &title = QString(), |
255 | const QString &primaryActionText = QString(), |
256 | const QString &secondaryActionText = QString()); |
257 | |
258 | /** |
259 | * Call this to show a message box from the worker |
260 | * @param text Message string. May contain newlines. |
261 | * @param type type of message box |
262 | * @param title Message box title. |
263 | * @param primaryActionText the text for the first button. |
264 | * Ignored for @p type Information. |
265 | * @param secondaryActionText the text for the second button. |
266 | * Ignored for @p type WarningContinueCancel, WarningContinueCancelDetailed, |
267 | * Information. |
268 | * @param dontAskAgainName the name used to store result from 'Do not ask again' checkbox. |
269 | * @return a button code, as defined in ButtonCode, or 0 on communication error. |
270 | */ |
271 | int messageBox(const QString &text, |
272 | MessageBoxType type, |
273 | const QString &title = QString(), |
274 | const QString &primaryActionText = QString(), |
275 | const QString &secondaryActionText = QString(), |
276 | const QString &dontAskAgainName = QString()); |
277 | |
278 | int sslError(const QVariantMap &sslData); |
279 | |
280 | /** |
281 | * Sets meta-data to be send to the application before the first |
282 | * data() or finished() signal. |
283 | */ |
284 | void setMetaData(const QString &key, const QString &value); |
285 | |
286 | /** |
287 | * Queries for the existence of a certain config/meta-data entry |
288 | * send by the application to the worker. |
289 | */ |
290 | bool hasMetaData(const QString &key) const; |
291 | |
292 | /** |
293 | * Queries for config/meta-data send by the application to the worker. |
294 | */ |
295 | QString metaData(const QString &key) const; |
296 | |
297 | /** |
298 | * @internal for ForwardingWorkerBase |
299 | * Contains all metadata (but no config) sent by the application to the worker. |
300 | */ |
301 | MetaData allMetaData() const; |
302 | |
303 | /** |
304 | * Returns a map to query config/meta-data information from. |
305 | * |
306 | * The application provides the worker with all configuration information |
307 | * relevant for the current protocol and host. |
308 | * |
309 | * Use configValue() as shortcut. |
310 | */ |
311 | QMap<QString, QVariant> mapConfig() const; |
312 | |
313 | /** |
314 | * Returns a bool from the config/meta-data information. |
315 | */ |
316 | bool configValue(const QString &key, bool defaultValue) const; |
317 | |
318 | /** |
319 | * Returns an int from the config/meta-data information. |
320 | */ |
321 | int configValue(const QString &key, int defaultValue) const; |
322 | |
323 | /** |
324 | * Returns a QString from the config/meta-data information. |
325 | */ |
326 | QString configValue(const QString &key, const QString &defaultValue = QString()) const; |
327 | |
328 | /** |
329 | * Returns a configuration object to query config/meta-data information |
330 | * from. |
331 | * |
332 | * The application provides the worker with all configuration information |
333 | * relevant for the current protocol and host. |
334 | * |
335 | * @note Since 5.64 prefer to use mapConfig() or one of the configValue(...) overloads. |
336 | * @todo Find replacements for the other current usages of this method. |
337 | */ |
338 | KConfigGroup *config(); |
339 | // KF6: perhaps rename mapConfig() to config() when removing this |
340 | |
341 | /** |
342 | * Returns an object that can translate remote filenames into proper |
343 | * Unicode forms. This encoding can be set by the user. |
344 | */ |
345 | KRemoteEncoding *remoteEncoding(); |
346 | |
347 | /////////// |
348 | // Commands sent by the job, the worker has to |
349 | // override what it wants to implement |
350 | /////////// |
351 | |
352 | /** |
353 | * @brief Application connected to the worker. |
354 | * |
355 | * Called when an application has connected to the worker. Mostly only useful |
356 | * when you want to e.g. send metadata to the application once it connects. |
357 | */ |
358 | virtual void appConnectionMade(); |
359 | |
360 | /** |
361 | * Set the host |
362 | * |
363 | * Called directly by createWorker and not via the interface. |
364 | * |
365 | * This method is called whenever a change in host, port or user occurs. |
366 | */ |
367 | virtual void setHost(const QString &host, quint16 port, const QString &user, const QString &pass); |
368 | |
369 | /** |
370 | * Opens the connection (forced). |
371 | * When this function gets called the worker is operating in |
372 | * connection-oriented mode. |
373 | * When a connection gets lost while the worker operates in |
374 | * connection oriented mode, the worker should report |
375 | * ERR_CONNECTION_BROKEN instead of reconnecting. The user is |
376 | * expected to disconnect the worker in the error handler. |
377 | */ |
378 | Q_REQUIRED_RESULT virtual WorkerResult openConnection(); |
379 | |
380 | /** |
381 | * Closes the connection (forced). |
382 | * Called when the application disconnects the worker to close |
383 | * any open network connections. |
384 | * |
385 | * When the worker was operating in connection-oriented mode, |
386 | * it should reset itself to connectionless (default) mode. |
387 | */ |
388 | virtual void closeConnection(); |
389 | |
390 | /** |
391 | * get, aka read. |
392 | * @param url the full url for this request. Host, port and user of the URL |
393 | * can be assumed to be the same as in the last setHost() call. |
394 | * |
395 | * The worker should first "emit" the MIME type by calling mimeType(), |
396 | * and then "emit" the data using the data() method. |
397 | * |
398 | * The reason why we need get() to emit the MIME type is: |
399 | * when pasting a URL in krunner, or konqueror's location bar, |
400 | * we have to find out what is the MIME type of that URL. |
401 | * Rather than doing it with a call to mimetype(), then the app or part |
402 | * would have to do a second request to the same server, this is done |
403 | * like this: get() is called, and when it emits the MIME type, the job |
404 | * is put on hold and the right app or part is launched. When that app |
405 | * or part calls get(), the worker is magically reused, and the download |
406 | * can now happen. All with a single call to get() in the worker. |
407 | * This mechanism is also described in KIO::get(). |
408 | */ |
409 | Q_REQUIRED_RESULT virtual WorkerResult get(const QUrl &url); |
410 | |
411 | /** |
412 | * open. |
413 | * @param url the full url for this request. Host, port and user of the URL |
414 | * can be assumed to be the same as in the last setHost() call. |
415 | * @param mode see \ref QIODevice::OpenMode |
416 | */ |
417 | Q_REQUIRED_RESULT virtual WorkerResult open(const QUrl &url, QIODevice::OpenMode mode); |
418 | |
419 | /** |
420 | * read. |
421 | * @param size the requested amount of data to read |
422 | * @see KIO::FileJob::read() |
423 | */ |
424 | Q_REQUIRED_RESULT virtual WorkerResult read(KIO::filesize_t size); |
425 | /** |
426 | * write. |
427 | * @param data the data to write |
428 | * @see KIO::FileJob::write() |
429 | */ |
430 | Q_REQUIRED_RESULT virtual WorkerResult write(const QByteArray &data); |
431 | /** |
432 | * seek. |
433 | * @param offset the requested amount of data to read |
434 | * @see KIO::FileJob::read() |
435 | */ |
436 | Q_REQUIRED_RESULT virtual WorkerResult seek(KIO::filesize_t offset); |
437 | /** |
438 | * truncate |
439 | * @param size size to truncate the file to |
440 | * @see KIO::FileJob::truncate() |
441 | */ |
442 | Q_REQUIRED_RESULT virtual WorkerResult truncate(KIO::filesize_t size); |
443 | /** |
444 | * close. |
445 | * @see KIO::FileJob::close() |
446 | */ |
447 | Q_REQUIRED_RESULT virtual WorkerResult close(); |
448 | |
449 | /** |
450 | * put, i.e.\ write data into a file. |
451 | * |
452 | * @param url where to write the file |
453 | * @param permissions may be -1. In this case no special permission mode is set. |
454 | * @param flags We support Overwrite here. Hopefully, we're going to |
455 | * support Resume in the future, too. |
456 | * If the file indeed already exists, the worker should NOT apply the |
457 | * permissions change to it. |
458 | * The support for resuming using .part files is done by calling canResume(). |
459 | * |
460 | * IMPORTANT: Use the "modified" metadata in order to set the modification time of the file. |
461 | * |
462 | * @see canResume() |
463 | */ |
464 | Q_REQUIRED_RESULT virtual WorkerResult put(const QUrl &url, int permissions, JobFlags flags); |
465 | |
466 | /** |
467 | * Finds all details for one file or directory. |
468 | * The information returned is the same as what listDir returns, |
469 | * but only for one file or directory. |
470 | * Call statEntry() after creating the appropriate UDSEntry for this |
471 | * url. |
472 | * |
473 | * You can use the "details" metadata to optimize this method to only |
474 | * do as much work as needed by the application. |
475 | * By default details is 2 (all details wanted, including modification time, size, etc.), |
476 | * details==1 is used when deleting: we don't need all the information if it takes |
477 | * too much time, no need to follow symlinks etc. |
478 | * details==0 is used for very simple probing: we'll only get the answer |
479 | * "it's a file or a directory (or a symlink), or it doesn't exist". |
480 | */ |
481 | Q_REQUIRED_RESULT virtual WorkerResult stat(const QUrl &url); |
482 | |
483 | /** |
484 | * Finds MIME type for one file or directory. |
485 | * |
486 | * This method should either emit 'mimeType' or it |
487 | * should send a block of data big enough to be able |
488 | * to determine the MIME type. |
489 | * |
490 | * If the worker doesn't reimplement it, a get will |
491 | * be issued, i.e.\ the whole file will be downloaded before |
492 | * determining the MIME type on it - this is obviously not a |
493 | * good thing in most cases. |
494 | */ |
495 | Q_REQUIRED_RESULT virtual WorkerResult mimetype(const QUrl &url); |
496 | |
497 | /** |
498 | * Lists the contents of @p url. |
499 | * The worker should emit ERR_CANNOT_ENTER_DIRECTORY if it doesn't exist, |
500 | * if we don't have enough permissions. |
501 | * You should not list files if the path in @p url is empty, but redirect |
502 | * to a non-empty path instead. |
503 | */ |
504 | Q_REQUIRED_RESULT virtual WorkerResult listDir(const QUrl &url); |
505 | |
506 | /** |
507 | * Create a directory |
508 | * @param url path to the directory to create |
509 | * @param permissions the permissions to set after creating the directory |
510 | * (-1 if no permissions to be set) |
511 | * The worker emits ERR_CANNOT_MKDIR if failure. |
512 | */ |
513 | Q_REQUIRED_RESULT virtual WorkerResult mkdir(const QUrl &url, int permissions); |
514 | |
515 | /** |
516 | * Rename @p oldname into @p newname. |
517 | * If the worker returns an error ERR_UNSUPPORTED_ACTION, the job will |
518 | * ask for copy + del instead. |
519 | * |
520 | * Important: the worker must implement the logic "if the destination already |
521 | * exists, error ERR_DIR_ALREADY_EXIST or ERR_FILE_ALREADY_EXIST". |
522 | * For performance reasons no stat is done in the destination before hand, |
523 | * the worker must do it. |
524 | * |
525 | * By default, rename() is only called when renaming (moving) from |
526 | * yourproto://host/path to yourproto://host/otherpath. |
527 | * |
528 | * If you set renameFromFile=true then rename() will also be called when |
529 | * moving a file from file:///path to yourproto://host/otherpath. |
530 | * Otherwise such a move would have to be done the slow way (copy+delete). |
531 | * See KProtocolManager::canRenameFromFile() for more details. |
532 | * |
533 | * If you set renameToFile=true then rename() will also be called when |
534 | * moving a file from yourproto: to file:. |
535 | * See KProtocolManager::canRenameToFile() for more details. |
536 | * |
537 | * @param src where to move the file from |
538 | * @param dest where to move the file to |
539 | * @param flags We support Overwrite here |
540 | */ |
541 | Q_REQUIRED_RESULT virtual WorkerResult rename(const QUrl &src, const QUrl &dest, JobFlags flags); |
542 | |
543 | /** |
544 | * Creates a symbolic link named @p dest, pointing to @p target, which |
545 | * may be a relative or an absolute path. |
546 | * @param target The string that will become the "target" of the link (can be relative) |
547 | * @param dest The symlink to create. |
548 | * @param flags We support Overwrite here |
549 | */ |
550 | Q_REQUIRED_RESULT virtual WorkerResult symlink(const QString &target, const QUrl &dest, JobFlags flags); |
551 | |
552 | /** |
553 | * Change permissions on @p url. |
554 | * The worker emits ERR_DOES_NOT_EXIST or ERR_CANNOT_CHMOD |
555 | */ |
556 | Q_REQUIRED_RESULT virtual WorkerResult chmod(const QUrl &url, int permissions); |
557 | |
558 | /** |
559 | * Change ownership of @p url. |
560 | * The worker emits ERR_DOES_NOT_EXIST or ERR_CANNOT_CHOWN |
561 | */ |
562 | Q_REQUIRED_RESULT virtual WorkerResult chown(const QUrl &url, const QString &owner, const QString &group); |
563 | |
564 | /** |
565 | * Sets the modification time for @url. |
566 | * For instance this is what CopyJob uses to set mtime on dirs at the end of a copy. |
567 | * It could also be used to set the mtime on any file, in theory. |
568 | * The usual implementation on unix is to call utime(path, &myutimbuf). |
569 | * The worker emits ERR_DOES_NOT_EXIST or ERR_CANNOT_SETTIME |
570 | */ |
571 | Q_REQUIRED_RESULT virtual WorkerResult setModificationTime(const QUrl &url, const QDateTime &mtime); |
572 | |
573 | /** |
574 | * Copy @p src into @p dest. |
575 | * |
576 | * By default, copy() is only called when copying a file from |
577 | * yourproto://host/path to yourproto://host/otherpath. |
578 | * |
579 | * If you set copyFromFile=true then copy() will also be called when |
580 | * moving a file from file:///path to yourproto://host/otherpath. |
581 | * Otherwise such a copy would have to be done the slow way (get+put). |
582 | * See also KProtocolManager::canCopyFromFile(). |
583 | * |
584 | * If you set copyToFile=true then copy() will also be called when |
585 | * moving a file from yourproto: to file:. |
586 | * See also KProtocolManager::canCopyToFile(). |
587 | * |
588 | * If the worker returns an error ERR_UNSUPPORTED_ACTION, the job will |
589 | * ask for get + put instead. |
590 | * |
591 | * If the worker returns an error ERR_FILE_ALREADY_EXIST, the job will |
592 | * ask for a different destination filename. |
593 | * |
594 | * @param src where to copy the file from (decoded) |
595 | * @param dest where to copy the file to (decoded) |
596 | * @param permissions may be -1. In this case no special permission mode is set, |
597 | * and the owner and group permissions are not preserved. |
598 | * @param flags We support Overwrite here |
599 | * |
600 | * Don't forget to set the modification time of @p dest to be the modification time of @p src. |
601 | */ |
602 | Q_REQUIRED_RESULT virtual WorkerResult copy(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags); |
603 | |
604 | /** |
605 | * Delete a file or directory. |
606 | * @param url file/directory to delete |
607 | * @param isfile if true, a file should be deleted. |
608 | * if false, a directory should be deleted. |
609 | * |
610 | * By default, del() on a directory should FAIL if the directory is not empty. |
611 | * However, if metadata("recurse") == "true", then the worker can do a recursive deletion. |
612 | * This behavior is only invoked if the worker specifies deleteRecursive=true in its protocol file. |
613 | */ |
614 | Q_REQUIRED_RESULT virtual WorkerResult del(const QUrl &url, bool isfile); |
615 | |
616 | /** |
617 | * Used for any command that is specific to this worker (protocol). |
618 | * Examples are : HTTP POST, mount and unmount (kio_file) |
619 | * |
620 | * @param data packed data; the meaning is completely dependent on the |
621 | * worker, but usually starts with an int for the command number. |
622 | * Document your worker's commands, at least in its header file. |
623 | */ |
624 | Q_REQUIRED_RESULT virtual WorkerResult special(const QByteArray &data); |
625 | |
626 | /** |
627 | * Get a filesystem's total and available space. |
628 | * |
629 | * @param url Url to the filesystem |
630 | */ |
631 | Q_REQUIRED_RESULT virtual WorkerResult fileSystemFreeSpace(const QUrl &url); |
632 | |
633 | /** |
634 | * Called to get the status of the worker. Worker should respond |
635 | * by calling workerStatus(...) |
636 | */ |
637 | virtual void worker_status(); |
638 | |
639 | /** |
640 | * Called by the scheduler to tell the worker that the configuration |
641 | * changed (i.e.\ proxy settings) . |
642 | */ |
643 | virtual void reparseConfiguration(); |
644 | |
645 | /** |
646 | * @return timeout value for connecting to remote host. |
647 | */ |
648 | int connectTimeout(); |
649 | |
650 | /** |
651 | * @return timeout value for connecting to proxy in secs. |
652 | */ |
653 | int proxyConnectTimeout(); |
654 | |
655 | /** |
656 | * @return timeout value for read from first data from |
657 | * remote host in seconds. |
658 | */ |
659 | int responseTimeout(); |
660 | |
661 | /** |
662 | * @return timeout value for read from subsequent data from |
663 | * remote host in secs. |
664 | */ |
665 | int readTimeout(); |
666 | |
667 | /** |
668 | * This function sets a timeout of @p timeout seconds and calls |
669 | * special(data) when the timeout occurs as if it was called by the |
670 | * application. |
671 | * |
672 | * A timeout can only occur when the worker is waiting for a command |
673 | * from the application. |
674 | * |
675 | * Specifying a negative timeout cancels a pending timeout. |
676 | * |
677 | * Only one timeout at a time is supported, setting a timeout |
678 | * cancels any pending timeout. |
679 | */ |
680 | void setTimeoutSpecialCommand(int timeout, const QByteArray &data = QByteArray()); |
681 | |
682 | /** |
683 | * Read data sent by the job, after a dataReq |
684 | * |
685 | * @param buffer buffer where data is stored |
686 | * @return 0 on end of data, |
687 | * > 0 bytes read |
688 | * < 0 error |
689 | **/ |
690 | int readData(QByteArray &buffer); |
691 | |
692 | /** |
693 | * It collects entries and emits them via listEntries |
694 | * when enough of them are there or a certain time |
695 | * frame exceeded (to make sure the app gets some |
696 | * items in time but not too many items one by one |
697 | * as this will cause a drastic performance penalty). |
698 | * @param entry The UDSEntry containing all of the object attributes. |
699 | */ |
700 | void listEntry(const UDSEntry &entry); |
701 | |
702 | /** |
703 | * internal function to connect a worker to/ disconnect from |
704 | * either the worker pool or the application |
705 | */ |
706 | void connectWorker(const QString &path); |
707 | void disconnectWorker(); |
708 | |
709 | /** |
710 | * Prompt the user for Authorization info (login & password). |
711 | * |
712 | * Use this function to request authorization information from |
713 | * the end user. You can also pass an error message which explains |
714 | * why a previous authorization attempt failed. Here is a very |
715 | * simple example: |
716 | * |
717 | * \code |
718 | * KIO::AuthInfo authInfo; |
719 | * int errorCode = openPasswordDialogV2(authInfo); |
720 | * if (!errorCode) { |
721 | * qDebug() << QLatin1String("User: ") << authInfo.username; |
722 | * qDebug() << QLatin1String("Password: not displayed here!"); |
723 | * } else { |
724 | * error(errorCode, QString()); |
725 | * } |
726 | * \endcode |
727 | * |
728 | * You can also preset some values like the username, caption or |
729 | * comment as follows: |
730 | * |
731 | * \code |
732 | * KIO::AuthInfo authInfo; |
733 | * authInfo.caption = i18n("Acme Password Dialog"); |
734 | * authInfo.username = "Wile E. Coyote"; |
735 | * QString errorMsg = i18n("You entered an incorrect password."); |
736 | * int errorCode = openPasswordDialogV2(authInfo, errorMsg); |
737 | * [...] |
738 | * \endcode |
739 | * |
740 | * \note You should consider using checkCachedAuthentication() to |
741 | * see if the password is available in kpasswdserver before calling |
742 | * this function. |
743 | * |
744 | * \note A call to this function can fail and return @p false, |
745 | * if the password server could not be started for whatever reason. |
746 | * |
747 | * \note This function does not store the password information |
748 | * automatically (and has not since kdelibs 4.7). If you want to |
749 | * store the password information in a persistent storage like |
750 | * KWallet, then you MUST call @ref cacheAuthentication. |
751 | * |
752 | * @see checkCachedAuthentication |
753 | * @param info See AuthInfo. |
754 | * @param errorMsg Error message to show |
755 | * @return a KIO error code: NoError (0), KIO::USER_CANCELED, or other error codes. |
756 | */ |
757 | int openPasswordDialog(KIO::AuthInfo &info, const QString &errorMsg = QString()); |
758 | |
759 | /** |
760 | * Checks for cached authentication based on parameters |
761 | * given by @p info. |
762 | * |
763 | * Use this function to check if any cached password exists |
764 | * for the URL given by @p info. If @p AuthInfo::realmValue |
765 | * and/or @p AuthInfo::verifyPath flag is specified, then |
766 | * they will also be factored in determining the presence |
767 | * of a cached password. Note that @p Auth::url is a required |
768 | * parameter when attempting to check for cached authorization |
769 | * info. Here is a simple example: |
770 | * |
771 | * \code |
772 | * AuthInfo info; |
773 | * info.url = QUrl("https://www.foobar.org/foo/bar"); |
774 | * info.username = "somename"; |
775 | * info.verifyPath = true; |
776 | * if ( !checkCachedAuthentication( info ) ) |
777 | * { |
778 | * int errorCode = openPasswordDialogV2(info); |
779 | * .... |
780 | * } |
781 | * \endcode |
782 | * |
783 | * @param info See AuthInfo. |
784 | * @return @p true if cached Authorization is found, false otherwise. |
785 | */ |
786 | bool checkCachedAuthentication(AuthInfo &info); |
787 | |
788 | /** |
789 | * Caches @p info in a persistent storage like KWallet. |
790 | * |
791 | * Note that calling openPasswordDialogV2 does not store passwords |
792 | * automatically for you (and has not since kdelibs 4.7). |
793 | * |
794 | * Here is a simple example of how to use cacheAuthentication: |
795 | * |
796 | * \code |
797 | * AuthInfo info; |
798 | * info.url = QUrl("https://www.foobar.org/foo/bar"); |
799 | * info.username = "somename"; |
800 | * info.verifyPath = true; |
801 | * if ( !checkCachedAuthentication( info ) ) { |
802 | * int errorCode = openPasswordDialogV2(info); |
803 | * if (!errorCode) { |
804 | * if (info.keepPassword) { // user asked password be save/remembered |
805 | * cacheAuthentication(info); |
806 | * } |
807 | * } |
808 | * } |
809 | * \endcode |
810 | * |
811 | * @param info See AuthInfo. |
812 | * @return @p true if @p info was successfully cached. |
813 | */ |
814 | bool cacheAuthentication(const AuthInfo &info); |
815 | |
816 | /** |
817 | * Wait for an answer to our request, until we get @p expected1 or @p expected2 |
818 | * @return the result from readData, as well as the cmd in *pCmd if set, and the data in @p data |
819 | */ |
820 | int waitForAnswer(int expected1, int expected2, QByteArray &data, int *pCmd = nullptr); |
821 | |
822 | /** |
823 | * Internal function to transmit meta data to the application. |
824 | * m_outgoingMetaData will be cleared; this means that if the worker is for |
825 | * example put on hold and picked up by a different KIO::Job later the new |
826 | * job will not see the metadata sent before. |
827 | * See kio/DESIGN.krun for an overview of the state |
828 | * progression of a job/worker. |
829 | * @warning calling this method may seriously interfere with the operation |
830 | * of KIO which relies on the presence of some metadata at some points in time. |
831 | * You should not use it if you are not familiar with KIO and not before |
832 | * the worker is connected to the last job before returning to idle state. |
833 | */ |
834 | void sendMetaData(); |
835 | |
836 | /** |
837 | * Internal function to transmit meta data to the application. |
838 | * Like sendMetaData() but m_outgoingMetaData will not be cleared. |
839 | * This method is mainly useful in code that runs before the worker is connected |
840 | * to its final job. |
841 | */ |
842 | void sendAndKeepMetaData(); |
843 | |
844 | /** If your ioworker was killed by a signal, wasKilled() returns true. |
845 | Check it regularly in lengthy functions (e.g. in get();) and return |
846 | as fast as possible from this function if wasKilled() returns true. |
847 | This will ensure that your worker destructor will be called correctly. |
848 | */ |
849 | bool wasKilled() const; |
850 | |
851 | /** Internally used |
852 | * @internal |
853 | */ |
854 | void lookupHost(const QString &host); |
855 | |
856 | /** Internally used |
857 | * @internal |
858 | */ |
859 | int waitForHostInfo(QHostInfo &info); |
860 | |
861 | /** |
862 | * Checks with job if privilege operation is allowed. |
863 | * @return privilege operation status. |
864 | * @see PrivilegeOperationStatus |
865 | */ |
866 | PrivilegeOperationStatus requestPrivilegeOperation(const QString &operationDetails); |
867 | |
868 | /** |
869 | * Adds @p action to the list of PolicyKit actions which the |
870 | * worker is authorized to perform. |
871 | * |
872 | * @param action the PolicyKit action |
873 | */ |
874 | void addTemporaryAuthorization(const QString &action); |
875 | |
876 | /** |
877 | * @brief Set the Incoming Meta Data |
878 | * This is only really useful if your worker wants to overwrite the |
879 | * metadata for consumption in other worker functions; this overwrites |
880 | * existing metadata set by the client! |
881 | * |
882 | * @param metaData metadata to set |
883 | * @since 5.99 |
884 | */ |
885 | void setIncomingMetaData(const KIO::MetaData &metaData); |
886 | |
887 | private: |
888 | std::unique_ptr<WorkerBasePrivate> d; |
889 | Q_DISABLE_COPY_MOVE(WorkerBase) |
890 | friend class WorkerSlaveBaseBridge; |
891 | friend class WorkerThread; |
892 | }; |
893 | |
894 | } // namespace KIO |
895 | |
896 | #endif |
897 | |
898 | // HACK while SlaveBase is still around: |
899 | // Separate include/declaration guard matching the one in slavebase.h |
900 | // around the same declaration of unsupportedActionErrorString() |
901 | // Avoids consumers to need to include slavebase.h, while implementation |
902 | // is still in slavebase.cpp for dependency reasons |
903 | #ifndef KIO_UNSUPPORTEDACTIONERRORSTRING |
904 | #define KIO_UNSUPPORTEDACTIONERRORSTRING |
905 | |
906 | namespace KIO |
907 | { |
908 | |
909 | /** |
910 | * Returns an appropriate error message if the given command @p cmd |
911 | * is an unsupported action (ERR_UNSUPPORTED_ACTION). |
912 | * @param protocol name of the protocol |
913 | * @param cmd given command |
914 | * @see enum Command |
915 | */ |
916 | KIOCORE_EXPORT QString unsupportedActionErrorString(const QString &protocol, int cmd); |
917 | |
918 | } // namespace KIO |
919 | |
920 | #endif |
921 | |