Changeset View
Changeset View
Standalone View
Standalone View
src/kmailtransport/plugins/smtp/smtpjob.cpp
Show All 18 Lines | 1 | /* | |||
---|---|---|---|---|---|
19 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 19 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | 02110-1301, USA. | 20 | 02110-1301, USA. | ||
21 | */ | 21 | */ | ||
22 | 22 | | |||
23 | #include "smtpjob.h" | 23 | #include "smtpjob.h" | ||
24 | #include "transport.h" | 24 | #include "transport.h" | ||
25 | #include "mailtransport_defs.h" | 25 | #include "mailtransport_defs.h" | ||
26 | #include "precommandjob.h" | 26 | #include "precommandjob.h" | ||
27 | #include "sessionuiproxy.h" | ||||
27 | #include "mailtransportplugin_smtp_debug.h" | 28 | #include "mailtransportplugin_smtp_debug.h" | ||
28 | 29 | | |||
29 | #include <QBuffer> | 30 | #include <QBuffer> | ||
30 | #include <QHash> | 31 | #include <QHash> | ||
31 | #include <QPointer> | 32 | #include <QPointer> | ||
32 | 33 | | |||
33 | #include <KLocalizedString> | 34 | #include <KLocalizedString> | ||
34 | #include <QUrl> | 35 | #include <QUrl> | ||
35 | #include <QUrlQuery> | 36 | #include <QUrlQuery> | ||
36 | #include "mailtransport_debug.h" | 37 | #include "mailtransport_debug.h" | ||
37 | #include <KIO/Job> | | |||
38 | #include <KIO/Scheduler> | | |||
39 | #include <KPasswordDialog> | 38 | #include <KPasswordDialog> | ||
40 | 39 | | |||
40 | #include <KSMTP/Session> | ||||
41 | #include <KSMTP/LoginJob> | ||||
42 | #include <KSMTP/SendJob> | ||||
43 | | ||||
41 | using namespace MailTransport; | 44 | using namespace MailTransport; | ||
42 | 45 | | |||
43 | class SlavePool | 46 | class SessionPool | ||
44 | { | 47 | { | ||
45 | public: | 48 | public: | ||
46 | SlavePool() : ref(0) | 49 | SessionPool() : ref(0) | ||
47 | { | 50 | { | ||
48 | } | 51 | } | ||
49 | 52 | | |||
50 | int ref; | 53 | int ref; | ||
51 | QHash<int, KIO::Slave *> slaves; | 54 | QHash<int, KSmtp::Session*> sessions; | ||
52 | 55 | | |||
53 | void removeSlave(KIO::Slave *slave, bool disconnect = false) | 56 | void removeSession(KSmtp::Session *session) | ||
54 | { | 57 | { | ||
55 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "Removing slave" << slave << "from pool"; | 58 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "Removing session" << session << "from the pool"; | ||
56 | const int slaveKey = slaves.key(slave); | 59 | int key = sessions.key(session); | ||
57 | if (slaveKey > 0) { | 60 | if (key > 0) { | ||
58 | slaves.remove(slaveKey); | 61 | QObject::connect(session, &KSmtp::Session::stateChanged, | ||
59 | if (disconnect) { | 62 | [session](KSmtp::Session::State state) { | ||
60 | KIO::Scheduler::disconnectSlave(slave); | 63 | if (state == KSmtp::Session::Disconnected) { | ||
61 | } | 64 | session->deleteLater(); | ||
65 | } | ||||
66 | }); | ||||
67 | session->quit(); | ||||
68 | sessions.remove(key); | ||||
62 | } | 69 | } | ||
63 | } | 70 | } | ||
64 | }; | 71 | }; | ||
65 | 72 | | |||
66 | Q_GLOBAL_STATIC(SlavePool, s_slavePool) | 73 | Q_GLOBAL_STATIC(SessionPool, s_sessionPool) | ||
67 | 74 | | |||
68 | /** | 75 | /** | ||
69 | * Private class that helps to provide binary compatibility between releases. | 76 | * Private class that helps to provide binary compatibility between releases. | ||
70 | * @internal | 77 | * @internal | ||
71 | */ | 78 | */ | ||
72 | class SmtpJobPrivate | 79 | class SmtpJobPrivate | ||
73 | { | 80 | { | ||
74 | public: | 81 | public: | ||
75 | SmtpJobPrivate(SmtpJob *parent) : q(parent) | 82 | SmtpJobPrivate(SmtpJob *parent) : q(parent) | ||
76 | { | 83 | { | ||
77 | } | 84 | } | ||
78 | 85 | | |||
79 | SmtpJob *q; | 86 | SmtpJob *q; | ||
80 | KIO::Slave *slave; | 87 | KSmtp::Session *session; | ||
88 | KSmtp::SessionUiProxy::Ptr uiProxy; | ||||
81 | enum State { | 89 | enum State { | ||
82 | Idle, Precommand, Smtp | 90 | Idle, Precommand, Smtp | ||
83 | } currentState; | 91 | } currentState; | ||
84 | bool finished; | 92 | bool finished; | ||
85 | }; | 93 | }; | ||
86 | 94 | | |||
87 | SmtpJob::SmtpJob(Transport *transport, QObject *parent) | 95 | SmtpJob::SmtpJob(Transport *transport, QObject *parent) | ||
88 | : TransportJob(transport, parent) | 96 | : TransportJob(transport, parent) | ||
89 | , d(new SmtpJobPrivate(this)) | 97 | , d(new SmtpJobPrivate(this)) | ||
90 | { | 98 | { | ||
91 | d->currentState = SmtpJobPrivate::Idle; | 99 | d->currentState = SmtpJobPrivate::Idle; | ||
92 | d->slave = nullptr; | 100 | d->session = nullptr; | ||
93 | d->finished = false; | 101 | d->finished = false; | ||
94 | if (!s_slavePool.isDestroyed()) { | 102 | d->uiProxy = KSmtp::SessionUiProxy::Ptr(new SmtpSessionUiProxy); | ||
95 | s_slavePool->ref++; | 103 | if (!s_sessionPool.isDestroyed()) { | ||
104 | s_sessionPool->ref++; | ||||
96 | } | 105 | } | ||
97 | KIO::Scheduler::connect(SIGNAL(slaveError(KIO::Slave *,int,QString)), this, SLOT(slaveError(KIO::Slave *,int,QString))); | | |||
98 | } | 106 | } | ||
99 | 107 | | |||
100 | SmtpJob::~SmtpJob() | 108 | SmtpJob::~SmtpJob() | ||
101 | { | 109 | { | ||
102 | if (!s_slavePool.isDestroyed()) { | 110 | if (!s_sessionPool.isDestroyed()) { | ||
103 | s_slavePool->ref--; | 111 | s_sessionPool->ref--; | ||
104 | if (s_slavePool->ref == 0) { | 112 | if (s_sessionPool->ref == 0) { | ||
105 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "clearing SMTP slave pool" << s_slavePool->slaves.count(); | 113 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "clearing SMTP session pool" << s_sessionPool->sessions.count(); | ||
106 | foreach (KIO::Slave *slave, s_slavePool->slaves) { | 114 | while (!s_sessionPool->sessions.isEmpty()) { | ||
107 | if (slave) { | 115 | s_sessionPool->removeSession(*(s_sessionPool->sessions.begin())); | ||
108 | KIO::Scheduler::disconnectSlave(slave); | | |||
109 | } | | |||
110 | } | 116 | } | ||
111 | s_slavePool->slaves.clear(); | | |||
112 | } | 117 | } | ||
113 | } | 118 | } | ||
114 | delete d; | 119 | delete d; | ||
115 | } | 120 | } | ||
116 | 121 | | |||
117 | void SmtpJob::doStart() | 122 | void SmtpJob::doStart() | ||
118 | { | 123 | { | ||
119 | if (s_slavePool.isDestroyed()) { | 124 | if (s_sessionPool.isDestroyed()) { | ||
120 | return; | 125 | return; | ||
121 | } | 126 | } | ||
122 | 127 | | |||
123 | if ((!s_slavePool->slaves.isEmpty() | 128 | if ((!s_sessionPool->sessions.isEmpty() | ||
124 | && s_slavePool->slaves.contains(transport()->id())) | 129 | && s_sessionPool->sessions.contains(transport()->id())) | ||
125 | || transport()->precommand().isEmpty()) { | 130 | || transport()->precommand().isEmpty()) { | ||
126 | d->currentState = SmtpJobPrivate::Smtp; | 131 | d->currentState = SmtpJobPrivate::Smtp; | ||
127 | startSmtpJob(); | 132 | startSmtpJob(); | ||
128 | } else { | 133 | } else { | ||
129 | d->currentState = SmtpJobPrivate::Precommand; | 134 | d->currentState = SmtpJobPrivate::Precommand; | ||
130 | PrecommandJob *job = new PrecommandJob(transport()->precommand(), this); | 135 | PrecommandJob *job = new PrecommandJob(transport()->precommand(), this); | ||
131 | addSubjob(job); | 136 | addSubjob(job); | ||
132 | job->start(); | 137 | job->start(); | ||
133 | } | 138 | } | ||
134 | } | 139 | } | ||
135 | 140 | | |||
136 | void SmtpJob::startSmtpJob() | 141 | void SmtpJob::startSmtpJob() | ||
137 | { | 142 | { | ||
138 | if (s_slavePool.isDestroyed()) { | 143 | if (s_sessionPool.isDestroyed()) { | ||
139 | return; | 144 | return; | ||
140 | } | 145 | } | ||
141 | 146 | | |||
142 | QUrl destination; | 147 | d->session = s_sessionPool->sessions.value(transport()->id()); | ||
143 | destination.setScheme((transport()->encryption() == Transport::EnumEncryption::SSL) | 148 | if (!d->session) { | ||
144 | ? SMTPS_PROTOCOL : SMTP_PROTOCOL); | 149 | d->session = new KSmtp::Session(transport()->host(), transport()->port()); | ||
145 | destination.setHost(transport()->host().trimmed()); | 150 | d->session->setUiProxy(d->uiProxy); | ||
146 | destination.setPort(transport()->port()); | 151 | if (transport()->specifyHostname()) { | ||
147 | 152 | d->session->setCustomHostname(transport()->localHostname()); | |||
148 | QUrlQuery destinationQuery(destination); | 153 | } | ||
149 | destinationQuery.addQueryItem(QStringLiteral("headers"), QStringLiteral("0")); | 154 | s_sessionPool->sessions.insert(transport()->id(), d->session); | ||
150 | destinationQuery.addQueryItem(QStringLiteral("from"), sender()); | 155 | } | ||
151 | 156 | | |||
152 | for (const QString &str : to()) { | 157 | connect(d->session, &KSmtp::Session::stateChanged, | ||
153 | destinationQuery.addQueryItem(QStringLiteral("to"), str); | 158 | this, &SmtpJob::sessionStateChanged, Qt::UniqueConnection); | ||
159 | connect(d->session, &KSmtp::Session::connectionError, | ||||
160 | this, [this](const QString &err) { | ||||
161 | setError(KJob::UserDefinedError); | ||||
162 | setErrorText(err); | ||||
163 | s_sessionPool->removeSession(d->session); | ||||
164 | emitResult(); | ||||
165 | }); | ||||
166 | | ||||
167 | if (d->session->state() == KSmtp::Session::Disconnected) { | ||||
168 | d->session->open(); | ||||
169 | } else { | ||||
170 | if (d->session->state() != KSmtp::Session::Authenticated) { | ||||
171 | startLoginJob(); | ||||
154 | } | 172 | } | ||
155 | for (const QString &str : cc()) { | 173 | | ||
156 | destinationQuery.addQueryItem(QStringLiteral("cc"), str); | 174 | startSendJob(); | ||
157 | } | 175 | } | ||
158 | for (const QString &str : bcc()) { | | |||
159 | destinationQuery.addQueryItem(QStringLiteral("bcc"), str); | | |||
160 | } | 176 | } | ||
161 | 177 | | |||
162 | if (transport()->specifyHostname()) { | 178 | void SmtpJob::sessionStateChanged(KSmtp::Session::State state) | ||
163 | destinationQuery.addQueryItem(QStringLiteral("hostname"), transport()->localHostname()); | 179 | { | ||
180 | if (state == KSmtp::Session::Ready) { | ||||
181 | startLoginJob(); | ||||
182 | } else if (state == KSmtp::Session::Authenticated) { | ||||
183 | startSendJob(); | ||||
184 | } | ||||
185 | } | ||||
186 | | ||||
187 | void SmtpJob::startLoginJob() | ||||
188 | { | ||||
189 | if (!transport()->requiresAuthentication()) { | ||||
190 | startSendJob(); | ||||
191 | return; | ||||
164 | } | 192 | } | ||
165 | 193 | | |||
166 | if (transport()->requiresAuthentication()) { | 194 | auto login = new KSmtp::LoginJob(d->session); | ||
167 | QString user = transport()->userName(); | 195 | auto user = transport()->userName(); | ||
168 | QString passwd = transport()->password(); | 196 | auto passwd = transport()->password(); | ||
169 | if ((user.isEmpty() || passwd.isEmpty()) | 197 | if ((user.isEmpty() || passwd.isEmpty()) | ||
170 | && transport()->authenticationType() != Transport::EnumAuthenticationType::GSSAPI) { | 198 | && transport()->authenticationType() != Transport::EnumAuthenticationType::GSSAPI) { | ||
171 | QPointer<KPasswordDialog> dlg | 199 | QPointer<KPasswordDialog> dlg | ||
172 | = new KPasswordDialog( | 200 | = new KPasswordDialog( | ||
173 | nullptr, | 201 | nullptr, | ||
174 | KPasswordDialog::ShowUsernameLine | 202 | KPasswordDialog::ShowUsernameLine | ||
175 | |KPasswordDialog::ShowKeepPassword); | 203 | |KPasswordDialog::ShowKeepPassword); | ||
176 | dlg->setPrompt(i18n("You need to supply a username and a password " | 204 | dlg->setPrompt(i18n("You need to supply a username and a password " | ||
Show All 14 Lines | |||||
191 | delete dlg; | 219 | delete dlg; | ||
192 | 220 | | |||
193 | if (!gotIt) { | 221 | if (!gotIt) { | ||
194 | setError(KilledJobError); | 222 | setError(KilledJobError); | ||
195 | emitResult(); | 223 | emitResult(); | ||
196 | return; | 224 | return; | ||
197 | } | 225 | } | ||
198 | } | 226 | } | ||
199 | destination.setUserName(transport()->userName()); | | |||
200 | destination.setPassword(transport()->password()); | | |||
201 | } | | |||
202 | 227 | | |||
203 | // dotstuffing is now done by the slave (see setting of metadata) | 228 | login->setUserName(transport()->userName()); | ||
204 | if (!data().isEmpty()) { | 229 | login->setPassword(transport()->password()); | ||
205 | // allow +5% for subsequent LF->CRLF and dotstuffing (an average | 230 | switch (transport()->authenticationType()) { | ||
206 | // over 2G-lines gives an average line length of 42-43): | 231 | case TransportBase::EnumAuthenticationType::PLAIN: | ||
207 | destinationQuery.addQueryItem(QStringLiteral("size"), | 232 | login->setPreferedAuthMode(KSmtp::LoginJob::Plain); | ||
208 | QString::number(qRound(data().length() * 1.05))); | 233 | break; | ||
209 | } | 234 | case TransportBase::EnumAuthenticationType::LOGIN: | ||
210 | 235 | login->setPreferedAuthMode(KSmtp::LoginJob::Login); | |||
211 | destination.setPath(QStringLiteral("/send")); | 236 | break; | ||
212 | destination.setQuery(destinationQuery); | 237 | case TransportBase::EnumAuthenticationType::CRAM_MD5: | ||
213 | 238 | login->setPreferedAuthMode(KSmtp::LoginJob::CramMD5); | |||
214 | d->slave = s_slavePool->slaves.value(transport()->id()); | 239 | break; | ||
215 | if (!d->slave) { | 240 | case TransportBase::EnumAuthenticationType::XOAUTH2: | ||
216 | KIO::MetaData slaveConfig; | 241 | login->setPreferedAuthMode(KSmtp::LoginJob::XOAuth); | ||
217 | slaveConfig.insert(QStringLiteral("tls"), | 242 | break; | ||
218 | (transport()->encryption() == Transport::EnumEncryption::TLS) | 243 | case TransportBase::EnumAuthenticationType::DIGEST_MD5: | ||
219 | ? QStringLiteral("on") : QStringLiteral("off")); | 244 | login->setPreferedAuthMode(KSmtp::LoginJob::DigestMD5); | ||
220 | if (transport()->requiresAuthentication()) { | 245 | break; | ||
221 | slaveConfig.insert(QStringLiteral("sasl"), transport()->authenticationTypeString()); | 246 | case TransportBase::EnumAuthenticationType::NTLM: | ||
222 | } | 247 | login->setPreferedAuthMode(KSmtp::LoginJob::NTLM); | ||
223 | d->slave = KIO::Scheduler::getConnectedSlave(destination, slaveConfig); | 248 | break; | ||
224 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "Created new SMTP slave" << d->slave; | 249 | case TransportBase::EnumAuthenticationType::GSSAPI: | ||
225 | s_slavePool->slaves.insert(transport()->id(), d->slave); | 250 | login->setPreferedAuthMode(KSmtp::LoginJob::GSSAPI); | ||
226 | } else { | 251 | break; | ||
227 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "Re-using existing slave" << d->slave; | 252 | default: | ||
228 | } | 253 | qCWarning(MAILTRANSPORT_SMTP_LOG) << "Unknown authentication mode" << transport()->authenticationTypeString(); | ||
254 | break; | ||||
255 | } | ||||
256 | | ||||
257 | switch (transport()->encryption()) { | ||||
258 | case Transport::EnumEncryption::None: | ||||
259 | login->setEncryptionMode(KSmtp::LoginJob::Unencrypted); | ||||
260 | break; | ||||
261 | case Transport::EnumEncryption::TLS: | ||||
262 | login->setEncryptionMode(KSmtp::LoginJob::TlsV1); | ||||
263 | break; | ||||
264 | case Transport::EnumEncryption::SSL: | ||||
265 | login->setEncryptionMode(KSmtp::LoginJob::AnySslVersion); | ||||
266 | break; | ||||
267 | default: | ||||
268 | qCWarning(MAILTRANSPORT_SMTP_LOG) << "Unknown encryption mode" << transport()->encryption(); | ||||
269 | break; | ||||
270 | | ||||
271 | } | ||||
272 | | ||||
273 | connect(login, &KJob::result, this, &SmtpJob::slotResult); | ||||
274 | addSubjob(login); | ||||
275 | login->start(); | ||||
276 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "Login started"; | ||||
277 | } | ||||
278 | | ||||
279 | void SmtpJob::startSendJob() | ||||
280 | { | ||||
281 | auto send = new KSmtp::SendJob(d->session); | ||||
282 | send->setFrom(sender()); | ||||
283 | send->setTo(to()); | ||||
284 | send->setCc(cc()); | ||||
285 | send->setBcc(bcc()); | ||||
286 | send->setData(data()); | ||||
287 | | ||||
288 | connect(send, &KJob::result, this, &SmtpJob::slotResult); | ||||
289 | addSubjob(send); | ||||
290 | send->start(); | ||||
229 | 291 | | |||
230 | KIO::TransferJob *job = KIO::put(destination, -1, KIO::HideProgressInfo); | 292 | qCDebug(MAILTRANSPORT_SMTP_LOG) << "Send started"; | ||
231 | if (!d->slave || !job) { | | |||
232 | setError(UserDefinedError); | | |||
233 | setErrorText(i18n("Unable to create SMTP job.")); | | |||
234 | emitResult(); | | |||
235 | return; | | |||
236 | } | | |||
237 | | ||||
238 | job->addMetaData(QStringLiteral("lf2crlf+dotstuff"), QStringLiteral("slave")); | | |||
239 | connect(job, &KIO::TransferJob::dataReq, this, &SmtpJob::dataRequest); | | |||
240 | | ||||
241 | addSubjob(job); | | |||
242 | KIO::Scheduler::assignJobToSlave(d->slave, job); | | |||
243 | | ||||
244 | setTotalAmount(KJob::Bytes, data().length()); | | |||
245 | } | 293 | } | ||
246 | 294 | | |||
247 | bool SmtpJob::doKill() | 295 | bool SmtpJob::doKill() | ||
248 | { | 296 | { | ||
249 | if (s_slavePool.isDestroyed()) { | 297 | if (s_sessionPool.isDestroyed()) { | ||
250 | return false; | 298 | return false; | ||
251 | } | 299 | } | ||
252 | 300 | | |||
253 | if (!hasSubjobs()) { | 301 | if (!hasSubjobs()) { | ||
254 | return true; | 302 | return true; | ||
255 | } | 303 | } | ||
256 | if (d->currentState == SmtpJobPrivate::Precommand) { | 304 | if (d->currentState == SmtpJobPrivate::Precommand) { | ||
257 | return subjobs().first()->kill(); | 305 | return subjobs().first()->kill(); | ||
258 | } else if (d->currentState == SmtpJobPrivate::Smtp) { | 306 | } else if (d->currentState == SmtpJobPrivate::Smtp) { | ||
259 | KIO::SimpleJob *job = static_cast<KIO::SimpleJob *>(subjobs().first()); | | |||
260 | clearSubjobs(); | 307 | clearSubjobs(); | ||
261 | KIO::Scheduler::cancelJob(job); | 308 | s_sessionPool->removeSession(d->session); | ||
262 | s_slavePool->removeSlave(d->slave); | | |||
263 | return true; | 309 | return true; | ||
264 | } | 310 | } | ||
265 | return false; | 311 | return false; | ||
266 | } | 312 | } | ||
267 | 313 | | |||
268 | void SmtpJob::slotResult(KJob *job) | 314 | void SmtpJob::slotResult(KJob *job) | ||
269 | { | 315 | { | ||
270 | if (s_slavePool.isDestroyed()) { | 316 | if (s_sessionPool.isDestroyed()) { | ||
271 | return; | 317 | return; | ||
272 | } | 318 | } | ||
273 | 319 | | |||
274 | // The job has finished, so we don't care about any further errors. Set | 320 | // The job has finished, so we don't care about any further errors. Set | ||
275 | // d->finished to true, so slaveError() knows about this and doesn't call | 321 | // d->finished to true, so slaveError() knows about this and doesn't call | ||
276 | // emitResult() anymore. | 322 | // emitResult() anymore. | ||
277 | // Sometimes, the SMTP slave emits more than one error | 323 | // Sometimes, the SMTP slave emits more than one error | ||
278 | // | 324 | // | ||
Show All 14 Lines | |||||
293 | // To prevent that, we call TransportJob::slotResult() only after removing the | 339 | // To prevent that, we call TransportJob::slotResult() only after removing the | ||
294 | // slave from the pool and calculate the error code ourselves. | 340 | // slave from the pool and calculate the error code ourselves. | ||
295 | int errorCode = error(); | 341 | int errorCode = error(); | ||
296 | if (!errorCode) { | 342 | if (!errorCode) { | ||
297 | errorCode = job->error(); | 343 | errorCode = job->error(); | ||
298 | } | 344 | } | ||
299 | 345 | | |||
300 | if (errorCode && d->currentState == SmtpJobPrivate::Smtp) { | 346 | if (errorCode && d->currentState == SmtpJobPrivate::Smtp) { | ||
301 | s_slavePool->removeSlave(d->slave, errorCode != KIO::ERR_SLAVE_DIED); | 347 | s_sessionPool->removeSession(d->session); | ||
302 | TransportJob::slotResult(job); | 348 | TransportJob::slotResult(job); | ||
303 | return; | 349 | return; | ||
304 | } | 350 | } | ||
305 | 351 | | |||
306 | TransportJob::slotResult(job); | 352 | TransportJob::slotResult(job); | ||
307 | if (!error() && d->currentState == SmtpJobPrivate::Precommand) { | 353 | if (!error() && d->currentState == SmtpJobPrivate::Precommand) { | ||
308 | d->currentState = SmtpJobPrivate::Smtp; | 354 | d->currentState = SmtpJobPrivate::Smtp; | ||
309 | startSmtpJob(); | 355 | startSmtpJob(); | ||
310 | return; | 356 | return; | ||
311 | } | 357 | } | ||
312 | if (!error()) { | 358 | if (!error() && !hasSubjobs()) { | ||
313 | emitResult(); | | |||
314 | } | | |||
315 | } | | |||
316 | | ||||
317 | void SmtpJob::dataRequest(KIO::Job *job, QByteArray &data) | | |||
318 | { | | |||
319 | if (s_slavePool.isDestroyed()) { | | |||
320 | return; | | |||
321 | } | | |||
322 | | ||||
323 | Q_UNUSED(job); | | |||
324 | Q_ASSERT(job); | | |||
325 | if (buffer()->atEnd()) { | | |||
326 | data.clear(); | | |||
327 | } else { | | |||
328 | Q_ASSERT(buffer()->isOpen()); | | |||
329 | data = buffer()->read(32 * 1024); | | |||
330 | } | | |||
331 | setProcessedAmount(KJob::Bytes, buffer()->pos()); | | |||
332 | } | | |||
333 | | ||||
334 | void SmtpJob::slaveError(KIO::Slave *slave, int errorCode, const QString &errorMsg) | | |||
335 | { | | |||
336 | if (s_slavePool.isDestroyed()) { | | |||
337 | return; | | |||
338 | } | | |||
339 | | ||||
340 | s_slavePool->removeSlave(slave, errorCode != KIO::ERR_SLAVE_DIED); | | |||
341 | if (d->slave == slave && !d->finished) { | | |||
342 | setError(errorCode); | | |||
343 | setErrorText(KIO::buildErrorString(errorCode, errorMsg)); | | |||
344 | emitResult(); | 359 | emitResult(); | ||
345 | } | 360 | } | ||
346 | } | 361 | } | ||
347 | 362 | | |||
348 | #include "moc_smtpjob.cpp" | 363 | #include "moc_smtpjob.cpp" |