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