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();
394 dataSize = Util::crlf2lf( (*it).data.data(), dataSize );
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();
413 dataSize = Util::crlf2lf( (*it).data.data(), dataSize );
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"
virtual TQString prettyURL() const
URL of the node for visualization purposes.
int open(const char *owner)
Open folder for access.
void updateBodyPart(const TQString partSpecifier, const TQByteArray &data)
Sets the body of the specified part.
DwBodyPart * getFirstDwBodyPart() const
Get the 1st DwBodyPart.
void setReadyToShow(bool v)
Set if the message is ready to be shown.
size_t msgSizeServer() const
Get/set size on server.
void setTransferInProgress(bool value, bool force=false)
Set that the message shall not be deleted because it is still required.
TQString subject() const
Get or set the 'Subject' header field.
TQCString asString() const
Return the entire message contents as a string.
bool transferInProgress() const
Return, if the message should not be deleted.
bool isMessage() const
Returns TRUE if object is a real message (not KMMsgInfo or KMMsgBase)
void setComplete(bool v)
Set if the message is a complete message.
KMMsgStatus status() const
Status of the message.
size_t msgSize() const
Get/set size of message in the folder including the whole header in bytes.
ulong UID() const
Get/set UID.
DwBodyPart * findDwBodyPart(int type, int subtype) const
Return the first DwBodyPart matching a given Content-Type or zero, if no found.