37 #include "kmfolderimap.h"
39 #include "kmmsgpart.h"
40 #include "progressmanager.h"
41 using KPIM::ProgressManager;
44 #include <tqstylesheet.h>
45 #include <tdeio/scheduler.h>
47 #include <tdelocale.h>
48 #include <mimelib/body.h>
49 #include <mimelib/bodypart.h>
50 #include <mimelib/string.h>
56 ImapJob::ImapJob(
KMMessage *msg, JobType jt, KMFolderImap* folder,
57 TQString partSpecifier,
const AttachmentStrategy *as )
58 : FolderJob( msg, jt, folder? folder->folder() : 0, partSpecifier ),
59 mAttachmentStrategy( as ), mParentProgressItem(0)
64 ImapJob::ImapJob( TQPtrList<KMMessage>& msgList, TQString sets, JobType jt,
65 KMFolderImap* folder )
66 : FolderJob( msgList, sets, jt, folder? folder->folder() : 0 ),
67 mAttachmentStrategy ( 0 ), mParentProgressItem(0)
71 void ImapJob::init( JobType jt, TQString sets, KMFolderImap* folder,
72 TQPtrList<KMMessage>& msgList )
76 assert(jt == tGetMessage || folder);
84 mDestFolder = folder? folder->folder() : 0;
87 folder->open(
"imapjobdest");
89 KMFolder *msg_parent = msg->parent();
91 msg_parent->
open(
"imapjobsrc");
93 mSrcFolder = msg_parent;
98 KMAcctImap *account = 0;
100 account = folder->account();
102 if ( msg_parent && msg_parent->storage() )
103 account =
static_cast<KMFolderImap*
>(msg_parent->storage())->account();
106 account->makeConnection() == ImapAccountBase::Error ) {
110 account->mJobList.append(
this );
111 if ( jt == tPutMessage )
114 TQPtrListIterator<KMMessage> it( msgList );
116 while ( ( curMsg = it.current() ) != 0 )
119 if ( mSrcFolder && !curMsg->
isMessage() )
121 int idx = mSrcFolder->find( curMsg );
122 curMsg = mSrcFolder->getMsg( idx );
124 KURL url = account->getUrl();
125 TQString flags = KMFolderImap::statusToFlags( curMsg->
status(), folder->permanentFlags() );
126 url.setPath( folder->imapPath() +
";SECTION=" + flags );
127 ImapAccountBase::jobData jd;
128 jd.parent = 0; jd.offset = 0; jd.done = 0;
131 jd.msgList.append( curMsg );
132 TQCString cstr( curMsg->
asString() );
133 int a = cstr.find(
"\nX-UID: ");
134 int b = cstr.find(
'\n', a);
135 if (a != -1 && b != -1 && cstr.find(
"\n\n") > a) cstr.remove(a, b-a);
136 jd.data.resize( cstr.length() + cstr.contains(
"\n" ) - cstr.contains(
"\r\n" ) );
138 char prevChar =
'\0';
140 for (
char *ch = cstr.data(); *ch; ch++ )
142 if ( *ch ==
'\n' && (prevChar !=
'\r') ) {
143 jd.data.at( i ) =
'\r';
146 jd.data.at( i ) = *ch;
150 jd.progressItem = ProgressManager::createProgressItem(
152 "ImapJobUploading"+ProgressManager::getUniqueID(),
153 i18n(
"Uploading message data"),
154 TQStyleSheet::escape( curMsg->
subject() ),
156 account->useSSL() || account->useTLS() );
157 jd.progressItem->setTotalItems( jd.total );
158 connect ( jd.progressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem*)),
159 account, TQ_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
160 TDEIO::SimpleJob *job = TDEIO::put( url, 0,
false,
false,
false );
161 TDEIO::Scheduler::assignJobToSlave( account->slave(), job );
162 account->insertJob( job, jd );
163 connect( job, TQ_SIGNAL(result(TDEIO::Job *)),
164 TQ_SLOT(slotPutMessageResult(TDEIO::Job *)) );
165 connect( job, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
166 TQ_SLOT(slotPutMessageDataReq(TDEIO::Job *, TQByteArray &)) );
167 connect( job, TQ_SIGNAL(infoMessage(TDEIO::Job *,
const TQString &)),
168 TQ_SLOT(slotPutMessageInfoData(TDEIO::Job *,
const TQString &)) );
169 connect( job, TQ_SIGNAL(processedSize(TDEIO::Job *, TDEIO::filesize_t)),
170 TQ_SLOT(slotProcessedSize(TDEIO::Job *, TDEIO::filesize_t)));
173 else if ( jt == tCopyMessage || jt == tMoveMessage )
175 KURL url = account->getUrl();
176 KURL destUrl = account->getUrl();
177 destUrl.setPath(folder->imapPath());
178 KMFolderImap *imapDestFolder =
static_cast<KMFolderImap*
>(msg_parent->storage());
179 url.setPath( imapDestFolder->imapPath() +
";UID=" + sets );
180 ImapAccountBase::jobData jd;
181 jd.parent = 0; jd.offset = 0;
182 jd.total = 1; jd.done = 0;
183 jd.msgList = msgList;
185 TQByteArray packedArgs;
186 TQDataStream stream( packedArgs, IO_WriteOnly );
188 stream << (int)
'C' << url << destUrl;
189 jd.progressItem = ProgressManager::createProgressItem(
191 "ImapJobCopyMove"+ProgressManager::getUniqueID(),
192 i18n(
"Server operation"),
193 i18n(
"Source folder: %1 - Destination folder: %2")
194 .arg( TQStyleSheet::escape( msg_parent->
prettyURL() ),
195 TQStyleSheet::escape( mDestFolder->prettyURL() ) ),
197 account->useSSL() || account->useTLS() );
198 jd.progressItem->setTotalItems( jd.total );
199 connect ( jd.progressItem, TQ_SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
200 account, TQ_SLOT( slotAbortRequested(KPIM::ProgressItem* ) ) );
201 TDEIO::SimpleJob *simpleJob = TDEIO::special( url, packedArgs,
false );
202 TDEIO::Scheduler::assignJobToSlave( account->slave(), simpleJob );
204 account->insertJob( mJob, jd );
205 connect( mJob, TQ_SIGNAL(result(TDEIO::Job *)),
206 TQ_SLOT(slotCopyMessageResult(TDEIO::Job *)) );
207 if ( jt == tMoveMessage )
209 connect( mJob, TQ_SIGNAL(infoMessage(TDEIO::Job *,
const TQString &)),
210 TQ_SLOT(slotCopyMessageInfoData(TDEIO::Job *,
const TQString &)) );
214 slotGetNextMessage();
224 KMAcctImap *account =
static_cast<KMFolderImap*
>(mDestFolder->storage())->account();
227 ImapAccountBase::JobIterator it = account->findJob( mJob );
228 if ( it != account->jobsEnd() ) {
229 if( (*it).progressItem ) {
230 (*it).progressItem->setComplete();
231 (*it).progressItem = 0;
233 if ( !(*it).msgList.isEmpty() ) {
234 for ( TQPtrListIterator<KMMessage> mit( (*it).msgList ); mit.current(); ++mit )
235 mit.current()->setTransferInProgress(
false );
238 account->removeJob( mJob );
240 account->mJobList.remove(
this );
242 mDestFolder->close(
"imapjobdest");
246 if (!mDestFolder || mDestFolder != mSrcFolder) {
247 if (! (mSrcFolder->folderType() == KMFolderTypeImap) )
return;
248 KMAcctImap *account =
static_cast<KMFolderImap*
>(mSrcFolder->storage())->account();
251 ImapAccountBase::JobIterator it = account->findJob( mJob );
252 if ( it != account->jobsEnd() ) {
253 if( (*it).progressItem ) {
254 (*it).progressItem->setComplete();
255 (*it).progressItem = 0;
257 if ( !(*it).msgList.isEmpty() ) {
258 for ( TQPtrListIterator<KMMessage> mit( (*it).msgList ); mit.current(); ++mit )
259 mit.current()->setTransferInProgress(
false );
262 account->removeJob( mJob );
264 account->mJobList.remove(
this );
267 mSrcFolder->close(
"imapjobsrc");
273 void ImapJob::slotGetNextMessage()
276 KMFolderImap *msgParent = msg ?
static_cast<KMFolderImap*
>(msg->storage()) : 0;
277 if ( !msgParent || !msg || msg->
UID() == 0 )
280 emit messageRetrieved( 0 );
284 KMAcctImap *account = msgParent->account();
285 KURL url = account->getUrl();
286 TQString path = msgParent->imapPath() +
";UID=" + TQString::number(msg->
UID());
287 ImapAccountBase::jobData jd;
288 jd.parent = 0; jd.offset = 0;
289 jd.total = 1; jd.done = 0;
290 jd.msgList.append( msg );
291 if ( !mPartSpecifier.isEmpty() )
293 if ( mPartSpecifier.find (
"STRUCTURE", 0,
false) != -1 ) {
294 path +=
";SECTION=STRUCTURE";
295 }
else if ( mPartSpecifier ==
"HEADER" ) {
296 path +=
";SECTION=HEADER";
298 path +=
";SECTION=BODY.PEEK[" + mPartSpecifier +
"]";
301 jd.total = part->BodySize();
304 path +=
";SECTION=BODY.PEEK[]";
312 jd.progressItem = ProgressManager::createProgressItem(
314 "ImapJobDownloading"+ProgressManager::getUniqueID(),
315 i18n(
"Downloading message data"),
316 i18n(
"Message with subject: ") +
317 TQStyleSheet::escape( msg->
subject() ),
319 account->useSSL() || account->useTLS() );
320 connect ( jd.progressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem*)),
321 account, TQ_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
322 jd.progressItem->setTotalItems( jd.total );
324 TDEIO::SimpleJob *simpleJob = TDEIO::get( url,
false,
false );
325 TDEIO::Scheduler::assignJobToSlave( account->slave(), simpleJob );
327 account->insertJob( mJob, jd );
328 if ( mPartSpecifier.find(
"STRUCTURE", 0,
false ) != -1 )
330 connect( mJob, TQ_SIGNAL(result(TDEIO::Job *)),
331 this, TQ_SLOT(slotGetBodyStructureResult(TDEIO::Job *)) );
333 connect( mJob, TQ_SIGNAL(result(TDEIO::Job *)),
334 this, TQ_SLOT(slotGetMessageResult(TDEIO::Job *)) );
336 connect( mJob, TQ_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
337 msgParent, TQ_SLOT(slotSimpleData(TDEIO::Job *,
const TQByteArray &)) );
340 connect(mJob, TQ_SIGNAL(processedSize(TDEIO::Job *, TDEIO::filesize_t)),
341 this, TQ_SLOT(slotProcessedSize(TDEIO::Job *, TDEIO::filesize_t)));
347 void ImapJob::slotGetMessageResult( TDEIO::Job * job )
350 if (!msg || !msg->parent() || !job) {
351 emit messageRetrieved( 0 );
355 KMFolderImap* parent =
static_cast<KMFolderImap*
>(msg->storage());
358 KMAcctImap *account = parent->account();
360 emit messageRetrieved( 0 );
364 ImapAccountBase::JobIterator it = account->findJob( job );
365 if ( it == account->jobsEnd() )
return;
370 TQString errorStr = i18n(
"Error while retrieving messages from the server." );
371 if ( (*it).progressItem )
372 (*it).progressItem->setStatus( errorStr );
373 account->handleJobError( job, errorStr );
376 if ((*it).data.size() > 0)
378 kdDebug(5006) <<
"ImapJob::slotGetMessageResult - retrieved part " << mPartSpecifier << endl;
379 if ( mPartSpecifier.isEmpty() ||
380 mPartSpecifier ==
"HEADER" )
383 if ( size > 0 && mPartSpecifier.isEmpty() )
385 ulong uid = msg->
UID();
387 if ( mPartSpecifier.isEmpty() )
393 size_t dataSize = (*it).data.size();
395 (*it).data.resize( dataSize );
400 msg->parent()->storage()->blockSignals(
true );
401 msg->fromByteArray( (*it).data );
403 msg->parent()->storage()->blockSignals(
false );
405 msg->setMsgSizeServer(size);
412 size_t dataSize = (*it).data.size();
414 (*it).data.resize( dataSize );
421 if (msg->attachmentState() != KMMsgHasAttachment)
422 msg->updateAttachmentState();
423 if (msg->invitationState() != KMMsgHasInvitation)
424 msg->updateInvitationState();
427 kdDebug(5006) <<
"ImapJob::slotGetMessageResult - got no data for " << mPartSpecifier << endl;
434 if (account->slave()) {
435 account->removeJob(it);
436 account->mJobList.remove(
this);
440 if ( mPartSpecifier.isEmpty() ||
441 mPartSpecifier ==
"HEADER" )
444 emit messageRetrieved(msg);
449 emit messageRetrieved( 0 );
450 parent->ignoreJobsForMessage( msg );
451 int idx = parent->find( msg );
452 if (idx != -1) parent->removeMsg( idx,
true );
458 emit messageUpdated(msg, mPartSpecifier);
464 void ImapJob::slotGetBodyStructureResult( TDEIO::Job * job )
467 if (!msg || !msg->parent() || !job) {
471 KMFolderImap* parent =
static_cast<KMFolderImap*
>(msg->storage());
474 KMAcctImap *account = parent->account();
479 ImapAccountBase::JobIterator it = account->findJob( job );
480 if ( it == account->jobsEnd() )
return;
485 account->handleJobError( job, i18n(
"Error while retrieving information on the structure of a message." ) );
488 if ((*it).data.size() > 0)
490 TQDataStream stream( (*it).data, IO_ReadOnly );
491 account->handleBodyStructure(stream, msg, mAttachmentStrategy);
494 if (account->slave()) {
495 account->removeJob(it);
496 account->mJobList.remove(
this);
502 void ImapJob::slotPutMessageDataReq( TDEIO::Job *job, TQByteArray &data )
504 KMAcctImap *account =
static_cast<KMFolderImap*
>(mDestFolder->storage())->account();
511 ImapAccountBase::JobIterator it = account->findJob( job );
512 if ( it == account->jobsEnd() )
return;
514 if ((*it).data.size() - (*it).offset > 0x8000)
516 data.duplicate((*it).data.data() + (*it).offset, 0x8000);
517 (*it).offset += 0x8000;
519 else if ((*it).data.size() - (*it).offset > 0)
521 data.duplicate((*it).data.data() + (*it).offset, (*it).data.size() - (*it).offset);
522 (*it).offset = (*it).data.size();
523 }
else data.resize(0);
528 void ImapJob::slotPutMessageResult( TDEIO::Job *job )
530 KMAcctImap *account =
static_cast<KMFolderImap*
>(mDestFolder->storage())->account();
537 ImapAccountBase::JobIterator it = account->findJob( job );
538 if ( it == account->jobsEnd() )
return;
539 bool deleteMe =
false;
542 if ( (*it).progressItem )
543 (*it).progressItem->setStatus( i18n(
"Uploading message data failed.") );
544 account->handlePutError( job, *it, mDestFolder );
547 if ( (*it).progressItem )
548 (*it).progressItem->setStatus( i18n(
"Uploading message data completed.") );
549 if ( mParentProgressItem )
551 mParentProgressItem->incCompletedItems();
552 mParentProgressItem->updateProgress();
555 emit messageStored( msg );
556 if ( msg == mMsgList.getLast() )
558 emit messageCopied( mMsgList );
559 if (account->slave()) {
560 account->mJobList.remove(
this );
565 if (account->slave()) {
566 account->removeJob( it );
573 void ImapJob::slotCopyMessageInfoData(TDEIO::Job * job,
const TQString & data)
575 KMFolderImap * imapFolder =
static_cast<KMFolderImap*
>(mDestFolder->storage());
576 KMAcctImap *account = imapFolder->account();
583 ImapAccountBase::JobIterator it = account->findJob( job );
584 if ( it == account->jobsEnd() )
return;
586 if (data.find(
"UID") != -1)
589 TQString oldUid = data.section(
' ', 1, 1);
590 TQString newUid = data.section(
' ', 2, 2);
593 TQValueList<ulong> olduids = KMFolderImap::splitSets(oldUid);
594 TQValueList<ulong> newuids = KMFolderImap::splitSets(newUid);
598 for ( msg = (*it).msgList.first(); msg; msg = (*it).msgList.next() )
600 ulong uid = msg->
UID();
601 index = olduids.findIndex(uid);
605 imapFolder->saveMsgMetaData( msg, newuids[index] );
612 void ImapJob::slotPutMessageInfoData(TDEIO::Job *job,
const TQString &data)
614 KMFolderImap * imapFolder =
static_cast<KMFolderImap*
>(mDestFolder->storage());
615 KMAcctImap *account = imapFolder->account();
622 ImapAccountBase::JobIterator it = account->findJob( job );
623 if ( it == account->jobsEnd() )
return;
625 if ( data.find(
"UID") != -1 )
627 ulong uid = ( data.right(data.length()-4) ).toInt();
628 if ( !(*it).msgList.isEmpty() )
630 imapFolder->saveMsgMetaData( (*it).msgList.first(), uid );
637 void ImapJob::slotCopyMessageResult( TDEIO::Job *job )
639 KMAcctImap *account =
static_cast<KMFolderImap*
>(mDestFolder->storage())->account();
646 ImapAccountBase::JobIterator it = account->findJob( job );
647 if ( it == account->jobsEnd() )
return;
651 mErrorCode = job->error();
652 TQString errStr = i18n(
"Error while copying messages.");
653 if ( (*it).progressItem )
654 (*it).progressItem->setStatus( errStr );
655 if ( account->handleJobError( job, errStr ) )
659 if ( !(*it).msgList.isEmpty() )
661 emit messageCopied((*it).msgList);
662 }
else if (mMsgList.first()) {
663 emit messageCopied(mMsgList.first());
666 if (account->slave()) {
667 account->removeJob(it);
668 account->mJobList.remove(
this);
674 void ImapJob::execute()
676 init( mType, mSets, mDestFolder?
677 dynamic_cast<KMFolderImap*
>( mDestFolder->storage() ):0, mMsgList );
681 void ImapJob::setParentFolder(
const KMFolderImap* parent )
683 mParentFolder =
const_cast<KMFolderImap*
>( parent );
687 void ImapJob::slotProcessedSize(TDEIO::Job * job, TDEIO::filesize_t processed)
693 KMFolderImap* parent = 0;
694 if ( msg->parent() && msg->parent()->folderType() == KMFolderTypeImap )
695 parent =
static_cast<KMFolderImap*
>(msg->parent()->storage());
696 else if (mDestFolder)
697 parent =
static_cast<KMFolderImap*
>(mDestFolder->storage());
699 KMAcctImap *account = parent->account();
700 if ( !account )
return;
701 ImapAccountBase::JobIterator it = account->findJob( job );
702 if ( it == account->jobsEnd() )
return;
703 (*it).done = processed;
704 if ( (*it).progressItem ) {
705 (*it).progressItem->setCompletedItems( processed );
706 (*it).progressItem->updateProgress();
708 emit progress( (*it).done, (*it).total );
713 #include "imapjob.moc"