00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
#ifdef HAVE_CONFIG_H
00033
#include <config.h>
00034
#endif
00035
00036
#include "imapjob.h"
00037
#include "kmfolderimap.h"
00038
#include "kmmsgpart.h"
00039
00040
#include <kio/scheduler.h>
00041
#include <kdebug.h>
00042
#include <mimelib/body.h>
00043
#include <mimelib/bodypart.h>
00044
#include <mimelib/string.h>
00045
00046
00047
namespace KMail {
00048
00049
00050 ImapJob::ImapJob( KMMessage *msg, JobType jt, KMFolderImap* folder,
00051 QString partSpecifier,
const AttachmentStrategy *as )
00052 : FolderJob( msg, jt, folder, partSpecifier ),
00053 mAttachmentStrategy( as )
00054 {
00055 }
00056
00057
00058 ImapJob::ImapJob( QPtrList<KMMessage>& msgList, QString sets, JobType jt,
00059 KMFolderImap* folder )
00060 : FolderJob( msgList, sets, jt, folder ),
00061 mAttachmentStrategy ( 0 )
00062 {
00063 }
00064
00065
void ImapJob::init( JobType jt, QString sets, KMFolderImap* folder,
00066 QPtrList<KMMessage>& msgList )
00067 {
00068 mJob = 0;
00069 assert(jt == tGetMessage || folder);
00070 KMMessage* msg = msgList.first();
00071 mType = jt;
00072 mDestFolder = folder;
00073
00074
if (folder) {
00075 folder->open();
00076 }
00077
KMFolder *msg_parent = msg->parent();
00078
if (msg_parent) {
00079
if (!folder || folder!= msg_parent) {
00080 msg_parent->
open();
00081 }
00082 }
00083 mSrcFolder = msg_parent;
00084
00085
00086
00087
00088 KMAcctImap *account;
00089
if (folder) {
00090 account = folder->account();
00091 }
else {
00092 account = static_cast<KMFolderImap*>(msg_parent)->account();
00093 }
00094
if ( !account ||
00095 account->makeConnection() == ImapAccountBase::Error ) {
00096 deleteLater();
00097
return;
00098 }
00099 account->mJobList.append(
this );
00100
if ( jt == tPutMessage )
00101 {
00102
00103 KURL url = account->getUrl();
00104 QString flags = KMFolderImap::statusToFlags( msg->status() );
00105 url.setPath( folder->imapPath() +
";SECTION=" + flags );
00106 ImapAccountBase::jobData jd;
00107 jd.parent = 0; jd.offset = 0;
00108 jd.total = 1; jd.done = 0;
00109 jd.msgList.append(msg);
00110 QCString cstr( msg->asString() );
00111
int a = cstr.find(
"\nX-UID: " );
00112
int b = cstr.find(
"\n", a );
00113
if ( a != -1 && b != -1 && cstr.find(
"\n\n" ) > a ) cstr.remove( a, b-a );
00114 mData.resize( cstr.length() + cstr.contains(
"\n" ) - cstr.contains(
"\r\n" ) );
00115
unsigned int i = 0;
00116
char prevChar =
'\0';
00117
00118
for (
char *ch = cstr.data(); *ch; ch++ )
00119 {
00120
if ( *ch ==
'\n' && (prevChar !=
'\r') ) {
00121 mData.at( i ) =
'\r';
00122 i++;
00123 }
00124 mData.at( i ) = *ch;
00125 prevChar = *ch;
00126 i++;
00127 }
00128 jd.data = mData;
00129 KIO::SimpleJob *simpleJob = KIO::put( url, 0, FALSE, FALSE, FALSE );
00130 KIO::Scheduler::assignJobToSlave( account->slave(), simpleJob );
00131 mJob = simpleJob;
00132 account->insertJob( mJob, jd );
00133 connect( mJob, SIGNAL(result(KIO::Job *)),
00134 SLOT(slotPutMessageResult(KIO::Job *)) );
00135 connect( mJob, SIGNAL(dataReq(KIO::Job *, QByteArray &)),
00136 SLOT(slotPutMessageDataReq(KIO::Job *, QByteArray &)) );
00137 connect( mJob, SIGNAL(infoMessage(KIO::Job *,
const QString &)),
00138 SLOT(slotPutMessageInfoData(KIO::Job *,
const QString &)) );
00139 }
00140
else if ( jt == tCopyMessage || jt == tMoveMessage )
00141 {
00142 KURL url = account->getUrl();
00143 KURL destUrl = account->getUrl();
00144 destUrl.setPath(folder->imapPath());
00145 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(msg_parent);
00146 url.setPath( imapDestFolder->imapPath() +
";UID=" + sets );
00147 ImapAccountBase::jobData jd;
00148 jd.parent = 0; mOffset = 0;
00149 jd.total = 1; jd.done = 0;
00150 jd.msgList = msgList;
00151
00152 QByteArray packedArgs;
00153 QDataStream stream( packedArgs, IO_WriteOnly );
00154
00155 stream << (
int)
'C' << url << destUrl;
00156
00157 KIO::SimpleJob *simpleJob = KIO::special( url, packedArgs, FALSE );
00158 KIO::Scheduler::assignJobToSlave( account->slave(), simpleJob );
00159 mJob = simpleJob;
00160 account->insertJob( mJob, jd );
00161 connect( mJob, SIGNAL(result(KIO::Job *)),
00162 SLOT(slotCopyMessageResult(KIO::Job *)) );
00163
if ( jt == tMoveMessage )
00164 {
00165 connect( mJob, SIGNAL(infoMessage(KIO::Job *,
const QString &)),
00166 SLOT(slotCopyMessageInfoData(KIO::Job *,
const QString &)) );
00167 }
00168 }
else {
00169 slotGetNextMessage();
00170 }
00171 }
00172
00173
00174
00175 ImapJob::~ImapJob()
00176 {
00177
00178
if ( mDestFolder )
00179 {
00180 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder)->account();
00181
if ( account )
00182 account->mJobList.remove(
this);
00183
if ( account && mJob )
00184 {
00185 ImapAccountBase::JobIterator it = account->findJob( mJob );
00186
if ( it != account->jobsEnd() && !(*it).msgList.isEmpty() )
00187 {
00188
for ( QPtrListIterator<KMMessage> mit( (*it).msgList ); mit.current(); ++mit )
00189 mit.current()->setTransferInProgress(
false);
00190 }
00191 }
00192
00193 mDestFolder->close();
00194 }
00195
00196
if (mSrcFolder) {
00197
if (!mDestFolder || mDestFolder != mSrcFolder) {
00198
if (! (mSrcFolder->folderType() == KMFolderTypeImap) )
return;
00199 KMAcctImap *account = static_cast<KMFolderImap*>(mSrcFolder)->account();
00200
if ( account )
00201 account->mJobList.remove(
this);
00202
if ( account && mJob )
00203 {
00204 ImapAccountBase::JobIterator it = account->findJob( mJob );
00205
if ( it != account->jobsEnd() && !(*it).msgList.isEmpty() )
00206 {
00207
for ( QPtrListIterator<KMMessage> mit( (*it).msgList ); mit.current(); ++mit )
00208 mit.current()->setTransferInProgress(
false);
00209 }
00210 }
00211 }
00212
00213 mSrcFolder->close();
00214 }
00215 }
00216
00217
00218
00219
void ImapJob::slotGetNextMessage()
00220 {
00221 KMMessage *msg = mMsgList.first();
00222 KMFolderImap *msgParent = static_cast<KMFolderImap*>(msg->parent());
00223 KMAcctImap *account = msgParent->account();
00224
if ( msg->headerField(
"X-UID").isEmpty() )
00225 {
00226 emit messageRetrieved( msg );
00227 account->mJobList.remove(
this );
00228 deleteLater();
00229
return;
00230 }
00231 KURL url = account->getUrl();
00232 QString path = msgParent->imapPath() +
";UID=" + msg->headerField(
"X-UID");
00233
if ( !mPartSpecifier.isEmpty() )
00234 {
00235
if ( mPartSpecifier.find (
"STRUCTURE", 0,
false) != -1 ) {
00236 path +=
";SECTION=STRUCTURE";
00237 }
else if ( mPartSpecifier ==
"HEADER" ) {
00238 path +=
";SECTION=HEADER";
00239 }
else {
00240 path +=
";SECTION=BODY.PEEK[" + mPartSpecifier +
"]";
00241 }
00242 }
else {
00243 path +=
";SECTION=BODY.PEEK[]";
00244 }
00245 url.setPath( path );
00246
00247 ImapAccountBase::jobData jd;
00248 jd.parent = 0;
00249 jd.total = 1; jd.done = 0;
00250
00251 msg->setTransferInProgress(
true );
00252 KIO::SimpleJob *simpleJob = KIO::get( url, FALSE, FALSE );
00253 KIO::Scheduler::assignJobToSlave( account->slave(), simpleJob );
00254 mJob = simpleJob;
00255 account->insertJob( mJob, jd );
00256
if ( mPartSpecifier.find(
"STRUCTURE", 0,
false ) != -1 )
00257 {
00258 connect( mJob, SIGNAL(result(KIO::Job *)),
00259
this, SLOT(slotGetBodyStructureResult(KIO::Job *)) );
00260 }
else {
00261 connect( mJob, SIGNAL(result(KIO::Job *)),
00262
this, SLOT(slotGetMessageResult(KIO::Job *)) );
00263 }
00264 connect( mJob, SIGNAL(data(KIO::Job *,
const QByteArray &)),
00265 msgParent, SLOT(slotSimpleData(KIO::Job *,
const QByteArray &)) );
00266 }
00267
00268
00269
00270
void ImapJob::slotGetMessageResult( KIO::Job * job )
00271 {
00272 KMMessage *msg = mMsgList.first();
00273
if (!msg || !msg->parent() || !job) {
00274 deleteLater();
00275
return;
00276 }
00277 KMFolderImap* parent = static_cast<KMFolderImap*>(msg->parent());
00278
if (msg->transferInProgress())
00279 msg->setTransferInProgress(
false );
00280 KMAcctImap *account = parent->account();
00281
if ( !account ) {
00282 deleteLater();
00283
return;
00284 }
00285 ImapAccountBase::JobIterator it = account->findJob( job );
00286
if ( it == account->jobsEnd() )
return;
00287
00288
bool gotData =
true;
00289
if (job->error())
00290 {
00291 account->slotSlaveError( account->slave(), job->error(), job->errorText() );
00292
return;
00293 }
else {
00294
if ((*it).data.size() > 0)
00295 {
00296 kdDebug(5006) <<
"ImapJob::slotGetMessageResult - retrieved part " << mPartSpecifier << endl;
00297
if ( mPartSpecifier.isEmpty() ||
00298 mPartSpecifier ==
"HEADER" )
00299 {
00300 uint size = msg->headerField(
"X-Length").toUInt();
00301 QString uid = msg->headerField(
"X-UID");
00302 msg->fromByteArray( (*it).data );
00303 msg->setHeaderField(
"X-UID",uid);
00304
00305
if ( size > 0 ) msg->setMsgLength(size);
00306
if ( mPartSpecifier.isEmpty() )
00307 msg->setComplete(
true );
00308
else
00309 msg->setReadyToShow(
false );
00310 }
else {
00311
00312 msg->updateBodyPart( mPartSpecifier, (*it).data );
00313 msg->setReadyToShow(
true );
00314 }
00315 }
else {
00316 kdDebug(5006) <<
"ImapJob::slotGetMessageResult - got no data for " << mPartSpecifier << endl;
00317 gotData =
false;
00318 msg->setReadyToShow(
true );
00319
00320 msg->notify();
00321 }
00322 }
00323
if (account->slave()) {
00324 account->removeJob(it);
00325 account->mJobList.remove(
this);
00326 }
00327
00328
00329
if ( mPartSpecifier.isEmpty() ||
00330 mPartSpecifier ==
"HEADER" )
00331 {
00332
if ( gotData )
00333 emit messageRetrieved(msg);
00334
else
00335 {
00336
00337
00338 parent->ignoreJobsForMessage( msg );
00339
int idx = parent->find( msg );
00340
if (idx != -1) parent->removeMsg( idx,
true );
00341 emit messageRetrieved( 0 );
00342 }
00343 }
else {
00344 emit messageUpdated(msg, mPartSpecifier);
00345 }
00346 deleteLater();
00347 }
00348
00349
00350
void ImapJob::slotGetBodyStructureResult( KIO::Job * job )
00351 {
00352 KMMessage *msg = mMsgList.first();
00353
if (!msg || !msg->parent() || !job) {
00354 deleteLater();
00355
return;
00356 }
00357 KMFolderImap* parent = static_cast<KMFolderImap*>(msg->parent());
00358
if (msg->transferInProgress())
00359 msg->setTransferInProgress(
false );
00360 KMAcctImap *account = parent->account();
00361
if ( !account ) {
00362 deleteLater();
00363
return;
00364 }
00365 ImapAccountBase::JobIterator it = account->findJob( job );
00366
if ( it == account->jobsEnd() )
return;
00367
00368
00369
if (job->error())
00370 {
00371 account->slotSlaveError( account->slave(), job->error(),
00372 job->errorText() );
00373
return;
00374 }
else {
00375
if ((*it).data.size() > 0)
00376 {
00377 QDataStream stream( (*it).data, IO_ReadOnly );
00378 account->handleBodyStructure(stream, msg, mAttachmentStrategy);
00379 }
00380 }
00381
if (account->slave()) {
00382 account->removeJob(it);
00383 account->mJobList.remove(
this);
00384 }
00385 deleteLater();
00386 }
00387
00388
00389
void ImapJob::slotPutMessageDataReq( KIO::Job *job, QByteArray &data )
00390 {
00391 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder)->account();
00392 ImapAccountBase::JobIterator it = account->findJob( job );
00393
if ( it == account->jobsEnd() )
return;
00394
00395
if ((*it).data.size() - (*it).offset > 0x8000)
00396 {
00397 data.duplicate((*it).data.data() + (*it).offset, 0x8000);
00398 (*it).offset += 0x8000;
00399 }
00400
else if ((*it).data.size() - (*it).offset > 0)
00401 {
00402 data.duplicate((*it).data.data() + (*it).offset, (*it).data.size() - (*it).offset);
00403 (*it).offset = (*it).data.size();
00404 }
else data.resize(0);
00405 }
00406
00407
00408
00409
void ImapJob::slotPutMessageResult( KIO::Job *job )
00410 {
00411 KMMessage *msg = mMsgList.first();
00412 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder)->account();
00413 ImapAccountBase::JobIterator it = account->findJob( job );
00414
if ( it == account->jobsEnd() )
return;
00415
00416
if (job->error())
00417 {
00418 account->slotSlaveError( account->slave(), job->error(),
00419 job->errorText() );
00420
return;
00421 }
else {
00422
if ( !(*it).msgList.isEmpty() )
00423 {
00424 emit messageStored((*it).msgList.last());
00425 (*it).msgList.removeLast();
00426 }
else if (msg)
00427 {
00428 emit messageStored(msg);
00429 }
00430 msg = 0;
00431 }
00432
if (account->slave()) {
00433 account->removeJob(it);
00434 account->mJobList.remove(
this);
00435 }
00436 deleteLater();
00437 }
00438
00439
00440
void ImapJob::slotCopyMessageInfoData(KIO::Job * job,
const QString & data)
00441 {
00442 KMFolderImap * imapFolder = static_cast<KMFolderImap*>(mDestFolder);
00443 KMAcctImap *account = imapFolder->account();
00444 ImapAccountBase::JobIterator it = account->findJob( job );
00445
if ( it == account->jobsEnd() )
return;
00446
00447
if (data.find(
"UID") != -1)
00448 {
00449
00450 QString oldUid = data.section(
' ', 1, 1);
00451 QString newUid = data.section(
' ', 2, 2);
00452
00453
00454 QValueList<int> olduids = KMFolderImap::splitSets(oldUid);
00455 QValueList<int> newuids = KMFolderImap::splitSets(newUid);
00456
00457
int index = -1;
00458
if ( !(*it).msgList.isEmpty() )
00459 {
00460 KMMessage * msg;
00461
for ( msg = (*it).msgList.first(); msg; msg = (*it).msgList.next() )
00462 {
00463 uint uid = msg->headerField(
"X-UID").toInt();
00464 index = olduids.findIndex(uid);
00465
if (index > -1)
00466 {
00467
00468
const ulong * sernum = (ulong *)msg->getMsgSerNum();
00469 imapFolder->insertUidSerNumEntry(newuids[index], sernum);
00470 }
00471 }
00472 }
else if (mMsgList.first()) {
00473 uint uid = mMsgList.first()->headerField(
"X-UID").toInt();
00474 index = olduids.findIndex(uid);
00475
if (index > -1)
00476 {
00477
00478
const ulong * sernum = (ulong *)mMsgList.first()->getMsgSerNum();
00479 imapFolder->insertUidSerNumEntry(newuids[index], sernum);
00480 }
00481 }
00482 }
00483 }
00484
00485
00486
void ImapJob::slotPutMessageInfoData(KIO::Job *job,
const QString &data)
00487 {
00488 KMFolderImap * imapFolder = static_cast<KMFolderImap*>(mDestFolder);
00489 KMAcctImap *account = imapFolder->account();
00490 ImapAccountBase::JobIterator it = account->findJob( job );
00491
if ( it == account->jobsEnd() )
return;
00492
00493
if (data.find(
"UID") != -1)
00494 {
00495
int uid = (data.right(data.length()-4)).toInt();
00496
00497
if ( !(*it).msgList.isEmpty() )
00498 {
00499
const ulong * sernum = (ulong *)(*it).msgList.last()->getMsgSerNum();
00500
00501 imapFolder->insertUidSerNumEntry(uid, sernum);
00502 }
else if (mMsgList.first())
00503 {
00504
const ulong * sernum = (ulong *)mMsgList.first()->getMsgSerNum();
00505
00506 imapFolder->insertUidSerNumEntry(uid, sernum);
00507 }
00508 }
00509 }
00510
00511
00512
00513
void ImapJob::slotCopyMessageResult( KIO::Job *job )
00514 {
00515 KMAcctImap *account = static_cast<KMFolderImap*>(mDestFolder)->account();
00516 ImapAccountBase::JobIterator it = account->findJob( job );
00517
if ( it == account->jobsEnd() )
return;
00518
00519
if (job->error())
00520 {
00521 account->slotSlaveError( account->slave(), job->error(),
00522 job->errorText() );
00523
return;
00524 }
else {
00525
if ( !(*it).msgList.isEmpty() )
00526 {
00527 emit messageCopied((*it).msgList);
00528 }
else if (mMsgList.first()) {
00529 emit messageCopied(mMsgList.first());
00530 }
00531 }
00532
if (account->slave()) {
00533 account->removeJob(it);
00534 account->mJobList.remove(
this);
00535 }
00536 deleteLater();
00537 }
00538
00539
00540
void ImapJob::execute()
00541 {
00542 init( mType, mSets, static_cast<KMFolderImap*>( mDestFolder ), mMsgList );
00543 }
00544
00545
00546
void ImapJob::expireMessages()
00547 {
00548
return;
00549 }
00550
00551 }
00552
00553
#include "imapjob.moc"