| 1 | /* |
| 2 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 3 | SPDX-FileCopyrightText: 2000 Waldo Bastian <bastian@kde.org> |
| 4 | SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> |
| 5 | SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org> |
| 6 | SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org> |
| 7 | SPDX-FileCopyrightText: 2019-2022 Harald Sitter <sitter@kde.org> |
| 8 | */ |
| 9 | |
| 10 | #ifndef WORKERBASE_P_H |
| 11 | #define WORKERBASE_P_H |
| 12 | |
| 13 | #include "workerbase.h" |
| 14 | |
| 15 | #include <commands_p.h> |
| 16 | #include <slavebase.h> |
| 17 | |
| 18 | namespace KIO |
| 19 | { |
| 20 | |
| 21 | // Bridges new worker API to legacy slave API. Overrides all SlaveBase virtual functions and redirects them at the |
| 22 | // fronting WorkerBase implementation. The WorkerBase implementation then returns Result objects which we translate |
| 23 | // back to the appropriate signal calls (error, finish, opened, etc.). |
| 24 | // When starting the dispatchLoop it actually runs inside the SlaveBase, so the SlaveBase is in the driver seat |
| 25 | // until KF6 when we can fully remove the SlaveBase in favor of the WorkerBase (means moving the dispatch and |
| 26 | // dispatchLoop functions into the WorkerBase and handling the signaling in the dispatch function rather than |
| 27 | // this intermediate Bridge object). |
| 28 | class WorkerSlaveBaseBridge : public SlaveBase |
| 29 | { |
| 30 | void finalize(const WorkerResult &result) |
| 31 | { |
| 32 | if (!result.success()) { |
| 33 | error(errid: result.error(), text: result.errorString()); |
| 34 | return; |
| 35 | } |
| 36 | finished(); |
| 37 | } |
| 38 | |
| 39 | void maybeError(const WorkerResult &result) |
| 40 | { |
| 41 | if (!result.success()) { |
| 42 | error(errid: result.error(), text: result.errorString()); |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | public: |
| 47 | using SlaveBase::SlaveBase; |
| 48 | |
| 49 | void setHost(const QString &host, quint16 port, const QString &user, const QString &pass) final |
| 50 | { |
| 51 | base->setHost(host, port, user, pass); |
| 52 | } |
| 53 | |
| 54 | void openConnection() final |
| 55 | { |
| 56 | const WorkerResult result = base->openConnection(); |
| 57 | if (!result.success()) { |
| 58 | error(errid: result.error(), text: result.errorString()); |
| 59 | return; |
| 60 | } |
| 61 | connected(); |
| 62 | } |
| 63 | |
| 64 | void closeConnection() final |
| 65 | { |
| 66 | base->closeConnection(); // not allowed to error but also not finishing |
| 67 | } |
| 68 | |
| 69 | void get(const QUrl &url) final |
| 70 | { |
| 71 | finalize(result: base->get(url)); |
| 72 | } |
| 73 | |
| 74 | void open(const QUrl &url, QIODevice::OpenMode mode) final |
| 75 | { |
| 76 | const WorkerResult result = base->open(url, mode); |
| 77 | if (!result.success()) { |
| 78 | error(errid: result.error(), text: result.errorString()); |
| 79 | return; |
| 80 | } |
| 81 | opened(); |
| 82 | } |
| 83 | |
| 84 | void read(KIO::filesize_t size) final |
| 85 | { |
| 86 | maybeError(result: base->read(size)); |
| 87 | } |
| 88 | |
| 89 | void write(const QByteArray &data) final |
| 90 | { |
| 91 | maybeError(result: base->write(data)); |
| 92 | } |
| 93 | |
| 94 | void seek(KIO::filesize_t offset) final |
| 95 | { |
| 96 | maybeError(result: base->seek(offset)); |
| 97 | } |
| 98 | |
| 99 | void close() final |
| 100 | { |
| 101 | finalize(result: base->close()); |
| 102 | } |
| 103 | |
| 104 | void put(const QUrl &url, int permissions, JobFlags flags) final |
| 105 | { |
| 106 | finalize(result: base->put(url, permissions, flags)); |
| 107 | } |
| 108 | |
| 109 | void stat(const QUrl &url) final |
| 110 | { |
| 111 | finalize(result: base->stat(url)); |
| 112 | } |
| 113 | |
| 114 | void mimetype(const QUrl &url) final |
| 115 | { |
| 116 | finalize(result: base->mimetype(url)); |
| 117 | } |
| 118 | |
| 119 | void listDir(const QUrl &url) final |
| 120 | { |
| 121 | finalize(result: base->listDir(url)); |
| 122 | } |
| 123 | |
| 124 | void mkdir(const QUrl &url, int permissions) final |
| 125 | { |
| 126 | finalize(result: base->mkdir(url, permissions)); |
| 127 | } |
| 128 | |
| 129 | void rename(const QUrl &src, const QUrl &dest, JobFlags flags) final |
| 130 | { |
| 131 | finalize(result: base->rename(src, dest, flags)); |
| 132 | } |
| 133 | |
| 134 | void symlink(const QString &target, const QUrl &dest, JobFlags flags) final |
| 135 | { |
| 136 | finalize(result: base->symlink(target, dest, flags)); |
| 137 | } |
| 138 | |
| 139 | void chmod(const QUrl &url, int permissions) final |
| 140 | { |
| 141 | finalize(result: base->chmod(url, permissions)); |
| 142 | } |
| 143 | |
| 144 | void chown(const QUrl &url, const QString &owner, const QString &group) final |
| 145 | { |
| 146 | finalize(result: base->chown(url, owner, group)); |
| 147 | } |
| 148 | |
| 149 | void setModificationTime(const QUrl &url, const QDateTime &mtime) final |
| 150 | { |
| 151 | finalize(result: base->setModificationTime(url, mtime)); |
| 152 | } |
| 153 | |
| 154 | void copy(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags) final |
| 155 | { |
| 156 | finalize(result: base->copy(src, dest, permissions, flags)); |
| 157 | } |
| 158 | |
| 159 | void del(const QUrl &url, bool isfile) final |
| 160 | { |
| 161 | finalize(result: base->del(url, isfile)); |
| 162 | } |
| 163 | |
| 164 | void special(const QByteArray &data) final |
| 165 | { |
| 166 | finalize(result: base->special(data)); |
| 167 | } |
| 168 | |
| 169 | void slave_status() final |
| 170 | { |
| 171 | base->worker_status(); // this only requests an update and isn't able to error or finish whatsoever |
| 172 | } |
| 173 | |
| 174 | void reparseConfiguration() final |
| 175 | { |
| 176 | base->reparseConfiguration(); |
| 177 | SlaveBase::reparseConfiguration(); |
| 178 | } |
| 179 | |
| 180 | void setIncomingMetaData(const KIO::MetaData &metaData) |
| 181 | { |
| 182 | mIncomingMetaData = metaData; |
| 183 | } |
| 184 | |
| 185 | WorkerBase *base = nullptr; |
| 186 | |
| 187 | protected: |
| 188 | void virtual_hook(int id, void *data) override |
| 189 | { |
| 190 | switch (id) { |
| 191 | case SlaveBase::AppConnectionMade: |
| 192 | base->appConnectionMade(); |
| 193 | return; |
| 194 | case SlaveBase::GetFileSystemFreeSpace: |
| 195 | finalize(result: base->fileSystemFreeSpace(url: *static_cast<QUrl *>(data))); |
| 196 | return; |
| 197 | case SlaveBase::Truncate: |
| 198 | maybeError(result: base->truncate(size: *static_cast<KIO::filesize_t *>(data))); |
| 199 | return; |
| 200 | } |
| 201 | |
| 202 | maybeError(result: WorkerResult::fail(error: ERR_UNSUPPORTED_ACTION, errorString: unsupportedActionErrorString(protocol: protocolName(), cmd: id))); |
| 203 | } |
| 204 | }; |
| 205 | |
| 206 | class WorkerBasePrivate |
| 207 | { |
| 208 | public: |
| 209 | WorkerBasePrivate(const QByteArray &protocol, const QByteArray &poolSocket, const QByteArray &appSocket, WorkerBase *base) |
| 210 | : bridge(protocol, poolSocket, appSocket) |
| 211 | { |
| 212 | bridge.base = base; |
| 213 | } |
| 214 | |
| 215 | WorkerSlaveBaseBridge bridge; |
| 216 | |
| 217 | inline QString protocolName() const |
| 218 | { |
| 219 | return bridge.protocolName(); |
| 220 | } |
| 221 | }; |
| 222 | |
| 223 | } // namespace KIO |
| 224 | |
| 225 | #endif |
| 226 | |