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 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <errno.h>
00033 #include <mimelib/enum.h>
00034 #include <mimelib/field.h>
00035 #include <mimelib/mimepp.h>
00036
00037 #include <qtextcodec.h>
00038
00039 #include <kdebug.h>
00040 #include <kfiledialog.h>
00041 #include <kio/netaccess.h>
00042 #include <klocale.h>
00043 #include <kmessagebox.h>
00044 #include <kparts/browserextension.h>
00045 #include <kprogress.h>
00046 #include <krun.h>
00047 #include <kbookmarkmanager.h>
00048 #include <kstandarddirs.h>
00049 #include "actionscheduler.h"
00050 using KMail::ActionScheduler;
00051 #include "mailinglist-magic.h"
00052 #include "kmaddrbook.h"
00053 #include "kmcomposewin.h"
00054 #include "kmfiltermgr.h"
00055 #include "kmfolderimap.h"
00056 #include "kmfoldermgr.h"
00057 #include "kmheaders.h"
00058 #include "kmmainwidget.h"
00059 #include "kmmsgdict.h"
00060 #include "kmsender.h"
00061 #include "undostack.h"
00062 #include "partNode.h"
00063 #include "kcursorsaver.h"
00064 #include "partNode.h"
00065 using KMail::FolderJob;
00066 #include "mailsourceviewer.h"
00067 using KMail::MailSourceViewer;
00068
00069 #include "kmcommands.h"
00070 #include "kmcommands.moc"
00071
00072 KMCommand::KMCommand( QWidget *parent )
00073 : mProgressDialog( 0 ), mDeletesItself( false ), mParent( parent )
00074 {
00075 }
00076
00077 KMCommand::KMCommand( QWidget *parent, const QPtrList<KMMsgBase> &msgList )
00078 : mProgressDialog( 0 ), mDeletesItself( false ), mParent( parent ), mMsgList( msgList )
00079 {
00080 }
00081
00082 KMCommand::KMCommand( QWidget *parent, KMMsgBase *msgBase )
00083 : mProgressDialog( 0 ), mDeletesItself( false ), mParent( parent )
00084 {
00085 mMsgList.append( msgBase );
00086 }
00087
00088 KMCommand::KMCommand( QWidget *parent, KMMessage *msg )
00089 : mProgressDialog( 0 ), mDeletesItself( false ), mParent( parent )
00090 {
00091 mMsgList.append( &msg->toMsgBase() );
00092 }
00093
00094 KMCommand::~KMCommand()
00095 {
00096 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00097 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00098 if (!(*fit))
00099 continue;
00100 (*fit)->close();
00101 }
00102 }
00103
00104 void KMCommand::start()
00105 {
00106 preTransfer();
00107 }
00108
00109
00110 const QPtrList<KMMessage> KMCommand::retrievedMsgs() const
00111 {
00112 return mRetrievedMsgs;
00113 }
00114
00115 KMMessage *KMCommand::retrievedMessage() const
00116 {
00117 return mRetrievedMsgs.getFirst();
00118 }
00119
00120 int KMCommand::mCountJobs = 0;
00121
00122 void KMCommand::preTransfer()
00123 {
00124 connect(this, SIGNAL(messagesTransfered(bool)),
00125 this, SLOT(slotPostTransfer(bool)));
00126 kmkernel->filterMgr()->ref();
00127
00128 if (mMsgList.find(0) != -1) {
00129 emit messagesTransfered(false);
00130 return;
00131 }
00132
00133 if ((mMsgList.count() == 1) &&
00134 (mMsgList.getFirst()->isMessage()) &&
00135 (mMsgList.getFirst()->parent() == 0))
00136 {
00137
00138 mRetrievedMsgs.append((KMMessage*)mMsgList.getFirst());
00139 emit messagesTransfered(true);
00140 return;
00141 }
00142
00143 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00144 if (!mb->parent()) {
00145 emit messagesTransfered(false);
00146 return;
00147 } else {
00148 mFolders.append( mb->parent() );
00149 mb->parent()->open();
00150 }
00151
00152
00153 transferSelectedMsgs();
00154 }
00155
00156 void KMCommand::slotPostTransfer(bool success)
00157 {
00158 disconnect(this, SIGNAL(messagesTransfered(bool)),
00159 this, SLOT(slotPostTransfer(bool)));
00160 if (success)
00161 execute();
00162 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00163 KMMessage* msg;
00164 while ( (msg = it.current()) != 0 )
00165 {
00166 ++it;
00167 if (msg->parent())
00168 msg->setTransferInProgress(false);
00169 }
00170 kmkernel->filterMgr()->deref();
00171 if ( !deletesItself() )
00172 delete this;
00173 }
00174
00175 void KMCommand::transferSelectedMsgs()
00176 {
00177
00178 if (KMCommand::mCountJobs > 0) {
00179 emit messagesTransfered(false);
00180 return;
00181 }
00182
00183 bool complete = true;
00184 KMCommand::mCountJobs = 0;
00185 mCountMsgs = 0;
00186 mRetrievedMsgs.clear();
00187 mCountMsgs = mMsgList.count();
00188
00189
00190
00191
00192 if ( mCountMsgs > 0 ) {
00193 mProgressDialog = new KProgressDialog(mParent, "transferProgress",
00194 i18n("Please wait"),
00195 i18n("Please wait while the message is transferred",
00196 "Please wait while the %n messages are transferred", mMsgList.count()),
00197 true);
00198 mProgressDialog->setMinimumDuration(1000);
00199 }
00200 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00201 {
00202
00203 KMMessage *thisMsg = 0;
00204 if ( mb->isMessage() )
00205 thisMsg = static_cast<KMMessage*>(mb);
00206 else
00207 {
00208 KMFolder *folder = mb->parent();
00209 int idx = folder->find(mb);
00210 if (idx < 0) continue;
00211 thisMsg = folder->getMsg(idx);
00212 }
00213 if (!thisMsg) continue;
00214 if ( thisMsg->transferInProgress() &&
00215 thisMsg->parent()->folderType() == KMFolderTypeImap )
00216 {
00217 thisMsg->setTransferInProgress( false, true );
00218 thisMsg->parent()->ignoreJobsForMessage( thisMsg );
00219 }
00220
00221 if ( thisMsg->parent() && !thisMsg->isComplete() &&
00222 ( !mProgressDialog || !mProgressDialog->wasCancelled() ) )
00223 {
00224 kdDebug(5006)<<"### INCOMPLETE with protocol = "<<thisMsg->parent()->protocol() <<endl;
00225
00226 complete = false;
00227 KMCommand::mCountJobs++;
00228 FolderJob *job = thisMsg->parent()->createJob(thisMsg);
00229
00230 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00231 this, SLOT(slotMsgTransfered(KMMessage*)));
00232
00233 connect(job, SIGNAL(finished()),
00234 this, SLOT(slotJobFinished()));
00235
00236 thisMsg->setTransferInProgress(true);
00237 job->start();
00238 } else {
00239 thisMsg->setTransferInProgress(true);
00240 mRetrievedMsgs.append(thisMsg);
00241 }
00242 }
00243
00244 if (complete)
00245 {
00246 delete mProgressDialog;
00247 emit messagesTransfered(true);
00248 } else {
00249
00250 if ( mProgressDialog ) {
00251 connect(mProgressDialog, SIGNAL(cancelClicked()),
00252 this, SLOT(slotTransferCancelled()));
00253 mProgressDialog->progressBar()->setTotalSteps(KMCommand::mCountJobs);
00254 }
00255 }
00256 }
00257
00258 void KMCommand::slotMsgTransfered(KMMessage* msg)
00259 {
00260 if ( mProgressDialog && mProgressDialog->wasCancelled() ) {
00261 emit messagesTransfered(false);
00262 return;
00263 }
00264
00265
00266 mRetrievedMsgs.append(msg);
00267 }
00268
00269 void KMCommand::slotJobFinished()
00270 {
00271
00272 KMCommand::mCountJobs--;
00273
00274 if ( mProgressDialog && mProgressDialog->wasCancelled() ) return;
00275
00276 if ( (mCountMsgs - static_cast<int>(mRetrievedMsgs.count())) > KMCommand::mCountJobs )
00277 {
00278
00279 if ( mProgressDialog )
00280 mProgressDialog->hide();
00281 slotTransferCancelled();
00282 return;
00283 }
00284
00285 if ( mProgressDialog ) {
00286 mProgressDialog->progressBar()->advance(1);
00287 mProgressDialog->setLabel(i18n("Please wait while the message is transferred",
00288 "Please wait while the %n messages are transferred", KMCommand::mCountJobs));
00289 }
00290 if (KMCommand::mCountJobs == 0)
00291 {
00292
00293 delete mProgressDialog;
00294 emit messagesTransfered(true);
00295 }
00296 }
00297
00298 void KMCommand::slotTransferCancelled()
00299 {
00300
00301 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00302 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00303 if (!(*fit))
00304 continue;
00305 KMFolder *folder = *fit;
00306 KMFolderImap *imapFolder = dynamic_cast<KMFolderImap*>(folder);
00307 if (imapFolder && imapFolder->account()) {
00308 imapFolder->account()->killAllJobs();
00309 imapFolder->account()->setIdle(true);
00310 }
00311 }
00312
00313 KMCommand::mCountJobs = 0;
00314 mCountMsgs = 0;
00315
00316 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00317 KMMessage* msg;
00318 while ( (msg = it.current()) != 0 )
00319 {
00320 KMFolder *folder = msg->parent();
00321 ++it;
00322 if (!folder)
00323 continue;
00324 msg->setTransferInProgress(false);
00325 int idx = folder->find(msg);
00326 if (idx > 0) folder->unGetMsg(idx);
00327 }
00328 mRetrievedMsgs.clear();
00329 emit messagesTransfered(false);
00330 }
00331
00332 KMMailtoComposeCommand::KMMailtoComposeCommand( const KURL &url,
00333 KMMessage *msg )
00334 :mUrl( url ), mMessage( msg )
00335 {
00336 }
00337
00338 void KMMailtoComposeCommand::execute()
00339 {
00340 KMComposeWin *win;
00341 KMMessage *msg = new KMMessage;
00342 uint id = 0;
00343
00344 if ( mMessage && mMessage->parent() )
00345 id = mMessage->parent()->identity();
00346
00347 msg->initHeader(id);
00348 msg->setCharset("utf-8");
00349 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00350
00351 win = new KMComposeWin(msg, id);
00352 win->setCharset("", TRUE);
00353 win->setFocusToSubject();
00354 win->show();
00355 }
00356
00357
00358 KMMailtoReplyCommand::KMMailtoReplyCommand( QWidget *parent,
00359 const KURL &url, KMMessage *msg, const QString &selection )
00360 :KMCommand( parent, msg ), mUrl( url ), mSelection( selection )
00361 {
00362 }
00363
00364 void KMMailtoReplyCommand::execute()
00365 {
00366
00367 KMMessage *msg = retrievedMessage();
00368 KMComposeWin *win;
00369 KMMessage *rmsg = msg->createReply( KMail::ReplyNone, mSelection );
00370 rmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00371
00372 win = new KMComposeWin(rmsg, 0);
00373 win->setCharset(msg->codec()->mimeName(), TRUE);
00374 win->setReplyFocus();
00375 win->show();
00376 }
00377
00378
00379 KMMailtoForwardCommand::KMMailtoForwardCommand( QWidget *parent,
00380 const KURL &url, KMMessage *msg )
00381 :KMCommand( parent, msg ), mUrl( url )
00382 {
00383 }
00384
00385 void KMMailtoForwardCommand::execute()
00386 {
00387
00388 KMMessage *msg = retrievedMessage();
00389 KMComposeWin *win;
00390 KMMessage *fmsg = msg->createForward();
00391 fmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00392
00393 win = new KMComposeWin(fmsg);
00394 win->setCharset(msg->codec()->mimeName(), TRUE);
00395 win->show();
00396 }
00397
00398
00399 KMAddBookmarksCommand::KMAddBookmarksCommand( const KURL &url, QWidget *parent )
00400 :mUrl( url ), mParent( parent )
00401 {
00402 }
00403
00404 void KMAddBookmarksCommand::execute()
00405 {
00406 QString filename = locateLocal( "data", QString::fromLatin1("konqueror/bookmarks.xml") );
00407 KBookmarkManager *bookManager = KBookmarkManager::managerForFile( filename,
00408 false );
00409 KBookmarkGroup group = bookManager->root();
00410 group.addBookmark( bookManager, mUrl.path(), KURL( mUrl ) );
00411 bookManager->save();
00412 }
00413
00414 KMMailtoAddAddrBookCommand::KMMailtoAddAddrBookCommand( const KURL &url,
00415 QWidget *parent )
00416 :mUrl( url ), mParent( parent )
00417 {
00418 }
00419
00420 void KMMailtoAddAddrBookCommand::execute()
00421 {
00422 KMAddrBookExternal::addEmail( KMMessage::decodeMailtoUrl( mUrl.path() ), mParent );
00423 }
00424
00425
00426 KMMailtoOpenAddrBookCommand::KMMailtoOpenAddrBookCommand( const KURL &url,
00427 QWidget *parent )
00428 :mUrl( url ), mParent( parent )
00429 {
00430 }
00431
00432 void KMMailtoOpenAddrBookCommand::execute()
00433 {
00434 KMAddrBookExternal::openEmail( KMMessage::decodeMailtoUrl( mUrl.path() ), mParent );
00435 }
00436
00437
00438 KMUrlCopyCommand::KMUrlCopyCommand( const KURL &url, KMMainWidget *mainWidget )
00439 :mUrl( url ), mMainWidget( mainWidget )
00440 {
00441 }
00442
00443 void KMUrlCopyCommand::execute()
00444 {
00445 QClipboard* clip = QApplication::clipboard();
00446
00447 if (mUrl.protocol() == "mailto") {
00448
00449 QString address = KMMessage::decodeMailtoUrl( mUrl.path() );
00450 clip->setSelectionMode( true );
00451 clip->setText( address );
00452 clip->setSelectionMode( false );
00453 clip->setText( address );
00454 if (mMainWidget)
00455 mMainWidget->statusMsg( i18n( "Address copied to clipboard." ));
00456 } else {
00457
00458 clip->setSelectionMode( true );
00459 clip->setText( mUrl.url() );
00460 clip->setSelectionMode( false );
00461 clip->setText( mUrl.url() );
00462 if ( mMainWidget )
00463 mMainWidget->statusMsg( i18n( "URL copied to clipboard." ));
00464 }
00465 }
00466
00467
00468 KMUrlOpenCommand::KMUrlOpenCommand( const KURL &url, KMReaderWin *readerWin )
00469 :mUrl( url ), mReaderWin( readerWin )
00470 {
00471 }
00472
00473 void KMUrlOpenCommand::execute()
00474 {
00475 if (mUrl.isEmpty()) return;
00476 mReaderWin->slotUrlOpen( mUrl, KParts::URLArgs() );
00477 }
00478
00479
00480 KMUrlSaveCommand::KMUrlSaveCommand( const KURL &url, QWidget *parent )
00481 :mUrl( url ), mParent( parent )
00482 {
00483 }
00484
00485 void KMUrlSaveCommand::execute()
00486 {
00487 if (mUrl.isEmpty()) return;
00488 KURL saveUrl = KFileDialog::getSaveURL(mUrl.fileName(), QString::null,
00489 mParent);
00490 if (saveUrl.isEmpty()) return;
00491 if (KIO::NetAccess::exists(saveUrl, false, mParent))
00492 {
00493 if (KMessageBox::warningContinueCancel(0,
00494 i18n("<qt>File <b>%1</b> exists.<br>Do you want to replace it?</qt>")
00495 .arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00496 != KMessageBox::Continue)
00497 return;
00498 }
00499 KIO::Job *job = KIO::file_copy(mUrl, saveUrl, -1, true);
00500 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotUrlSaveResult(KIO::Job*)));
00501 }
00502
00503 void KMUrlSaveCommand::slotUrlSaveResult( KIO::Job *job )
00504 {
00505 if (job->error()) job->showErrorDialog();
00506 }
00507
00508
00509 KMEditMsgCommand::KMEditMsgCommand( QWidget *parent, KMMessage *msg )
00510 :KMCommand( parent, msg )
00511 {
00512 }
00513
00514 void KMEditMsgCommand::execute()
00515 {
00516 KMMessage *msg = retrievedMessage();
00517 if (!msg || !msg->parent() ||
00518 !kmkernel->folderIsDraftOrOutbox( msg->parent() ))
00519 return;
00520
00521
00522
00523
00524 KMFolder *parent = msg->parent();
00525 if ( parent )
00526 parent->take( parent->find( msg ) );
00527 #if 0
00528
00529 mHeaders->setSelected(mHeaders->currentItem(), TRUE);
00530 mHeaders->highlightMessage(mHeaders->currentItem(), true);
00531 #endif
00532
00533 KMComposeWin *win = new KMComposeWin();
00534 #if 0
00535
00536 QObject::connect( win, SIGNAL( messageQueuedOrDrafted()),
00537 this, SLOT( slotMessageQueuedOrDrafted()) );
00538 #endif
00539 msg->setTransferInProgress(false);
00540 win->setMsg(msg, FALSE, TRUE);
00541 win->setFolder( parent );
00542 win->show();
00543 }
00544
00545
00546 KMShowMsgSrcCommand::KMShowMsgSrcCommand( QWidget *parent,
00547 KMMessage *msg, bool fixedFont )
00548 :KMCommand( parent, msg ), mFixedFont( fixedFont )
00549 {
00550 }
00551
00552 void KMShowMsgSrcCommand::execute()
00553 {
00554 KMMessage *msg = retrievedMessage();
00555 QString str = QString::fromLatin1( msg->asString() );
00556
00557 MailSourceViewer *viewer = new MailSourceViewer();
00558 viewer->setCaption( i18n("Message as Plain Text") );
00559 viewer->setText(str);
00560 if( mFixedFont )
00561 viewer->setFont(KGlobalSettings::fixedFont());
00562
00563
00564
00565
00566 if (QApplication::desktop()->isVirtualDesktop()) {
00567 int scnum = QApplication::desktop()->screenNumber(QCursor::pos());
00568 viewer->resize(QApplication::desktop()->screenGeometry(scnum).width()/2,
00569 2*QApplication::desktop()->screenGeometry(scnum).height()/3);
00570 } else {
00571 viewer->resize(QApplication::desktop()->geometry().width()/2,
00572 2*QApplication::desktop()->geometry().height()/3);
00573 }
00574 viewer->show();
00575 }
00576
00577 namespace {
00578 KURL subjectToUrl( const QString & subject ) {
00579 return KFileDialog::getSaveURL( subject.mid( subject.findRev(':') + 1 )
00580 .stripWhiteSpace()
00581 .replace( QDir::separator(), '_' ),
00582 QString::null );
00583 }
00584 }
00585
00586 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent, KMMessage * msg )
00587 : KMCommand( parent ),
00588 mMsgListIndex( 0 ),
00589 mOffset( 0 ),
00590 mTotalSize( msg ? msg->msgSize() : 0 )
00591 {
00592 if ( !msg ) return;
00593 setDeletesItself( true );
00594 mMsgList.append( msg->getMsgSerNum() );
00595 mUrl = subjectToUrl( msg->subject() );
00596 }
00597
00598 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent,
00599 const QPtrList<KMMsgBase> &msgList )
00600 : KMCommand( parent ),
00601 mMsgListIndex( 0 ),
00602 mOffset( 0 ),
00603 mTotalSize( 0 )
00604 {
00605 if (!msgList.getFirst())
00606 return;
00607 setDeletesItself( true );
00608 KMMsgBase *msgBase = msgList.getFirst();
00609
00610
00611
00612
00613 QPtrListIterator<KMMsgBase> it(msgList);
00614 while ( it.current() ) {
00615 mMsgList.append( (*it)->getMsgSerNum() );
00616 mTotalSize += (*it)->msgSize();
00617 if ((*it)->parent() != 0)
00618 (*it)->parent()->open();
00619 ++it;
00620 }
00621 mMsgListIndex = 0;
00622 mUrl = subjectToUrl( msgBase->subject() );
00623 }
00624
00625 KURL KMSaveMsgCommand::url()
00626 {
00627 return mUrl;
00628 }
00629
00630 void KMSaveMsgCommand::execute()
00631 {
00632 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, false, false );
00633 mJob->slotTotalSize( mTotalSize );
00634 mJob->setAsyncDataEnabled( true );
00635 mJob->setReportDataSent( true );
00636 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00637 SLOT(slotSaveDataReq()));
00638 connect(mJob, SIGNAL(result(KIO::Job*)),
00639 SLOT(slotSaveResult(KIO::Job*)));
00640 }
00641
00642 void KMSaveMsgCommand::slotSaveDataReq()
00643 {
00644 int remainingBytes = mData.size() - mOffset;
00645 if ( remainingBytes > 0 ) {
00646
00647 if ( remainingBytes > MAX_CHUNK_SIZE )
00648 remainingBytes = MAX_CHUNK_SIZE;
00649
00650 QByteArray data;
00651 data.duplicate( mData.data() + mOffset, remainingBytes );
00652 mJob->sendAsyncData( data );
00653 mOffset += remainingBytes;
00654 return;
00655 }
00656
00657 if ( mMsgListIndex < mMsgList.size() ) {
00658 KMMessage *msg = 0;
00659 int idx = -1;
00660 KMFolder * p = 0;
00661 kmkernel->msgDict()->getLocation( mMsgList[mMsgListIndex], &p, &idx );
00662 assert( p );
00663 assert( idx >= 0 );
00664 msg = p->getMsg(idx);
00665
00666 if (msg->transferInProgress()) {
00667 QByteArray data = QByteArray();
00668 mJob->sendAsyncData( data );
00669 }
00670 msg->setTransferInProgress( true );
00671 if (msg->isComplete() ) {
00672 slotMessageRetrievedForSaving(msg);
00673 } else {
00674
00675 if (msg->parent() && !msg->isComplete() ) {
00676 FolderJob *job = msg->parent()->createJob(msg);
00677 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00678 this, SLOT(slotMessageRetrievedForSaving(KMMessage*)));
00679 job->start();
00680 }
00681 }
00682 } else {
00683
00684 QByteArray data = QByteArray();
00685 mJob->sendAsyncData( data );
00686 }
00687 }
00688
00689 void KMSaveMsgCommand::slotMessageRetrievedForSaving(KMMessage *msg)
00690 {
00691 QCString str( msg->fromEmail() );
00692 if ( str.isEmpty() )
00693 str = "unknown@unknown.invalid";
00694 str = "From " + str + " " + msg->dateShortStr() + "\n";
00695 str += KMFolderMbox::escapeFrom( msg->asString() );
00696 str += "\n";
00697 msg->setTransferInProgress(false);
00698
00699 mData = str;
00700 mData.resize(mData.size() - 1);
00701 mOffset = 0;
00702 QByteArray data;
00703 int size;
00704
00705 if( mData.size() > (unsigned int) MAX_CHUNK_SIZE )
00706 size = MAX_CHUNK_SIZE;
00707 else
00708 size = mData.size();
00709
00710 data.duplicate( mData, size );
00711 mJob->sendAsyncData( data );
00712 mOffset += size;
00713 ++mMsgListIndex;
00714
00715 if (msg->parent()) {
00716 int idx = -1;
00717 KMFolder * p = 0;
00718 kmkernel->msgDict()->getLocation( msg, &p, &idx );
00719 assert( p == msg->parent() ); assert( idx >= 0 );
00720 p->unGetMsg( idx );
00721 p->close();
00722 }
00723 }
00724
00725 void KMSaveMsgCommand::slotSaveResult(KIO::Job *job)
00726 {
00727 if (job->error())
00728 {
00729 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST)
00730 {
00731 if (KMessageBox::warningContinueCancel(0,
00732 i18n("File %1 exists.\nDo you want to replace it?")
00733 .arg(mUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00734 == KMessageBox::Continue) {
00735 mOffset = 0;
00736
00737 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, true, false );
00738 mJob->slotTotalSize( mTotalSize );
00739 mJob->setAsyncDataEnabled( true );
00740 mJob->setReportDataSent( true );
00741 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00742 SLOT(slotSaveDataReq()));
00743 connect(mJob, SIGNAL(result(KIO::Job*)),
00744 SLOT(slotSaveResult(KIO::Job*)));
00745 }
00746 }
00747 else
00748 {
00749 job->showErrorDialog();
00750 delete this;
00751 }
00752 } else {
00753 delete this;
00754 }
00755 }
00756
00757
00758
00759 KMReplyToCommand::KMReplyToCommand( QWidget *parent, KMMessage *msg,
00760 const QString &selection )
00761 : KMCommand( parent, msg ), mSelection( selection )
00762 {
00763 }
00764
00765 void KMReplyToCommand::execute()
00766 {
00767 KCursorSaver busy(KBusyPtr::busy());
00768 KMMessage *msg = retrievedMessage();
00769 KMMessage *reply = msg->createReply( KMail::ReplySmart, mSelection );
00770 KMComposeWin *win = new KMComposeWin( reply );
00771 win->setCharset( msg->codec()->mimeName(), TRUE );
00772 win->setReplyFocus();
00773 win->show();
00774 }
00775
00776
00777 KMNoQuoteReplyToCommand::KMNoQuoteReplyToCommand( QWidget *parent,
00778 KMMessage *msg )
00779 : KMCommand( parent, msg )
00780 {
00781 }
00782
00783 void KMNoQuoteReplyToCommand::execute()
00784 {
00785 KCursorSaver busy(KBusyPtr::busy());
00786 KMMessage *msg = retrievedMessage();
00787 KMMessage *reply = msg->createReply( KMail::ReplySmart, "", TRUE);
00788 KMComposeWin *win = new KMComposeWin( reply );
00789 win->setCharset(msg->codec()->mimeName(), TRUE);
00790 win->setReplyFocus(false);
00791 win->show();
00792 }
00793
00794
00795 KMReplyListCommand::KMReplyListCommand( QWidget *parent,
00796 KMMessage *msg, const QString &selection )
00797 : KMCommand( parent, msg ), mSelection( selection )
00798 {
00799 }
00800
00801 void KMReplyListCommand::execute()
00802 {
00803 KCursorSaver busy(KBusyPtr::busy());
00804 KMMessage *msg = retrievedMessage();
00805 KMMessage *reply = msg->createReply( KMail::ReplyList, mSelection);
00806 KMComposeWin *win = new KMComposeWin( reply );
00807 win->setCharset(msg->codec()->mimeName(), TRUE);
00808 win->setReplyFocus(false);
00809 win->show();
00810 }
00811
00812
00813 KMReplyToAllCommand::KMReplyToAllCommand( QWidget *parent,
00814 KMMessage *msg, const QString &selection )
00815 :KMCommand( parent, msg ), mSelection( selection )
00816 {
00817 }
00818
00819 void KMReplyToAllCommand::execute()
00820 {
00821 KCursorSaver busy(KBusyPtr::busy());
00822 KMMessage *msg = retrievedMessage();
00823 KMMessage *reply = msg->createReply( KMail::ReplyAll, mSelection );
00824 KMComposeWin *win = new KMComposeWin( reply );
00825 win->setCharset( msg->codec()->mimeName(), TRUE );
00826 win->setReplyFocus();
00827 win->show();
00828 }
00829
00830
00831 KMReplyAuthorCommand::KMReplyAuthorCommand( QWidget *parent, KMMessage *msg,
00832 const QString &selection )
00833 : KMCommand( parent, msg ), mSelection( selection )
00834 {
00835 }
00836
00837 void KMReplyAuthorCommand::execute()
00838 {
00839 KCursorSaver busy(KBusyPtr::busy());
00840 KMMessage *msg = retrievedMessage();
00841 KMMessage *reply = msg->createReply( KMail::ReplyAuthor, mSelection );
00842 KMComposeWin *win = new KMComposeWin( reply );
00843 win->setCharset( msg->codec()->mimeName(), TRUE );
00844 win->setReplyFocus();
00845 win->show();
00846 }
00847
00848
00849 KMForwardCommand::KMForwardCommand( QWidget *parent,
00850 const QPtrList<KMMsgBase> &msgList, uint identity )
00851 : KMCommand( parent, msgList ),
00852 mParent( parent ),
00853 mIdentity( identity )
00854 {
00855 }
00856
00857 KMForwardCommand::KMForwardCommand( QWidget *parent, KMMessage *msg,
00858 uint identity )
00859 : KMCommand( parent, msg ),
00860 mParent( parent ),
00861 mIdentity( identity )
00862 {
00863 }
00864
00865 void KMForwardCommand::execute()
00866 {
00867 KMComposeWin *win;
00868 QPtrList<KMMessage> msgList = retrievedMsgs();
00869
00870 if (msgList.count() >= 2) {
00871
00872
00873 if (KMessageBox::questionYesNo(mParent, i18n("Forward selected messages as"
00874 " a MIME digest?"))
00875 == KMessageBox::Yes) {
00876 uint id = 0;
00877 KMMessage *fwdMsg = new KMMessage;
00878 KMMessagePart *msgPart = new KMMessagePart;
00879 QString msgPartText;
00880 int msgCnt = 0;
00881
00882
00883
00884 fwdMsg->initHeader(id);
00885 fwdMsg->setAutomaticFields(true);
00886 fwdMsg->mMsg->Headers().ContentType().CreateBoundary(1);
00887 QCString boundary( fwdMsg->mMsg->Headers().ContentType().Boundary().c_str() );
00888 msgPartText = i18n("\nThis is a MIME digest forward. The content of the"
00889 " message is contained in the attachment(s).\n\n\n");
00890
00891 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
00892
00893 if (id == 0)
00894 id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
00895
00896 msgPartText += "--";
00897 msgPartText += QString::fromLatin1( boundary );
00898 msgPartText += "\nContent-Type: MESSAGE/RFC822";
00899 msgPartText += QString("; CHARSET=%1").arg(msg->charset());
00900 msgPartText += "\n";
00901 DwHeaders dwh;
00902 dwh.MessageId().CreateDefault();
00903 msgPartText += QString("Content-ID: %1\n").arg(dwh.MessageId().AsString().c_str());
00904 msgPartText += QString("Content-Description: %1").arg(msg->subject());
00905 if (!msg->subject().contains("(fwd)"))
00906 msgPartText += " (fwd)";
00907 msgPartText += "\n\n";
00908
00909 msg->removePrivateHeaderFields();
00910 msg->removeHeaderField("BCC");
00911
00912 msgPartText += msg->headerAsString();
00913 msgPartText += "\n";
00914 msgPartText += msg->body();
00915 msgPartText += "\n";
00916 msgCnt++;
00917 fwdMsg->link(msg, KMMsgStatusForwarded);
00918 }
00919 if ( id == 0 )
00920 id = mIdentity;
00921 fwdMsg->initHeader(id);
00922 msgPartText += "--";
00923 msgPartText += QString::fromLatin1( boundary );
00924 msgPartText += "--\n";
00925 QCString tmp;
00926 msgPart->setTypeStr("MULTIPART");
00927 tmp.sprintf( "Digest; boundary=\"%s\"", boundary.data() );
00928 msgPart->setSubtypeStr( tmp );
00929 msgPart->setName("unnamed");
00930 msgPart->setCte(DwMime::kCte7bit);
00931 msgPart->setContentDescription(QString("Digest of %1 messages.").arg(msgCnt));
00932
00933 msgPart->setBodyEncoded(QCString(msgPartText.ascii()));
00934 KCursorSaver busy(KBusyPtr::busy());
00935 win = new KMComposeWin(fwdMsg, id);
00936 win->addAttach(msgPart);
00937 win->show();
00938 return;
00939 } else {
00940 uint id = 0;
00941 QCString msgText = "";
00942 QPtrList<KMMessage> linklist;
00943 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
00944
00945 if (id == 0)
00946 id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
00947
00948 msgText += msg->createForwardBody();
00949 linklist.append(msg);
00950 }
00951 if ( id == 0 )
00952 id = mIdentity;
00953 KMMessage *fwdMsg = new KMMessage;
00954 fwdMsg->initHeader(id);
00955 fwdMsg->setAutomaticFields(true);
00956 fwdMsg->setCharset("utf-8");
00957 fwdMsg->setBody(msgText);
00958
00959 for (KMMessage *msg = linklist.first(); msg; msg = linklist.next())
00960 fwdMsg->link(msg, KMMsgStatusForwarded);
00961
00962 KCursorSaver busy(KBusyPtr::busy());
00963 win = new KMComposeWin(fwdMsg, id);
00964 win->setCharset("");
00965 win->show();
00966 return;
00967 }
00968 }
00969
00970
00971
00972 KMMessage *msg = msgList.getFirst();
00973 if (!msg || !msg->codec()) return;
00974
00975 KCursorSaver busy(KBusyPtr::busy());
00976 win = new KMComposeWin(msg->createForward());
00977 win->setCharset(msg->codec()->mimeName(), TRUE);
00978 win->show();
00979 }
00980
00981
00982 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
00983 const QPtrList<KMMsgBase> &msgList, uint identity, KMComposeWin *win )
00984 : KMCommand( parent, msgList ), mIdentity( identity ),
00985 mWin( QGuardedPtr< KMComposeWin >( win ))
00986 {
00987 }
00988
00989 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
00990 KMMessage * msg, uint identity, KMComposeWin *win )
00991 : KMCommand( parent, msg ), mIdentity( identity ),
00992 mWin( QGuardedPtr< KMComposeWin >( win ))
00993 {
00994 }
00995
00996 void KMForwardAttachedCommand::execute()
00997 {
00998 QPtrList<KMMessage> msgList = retrievedMsgs();
00999 KMMessage *fwdMsg = new KMMessage;
01000
01001 if (msgList.count() >= 2) {
01002
01003
01004 fwdMsg->initHeader(mIdentity);
01005 }
01006 else if (msgList.count() == 1) {
01007 KMMessage *msg = msgList.getFirst();
01008 fwdMsg->initFromMessage(msg);
01009 fwdMsg->setSubject( msg->forwardSubject() );
01010 }
01011
01012 fwdMsg->setAutomaticFields(true);
01013
01014 KCursorSaver busy(KBusyPtr::busy());
01015 if (!mWin)
01016 mWin = new KMComposeWin(fwdMsg, mIdentity);
01017
01018
01019 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01020
01021 msg->removePrivateHeaderFields();
01022 msg->removeHeaderField("BCC");
01023
01024 KMMessagePart *msgPart = new KMMessagePart;
01025 msgPart->setTypeStr("message");
01026 msgPart->setSubtypeStr("rfc822");
01027 msgPart->setCharset(msg->charset());
01028 msgPart->setName("forwarded message");
01029 msgPart->setContentDescription(msg->from()+": "+msg->subject());
01030 msgPart->setContentDisposition( "inline" );
01031
01032 QValueList<int> dummy;
01033 msgPart->setBodyAndGuessCte(msg->asString(), dummy, true);
01034 msgPart->setCharset("");
01035
01036 fwdMsg->link(msg, KMMsgStatusForwarded);
01037 mWin->addAttach(msgPart);
01038 }
01039
01040 mWin->show();
01041 }
01042
01043
01044 KMRedirectCommand::KMRedirectCommand( QWidget *parent,
01045 KMMessage *msg )
01046 : KMCommand( parent, msg )
01047 {
01048 }
01049
01050 void KMRedirectCommand::execute()
01051 {
01052
01053 KMComposeWin *win;
01054 KMMessage *msg = retrievedMessage();
01055 if (!msg || !msg->codec()) return;
01056
01057 KCursorSaver busy(KBusyPtr::busy());
01058 win = new KMComposeWin();
01059 win->setMsg(msg->createRedirect(), FALSE);
01060 win->setCharset(msg->codec()->mimeName());
01061 win->show();
01062 }
01063
01064
01065 KMBounceCommand::KMBounceCommand( QWidget *parent,
01066 KMMessage *msg )
01067 : KMCommand( parent, msg )
01068 {
01069 }
01070
01071 void KMBounceCommand::execute()
01072 {
01073 KMMessage *msg = retrievedMessage();
01074 KMMessage *newMsg = msg->createBounce( TRUE );
01075 if (newMsg)
01076 kmkernel->msgSender()->send(newMsg, kmkernel->msgSender()->sendImmediate());
01077 }
01078
01079
01080 KMPrintCommand::KMPrintCommand( QWidget *parent,
01081 KMMessage *msg, bool htmlOverride )
01082 : KMCommand( parent, msg ), mHtmlOverride( htmlOverride )
01083 {
01084 }
01085
01086 void KMPrintCommand::execute()
01087 {
01088 KMReaderWin printWin( 0, 0, 0 );
01089 printWin.setPrinting(TRUE);
01090 printWin.readConfig();
01091 printWin.setHtmlOverride( mHtmlOverride );
01092 printWin.setMsg(retrievedMessage(), TRUE);
01093 printWin.printMsg();
01094 }
01095
01096
01097 KMSetStatusCommand::KMSetStatusCommand( KMMsgStatus status,
01098 const QValueList<Q_UINT32> &serNums, bool toggle )
01099 : mStatus( status ), mSerNums( serNums ), mToggle( toggle )
01100 {
01101 }
01102
01103 void KMSetStatusCommand::execute()
01104 {
01105 QValueListIterator<Q_UINT32> it;
01106 int idx = -1;
01107 KMFolder *folder = 0;
01108 bool parentStatus = false;
01109
01110
01111
01112 if (mToggle) {
01113 KMMsgBase *msg;
01114 kmkernel->msgDict()->getLocation( *mSerNums.begin(), &folder, &idx );
01115 if (folder) {
01116 msg = folder->getMsgBase(idx);
01117 if (msg && (msg->status()&mStatus))
01118 parentStatus = true;
01119 else
01120 parentStatus = false;
01121 }
01122 }
01123 QMap< KMFolder*, QValueList<int> > folderMap;
01124 for ( it = mSerNums.begin(); it != mSerNums.end(); ++it ) {
01125 kmkernel->msgDict()->getLocation( *it, &folder, &idx );
01126 if (folder) {
01127 if (mToggle) {
01128 KMMsgBase *msg = folder->getMsgBase(idx);
01129
01130 if (msg) {
01131 bool myStatus;
01132 if (msg->status()&mStatus)
01133 myStatus = true;
01134 else
01135 myStatus = false;
01136 if (myStatus != parentStatus)
01137 continue;
01138 }
01139 }
01140
01141
01142 folderMap[folder].append(idx);
01143 }
01144 }
01145 QMapIterator< KMFolder*, QValueList<int> > it2 = folderMap.begin();
01146 while ( it2 != folderMap.end() ) {
01147 KMFolder *f = it2.key();
01148 f->setStatus( (*it2), mStatus, mToggle );
01149 ++it2;
01150 }
01151 }
01152
01153
01154 KMFilterCommand::KMFilterCommand( const QCString &field, const QString &value )
01155 : mField( field ), mValue( value )
01156 {
01157 }
01158
01159 void KMFilterCommand::execute()
01160 {
01161 kmkernel->filterMgr()->createFilter( mField, mValue );
01162 }
01163
01164
01165 KMMailingListFilterCommand::KMMailingListFilterCommand( QWidget *parent,
01166 KMMessage *msg )
01167 : KMCommand( parent, msg )
01168 {
01169 }
01170
01171 KMFilterActionCommand::KMFilterActionCommand( QWidget *parent,
01172 const QPtrList<KMMsgBase> &msgList,
01173 KMFilter *filter )
01174 : KMCommand( parent, msgList ), mFilter( filter )
01175 {
01176 }
01177
01178 void KMFilterActionCommand::execute()
01179 {
01180 QPtrList<KMMessage> msgList = retrievedMsgs();
01181
01182 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next())
01183 kmkernel->filterMgr()->tempOpenFolder(msg->parent());
01184
01185 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01186 msg->setTransferInProgress(false);
01187
01188 int filterResult = kmkernel->filterMgr()->process(msg, mFilter);
01189 if (filterResult == 2) {
01190
01191 perror("Critical error");
01192 kmkernel->emergencyExit( i18n("Not enough free disk space?" ));
01193 }
01194 msg->setTransferInProgress(true);
01195 }
01196 }
01197
01198
01199 KMMetaFilterActionCommand::KMMetaFilterActionCommand( KMFilter *filter,
01200 KMHeaders *headers,
01201 KMMainWidget *main )
01202 : QObject( main ),
01203 mFilter( filter ), mHeaders( headers ), mMainWidget( main )
01204 {
01205 }
01206
01207 void KMMetaFilterActionCommand::start()
01208 {
01209 #if 0 // use action scheduler
01210 KMFilterMgr::FilterSet set = KMFilterMgr::All;
01211 QPtrList<KMFilter> filters;
01212 filters.append( mFilter );
01213 ActionScheduler *scheduler = new ActionScheduler( set, filters, mHeaders );
01214 scheduler->setAlwaysMatch( true );
01215 scheduler->setAutoDestruct( true );
01216
01217 int contentX, contentY;
01218 KMHeaderItem *nextItem = mHeaders->prepareMove( &contentX, &contentY );
01219 QPtrList<KMMsgBase> msgList = *mHeaders->selectedMsgs(true);
01220 mHeaders->finalizeMove( nextItem, contentX, contentY );
01221
01222
01223 for (KMMsgBase *msg = msgList.first(); msg; msg = msgList.next())
01224 scheduler->execFilters( msg );
01225 #else
01226 KMCommand *filterCommand = new KMFilterActionCommand( mMainWidget,
01227 *mHeaders->selectedMsgs(), mFilter);
01228 filterCommand->start();
01229 #endif
01230 }
01231
01232
01233 void KMMailingListFilterCommand::execute()
01234 {
01235 QCString name;
01236 QString value;
01237 KMMessage *msg = retrievedMessage();
01238 if (!msg)
01239 return;
01240
01241 if (!KMMLInfo::name( msg, name, value ).isNull())
01242 kmkernel->filterMgr()->createFilter( name, value );
01243 }
01244
01245
01246 QPopupMenu* KMMenuCommand::folderToPopupMenu(bool move,
01247 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01248 {
01249 while ( menu->count() )
01250 {
01251 QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
01252 if (popup)
01253 delete popup;
01254 else
01255 menu->removeItemAt( 0 );
01256 }
01257
01258 if (!kmkernel->imapFolderMgr()->dir().first()) {
01259 KMMenuCommand::makeFolderMenu( &kmkernel->folderMgr()->dir(), move,
01260 receiver, aMenuToFolder, menu );
01261 } else {
01262
01263 QPopupMenu* subMenu = new QPopupMenu(menu);
01264 subMenu = KMMenuCommand::makeFolderMenu( &kmkernel->folderMgr()->dir(),
01265 move, receiver, aMenuToFolder, subMenu );
01266 menu->insertItem( i18n( "Local Folders" ), subMenu );
01267 KMFolderDir* fdir = &kmkernel->imapFolderMgr()->dir();
01268 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01269 if (node->isDir())
01270 continue;
01271 subMenu = new QPopupMenu(menu);
01272 subMenu = makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01273 menu->insertItem( node->label(), subMenu );
01274 }
01275 }
01276
01277 return menu;
01278 }
01279
01280 QPopupMenu* KMMenuCommand::makeFolderMenu(KMFolderNode* node, bool move,
01281 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01282 {
01283
01284 if (move)
01285 {
01286 disconnect(menu, SIGNAL(activated(int)), receiver,
01287 SLOT(moveSelectedToFolder(int)));
01288 connect(menu, SIGNAL(activated(int)), receiver,
01289 SLOT(moveSelectedToFolder(int)));
01290 } else {
01291 disconnect(menu, SIGNAL(activated(int)), receiver,
01292 SLOT(copySelectedToFolder(int)));
01293 connect(menu, SIGNAL(activated(int)), receiver,
01294 SLOT(copySelectedToFolder(int)));
01295 }
01296
01297 KMFolder *folder = 0;
01298 KMFolderDir *folderDir = 0;
01299 if (node->isDir()) {
01300 folderDir = static_cast<KMFolderDir*>(node);
01301 } else {
01302 folder = static_cast<KMFolder*>(node);
01303 folderDir = folder->child();
01304 }
01305
01306 if (folder && !folder->noContent())
01307 {
01308 int menuId;
01309 if (move)
01310 menuId = menu->insertItem(i18n("Move to This Folder"));
01311 else
01312 menuId = menu->insertItem(i18n("Copy to This Folder"));
01313 aMenuToFolder->insert( menuId, folder );
01314 menu->insertSeparator();
01315 }
01316
01317 if (!folderDir)
01318 return menu;
01319
01320 for (KMFolderNode *it = folderDir->first(); it; it = folderDir->next() ) {
01321 if (it->isDir())
01322 continue;
01323 KMFolder *child = static_cast<KMFolder*>(it);
01324 QString label = child->label();
01325 label.replace("&","&&");
01326 if (child->child() && child->child()->first()) {
01327
01328 QPopupMenu *subMenu = makeFolderMenu(child, move, receiver,
01329 aMenuToFolder, new QPopupMenu(menu, "subMenu"));
01330 menu->insertItem(label, subMenu);
01331 } else {
01332
01333 int menuId = menu->insertItem(label);
01334 aMenuToFolder->insert( menuId, child );
01335 }
01336 }
01337 return menu;
01338 }
01339
01340
01341 KMCopyCommand::KMCopyCommand( KMFolder* destFolder,
01342 const QPtrList<KMMsgBase> &msgList )
01343 :mDestFolder( destFolder ), mMsgList( msgList )
01344 {
01345 }
01346
01347 KMCopyCommand::KMCopyCommand( KMFolder* destFolder, KMMessage * msg )
01348 :mDestFolder( destFolder )
01349 {
01350 mMsgList.append( &msg->toMsgBase() );
01351 }
01352
01353 void KMCopyCommand::execute()
01354 {
01355 KMMsgBase *msgBase;
01356 KMMessage *msg, *newMsg;
01357 int idx = -1;
01358 bool isMessage;
01359 QPtrList<KMMessage> list;
01360
01361 KCursorSaver busy(KBusyPtr::busy());
01362
01363 for (msgBase = mMsgList.first(); msgBase; msgBase = mMsgList.next() )
01364 {
01365 KMFolder *srcFolder = msgBase->parent();
01366 if (isMessage = msgBase->isMessage())
01367 {
01368 msg = static_cast<KMMessage*>(msgBase);
01369 } else {
01370 idx = srcFolder->find(msgBase);
01371 assert(idx != -1);
01372 msg = srcFolder->getMsg(idx);
01373 }
01374
01375 if (srcFolder &&
01376 (srcFolder->folderType()== KMFolderTypeImap) &&
01377 (mDestFolder->folderType() == KMFolderTypeImap) &&
01378 (static_cast<KMFolderImap*>(srcFolder)->account() ==
01379 static_cast<KMFolderImap*>(mDestFolder)->account()))
01380 {
01381 list.append(msg);
01382 } else {
01383 newMsg = new KMMessage;
01384 newMsg->fromString(msg->asString());
01385 newMsg->setStatus(msg->status());
01386 newMsg->setComplete(msg->isComplete());
01387
01388 if (srcFolder && !newMsg->isComplete())
01389 {
01390 newMsg->setParent(msg->parent());
01391 FolderJob *job = srcFolder->createJob(newMsg);
01392 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
01393 mDestFolder, SLOT(reallyAddCopyOfMsg(KMMessage*)));
01394
01395 newMsg->setTransferInProgress(true);
01396 job->start();
01397 } else {
01398 int rc, index;
01399 rc = mDestFolder->addMsg(newMsg, &index);
01400 if (rc == 0 && index != -1)
01401 mDestFolder->unGetMsg( mDestFolder->count() - 1 );
01402 }
01403 }
01404
01405 if (!isMessage && list.isEmpty())
01406 {
01407 assert(idx != -1);
01408 srcFolder->unGetMsg( idx );
01409 }
01410
01411 }
01412
01413
01414
01415
01416 if (!list.isEmpty())
01417 {
01418
01419 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(mDestFolder);
01420 imapDestFolder->copyMsg(list);
01421 imapDestFolder->getFolder();
01422 }
01423
01424 }
01425
01426
01427 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01428 const QPtrList<KMMsgBase> &msgList)
01429 :mDestFolder( destFolder ), mMsgList( msgList )
01430 {
01431 setDeletesItself( true );
01432 }
01433
01434 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01435 KMMessage *msg )
01436 :mDestFolder( destFolder )
01437 {
01438 setDeletesItself( true );
01439 mMsgList.append( &msg->toMsgBase() );
01440 }
01441
01442 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01443 KMMsgBase *msgBase )
01444 :mDestFolder( destFolder )
01445 {
01446 setDeletesItself( true );
01447 mMsgList.append( msgBase );
01448 }
01449
01450 void KMMoveCommand::execute()
01451 {
01452 typedef QMap< KMFolder*, QPtrList<KMMessage>* > FolderToMessageListMap;
01453 FolderToMessageListMap folderDeleteList;
01454
01455 if (mDestFolder && mDestFolder->open() != 0)
01456 return;
01457 KCursorSaver busy(KBusyPtr::busy());
01458
01459 KMMessage *msg;
01460 KMMsgBase *msgBase;
01461 int rc = 0;
01462 int index;
01463 QPtrList<KMMessage> list;
01464 int undoId = -1;
01465
01466 if (mDestFolder) {
01467 connect (mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
01468 this, SLOT(slotMsgAddedToDestFolder(KMFolder*, Q_UINT32)));
01469
01470 }
01471
01472 for (msgBase=mMsgList.first(); msgBase && !rc; msgBase=mMsgList.next()) {
01473 KMFolder *srcFolder = msgBase->parent();
01474 if (srcFolder == mDestFolder)
01475 continue;
01476 bool undo = msgBase->enableUndo();
01477 int idx = srcFolder->find(msgBase);
01478 assert(idx != -1);
01479 if ( msgBase->isMessage() )
01480 msg = static_cast<KMMessage*>(msgBase);
01481 else
01482 msg = srcFolder->getMsg(idx);
01483
01484 if ( msg->transferInProgress() &&
01485 srcFolder->folderType() == KMFolderTypeImap )
01486 {
01487
01488 msg->setTransferInProgress( false, true );
01489 static_cast<KMFolderImap*>(srcFolder)->ignoreJobsForMessage( msg );
01490 }
01491
01492 if (mDestFolder) {
01493 mLostBoys.append(msg->getMsgSerNum());
01494 if (mDestFolder->folderType() == KMFolderTypeImap) {
01495
01496
01497
01498 connect (mDestFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
01499 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
01500 list.append(msg);
01501 } else {
01502
01503 rc = mDestFolder->moveMsg(msg, &index);
01504 if (rc == 0 && index != -1) {
01505 KMMsgBase *mb = mDestFolder->unGetMsg( mDestFolder->count() - 1 );
01506 if (undo && mb)
01507 {
01508 if ( undoId == -1 )
01509 undoId = kmkernel->undoStack()->newUndoAction( srcFolder, mDestFolder );
01510 kmkernel->undoStack()->addMsgToAction( undoId, mb->getMsgSerNum() );
01511 }
01512 } else if (rc != 0) {
01513
01514
01515 emit completed( false);
01516 deleteLater();
01517 return;
01518 }
01519 }
01520 } else {
01521
01522
01523 if (srcFolder->folderType() == KMFolderTypeImap) {
01524 if (!folderDeleteList[srcFolder])
01525 folderDeleteList[srcFolder] = new QPtrList<KMMessage>;
01526 folderDeleteList[srcFolder]->append( msg );
01527 } else {
01528 srcFolder->removeMsg(idx);
01529 delete msg;
01530 }
01531 }
01532 }
01533 if (!list.isEmpty() && mDestFolder) {
01534 mDestFolder->moveMsg(list, &index);
01535 } else {
01536 FolderToMessageListMap::Iterator it;
01537 for ( it = folderDeleteList.begin(); it != folderDeleteList.end(); ++it ) {
01538 it.key()->removeMsg(*it.data());
01539 delete it.data();
01540 }
01541
01542
01543
01544 KMFolder *srcFolder = 0;
01545 if ( mMsgList.first() ) {
01546 srcFolder = mMsgList.first()->parent();
01547 if ( mDestFolder && mDestFolder == srcFolder ) {
01548 emit completed( true );
01549 deleteLater();
01550 }
01551 }
01552 if ( !mDestFolder ) {
01553 emit completed( true );
01554 deleteLater();
01555 }
01556 }
01557 }
01558
01559 void KMMoveCommand::slotImapFolderCompleted(KMFolderImap *, bool success)
01560 {
01561 if ( success ) {
01562
01563
01564
01565
01566
01567
01568 if ( !mLostBoys.isEmpty() ) {
01569 kdDebug(5006) << "### Not all moved messages reported back that they were " << endl
01570 << "### added to the target folder. Did uidValidity change? " << endl;
01571 }
01572 } else {
01573
01574 }
01575 emit completed( success );
01576 deleteLater();
01577 }
01578
01579 void KMMoveCommand::slotMsgAddedToDestFolder(KMFolder *folder, Q_UINT32 serNum)
01580 {
01581 if (folder != mDestFolder) {
01582 kdDebug(5006) << "KMMoveCommand::msgAddedToDestFolder different "
01583 "folder or invalid serial number." << endl;
01584 return;
01585 }
01586 mLostBoys.remove(serNum);
01587 if ( mLostBoys.isEmpty() ) {
01588
01589 if (mDestFolder && mDestFolder->folderType() != KMFolderTypeImap) {
01590 mDestFolder->sync();
01591 }
01592 emit completed( true );
01593 deleteLater();
01594 }
01595 }
01596
01597
01598 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder,
01599 const QPtrList<KMMsgBase> &msgList )
01600 :KMMoveCommand(findTrashFolder( srcFolder ), msgList)
01601 {
01602 }
01603
01604 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder, KMMessage * msg )
01605 :KMMoveCommand(findTrashFolder( srcFolder ), msg)
01606 {
01607 }
01608
01609
01610 KMFolder * KMDeleteMsgCommand::findTrashFolder( KMFolder * folder )
01611 {
01612 if (folder->folderType()== KMFolderTypeImap)
01613 {
01614 KMFolderImap* fi = static_cast<KMFolderImap*> (folder);
01615 QString trashStr = fi->account()->trash();
01616 KMFolder* trash = kmkernel->imapFolderMgr()->findIdString( trashStr );
01617 if (!trash) trash = kmkernel->trashFolder();
01618 if (folder != trash)
01619 return trash;
01620 } else {
01621 if (folder != kmkernel->trashFolder())
01622
01623 return kmkernel->trashFolder();
01624 }
01625 return 0;
01626 }
01627
01628 KMUrlClickedCommand::KMUrlClickedCommand( const KURL &url, uint identity,
01629 KMReaderWin *readerWin, bool htmlPref, KMMainWidget *mainWidget )
01630 :mUrl( url ), mIdentity( identity ), mReaderWin( readerWin ),
01631 mHtmlPref( htmlPref ), mMainWidget( mainWidget )
01632 {
01633 }
01634
01635 void KMUrlClickedCommand::execute()
01636 {
01637 KMComposeWin *win;
01638 KMMessage* msg;
01639
01640 if (mUrl.protocol() == "mailto")
01641 {
01642 msg = new KMMessage;
01643 msg->initHeader(mIdentity);
01644 msg->setCharset("utf-8");
01645 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
01646 QString query=mUrl.query();
01647 while (!query.isEmpty()) {
01648 QString queryPart;
01649 int secondQuery = query.find('?',1);
01650 if (secondQuery != -1)
01651 queryPart = query.left(secondQuery);
01652 else
01653 queryPart = query;
01654 query = query.mid(queryPart.length());
01655
01656 if (queryPart.left(9) == "?subject=")
01657 msg->setSubject( KURL::decode_string(queryPart.mid(9)) );
01658 else if (queryPart.left(6) == "?body=")
01659
01660
01661 msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() );
01662 else if (queryPart.left(4) == "?cc=")
01663 msg->setCc( KURL::decode_string(queryPart.mid(4)) );
01664 }
01665
01666 win = new KMComposeWin(msg, mIdentity);
01667 win->setCharset("", TRUE);
01668 win->show();
01669 }
01670 else if ((mUrl.protocol() == "http") || (mUrl.protocol() == "https") ||
01671 (mUrl.protocol() == "ftp") || (mUrl.protocol() == "file") ||
01672 (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
01673 (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
01674 (mUrl.protocol() == "smb"))
01675 {
01676 if (mMainWidget)
01677 mMainWidget->statusMsg( i18n("Opening URL..."));
01678 KMimeType::Ptr mime = KMimeType::findByURL( mUrl );
01679 if (mime->name() == "application/x-desktop" ||
01680 mime->name() == "application/x-executable" ||
01681 mime->name() == "application/x-msdos-program" ||
01682 mime->name() == "application/x-shellscript" )
01683 {
01684 if (KMessageBox::warningYesNo( 0, i18n( "<qt>Do you really want to execute <b>%1</b>?</qt>" )
01685 .arg( mUrl.prettyURL() ) ) != KMessageBox::Yes) return;
01686 }
01687 (void) new KRun( mUrl );
01688 }
01689 }
01690
01691 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, KMMessage *msg )
01692 : KMCommand( parent, msg ), mParent( parent ), mEncoded( false )
01693 {
01694 }
01695
01696 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, const QPtrList<KMMsgBase>& msgs )
01697 : KMCommand( parent, msgs ), mParent( parent ), mEncoded( false )
01698 {
01699 }
01700
01701 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, QPtrList<partNode>& attachments,
01702 KMMessage *msg, bool encoded )
01703 : KMCommand( parent, msg ), mParent( parent ), mAttachments( attachments ), mEncoded( encoded )
01704 {
01705
01706 mMessageComplete = msg->isComplete();
01707 msg->setComplete( true );
01708 setDeletesItself( true );
01709 }
01710
01711 void KMSaveAttachmentsCommand::execute()
01712 {
01713 QPtrList<KMMessage> lst = retrievedMsgs();
01714 if ( lst.count() == 1 )
01715 lst.first()->setComplete(mMessageComplete);
01716 if ( mAttachments.count() > 0 )
01717 {
01718 saveAll( mAttachments );
01719 return;
01720 }
01721 KMMessage *msg = 0;
01722 QPtrListIterator<KMMessage> itr( lst );
01723
01724 while ( itr.current() ) {
01725 msg = itr.current();
01726 ++itr;
01727 QCString type = msg->typeStr();
01728
01729 int mainType = msg->type();
01730 int mainSubType = msg->subtype();
01731 DwBodyPart* mainBody = 0;
01732 DwBodyPart* firstBodyPart = msg->getFirstDwBodyPart();
01733 if( !firstBodyPart ) {
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743 kdDebug(5006) << "*no* first body part found, creating one from Message" << endl;
01744 mainBody = new DwBodyPart( msg->asDwString(), 0 );
01745 mainBody->Parse();
01746 }
01747 partNode *rootNode = new partNode( mainBody, mainType, mainSubType, true );
01748 rootNode->setFromAddress( msg->from() );
01749
01750 if ( firstBodyPart ) {
01751 partNode* curNode = new partNode(firstBodyPart);
01752 rootNode->setFirstChild( curNode );
01753 curNode->buildObjectTree();
01754 }
01755 parse( rootNode );
01756 }
01757 }
01758
01759 void KMSaveAttachmentsCommand::parse( partNode *rootNode )
01760 {
01761 QPtrList<partNode> attachments;
01762 for( partNode *child = rootNode; child; child = child->firstChild() ) {
01763 for( partNode *tmp = child; tmp; tmp = tmp->nextSibling() ) {
01764 attachments.append( tmp );
01765 }
01766 }
01767 saveAll( attachments );
01768 }
01769
01770 void KMSaveAttachmentsCommand::saveAll( const QPtrList<partNode>& attachments )
01771 {
01772 if ( attachments.isEmpty() ) {
01773 KMessageBox::information( 0, i18n("Found no attachments to save.") );
01774 return;
01775 }
01776 mAttachments = attachments;
01777
01778 KMLoadPartsCommand *command = new KMLoadPartsCommand( mAttachments, retrievedMessage() );
01779 connect( command, SIGNAL( partsRetrieved() ),
01780 this, SLOT( slotSaveAll() ) );
01781 command->start();
01782 }
01783
01784 void KMSaveAttachmentsCommand::slotSaveAll()
01785 {
01786 QPtrListIterator<partNode> itr( mAttachments );
01787
01788 QString dir, file;
01789 if ( mAttachments.count() > 1 )
01790 {
01791
01792 KFileDialog fdlg( QString::null, QString::null, mParent, 0, true );
01793 fdlg.setMode( (unsigned int) KFile::Directory );
01794 if ( !fdlg.exec() ) return;
01795 dir = fdlg.selectedURL().path();
01796 }
01797 else {
01798
01799
01800 QString s =
01801 (*itr)->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
01802 if ( s.isEmpty() )
01803 s = (*itr)->msgPart().name().stripWhiteSpace().replace( ':', '_' );
01804 if ( s.isEmpty() )
01805 s = "unnamed";
01806 file = KFileDialog::getSaveFileName( s, QString::null, mParent,
01807 QString::null );
01808 }
01809
01810 while ( itr.current() ) {
01811 QString s;
01812 QString filename;
01813 if ( !dir.isEmpty() ) {
01814 s = (*itr)->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
01815 if ( s.isEmpty() )
01816 s = (*itr)->msgPart().name().stripWhiteSpace().replace( ':', '_' );
01817
01818
01819
01820
01821 if ( s.isEmpty() ) {
01822 ++itr;
01823 continue;
01824 }
01825 filename = dir + "/" + s;
01826 }
01827 else
01828 filename = file;
01829
01830 if( !filename.isEmpty() ) {
01831 if( QFile::exists( filename ) ) {
01832 if( KMessageBox::warningYesNo( mParent,
01833 i18n( "A file named %1 already exists. Do you want to overwrite it?" ).arg( s.isEmpty() ? filename : s ),
01834 i18n( "KMail Warning" ) ) ==
01835 KMessageBox::No ) {
01836 ++itr;
01837 continue;
01838 }
01839 }
01840 saveItem( itr.current(), filename );
01841 }
01842 ++itr;
01843 }
01844 }
01845
01846 void KMSaveAttachmentsCommand::saveItem( partNode *node, const QString& filename )
01847 {
01848 if ( node && !filename.isEmpty() ) {
01849 bool bSaveEncrypted = false;
01850 bool bEncryptedParts = node->encryptionState() != KMMsgNotEncrypted;
01851 if( bEncryptedParts )
01852 if( KMessageBox::questionYesNo( mParent,
01853 i18n( "This part of the message is encrypted. Do you want to keep the encryption when saving?" ),
01854 i18n( "KMail Question" ) ) ==
01855 KMessageBox::Yes )
01856 bSaveEncrypted = true;
01857
01858 bool bSaveWithSig = true;
01859 if( node->signatureState() != KMMsgNotSigned )
01860 if( KMessageBox::questionYesNo( mParent,
01861 i18n( "This part of the message is signed. Do you want to keep the signature when saving?" ),
01862 i18n( "KMail Question" ) ) !=
01863 KMessageBox::Yes )
01864 bSaveWithSig = false;
01865
01866 QFile file( filename );
01867 if( file.open( IO_WriteOnly ) ) {
01868 fchmod( file.handle(), S_IRUSR | S_IWUSR );
01869 if ( mEncoded )
01870 {
01871
01872
01873 QDataStream ds( &file );
01874 QCString cstr( node->msgPart().body() );
01875 ds.writeRawBytes( cstr, cstr.size() );
01876 }
01877 else
01878 {
01879 QDataStream ds( &file );
01880 if( bSaveEncrypted || !bEncryptedParts) {
01881 partNode *dataNode = node;
01882 if( !bSaveWithSig ) {
01883 if( DwMime::kTypeMultipart == node->type() &&
01884 DwMime::kSubtypeSigned == node->subType() ){
01885
01886 if( node->findType( DwMime::kTypeApplication,
01887 DwMime::kSubtypePgpSignature,
01888 TRUE, false ) ){
01889 dataNode = node->findTypeNot( DwMime::kTypeApplication,
01890 DwMime::kSubtypePgpSignature,
01891 TRUE, false );
01892 }else if( node->findType( DwMime::kTypeApplication,
01893 DwMime::kSubtypePkcs7Mime,
01894 TRUE, false ) ){
01895 dataNode = node->findTypeNot( DwMime::kTypeApplication,
01896 DwMime::kSubtypePkcs7Mime,
01897 TRUE, false );
01898 }else{
01899 dataNode = node->findTypeNot( DwMime::kTypeMultipart,
01900 DwMime::kSubtypeUnknown,
01901 TRUE, false );
01902 }
01903 }
01904 }
01905 QByteArray cstr = dataNode->msgPart().bodyDecodedBinary();
01906 size_t size = cstr.size();
01907 if ( dataNode->msgPart().type() == DwMime::kTypeText ) {
01908
01909 size = KMFolder::crlf2lf( cstr.data(), size );
01910 }
01911 ds.writeRawBytes( cstr.data(), size );
01912 }
01913 }
01914 file.close();
01915 } else
01916
01917
01918
01919
01920
01921
01922 KMessageBox::error( mParent,
01923 i18n( "Could not write the file." ) + "\n"
01924 + QString::fromLocal8Bit( strerror( errno ) ),
01925 i18n( "KMail Error" ) );
01926 }
01927 }
01928
01929 KMLoadPartsCommand::KMLoadPartsCommand( QPtrList<partNode>& parts, KMMessage *msg )
01930 : mParts( parts ), mNeedsRetrieval( 0 ), mMsg( msg )
01931 {
01932 }
01933
01934 KMLoadPartsCommand::KMLoadPartsCommand( partNode* node, KMMessage *msg )
01935 : mNeedsRetrieval( 0 ), mMsg( msg )
01936 {
01937 mParts.append( node );
01938 }
01939
01940 void KMLoadPartsCommand::start()
01941 {
01942 QPtrListIterator<partNode> it( mParts );
01943 while ( it.current() )
01944 {
01945 if ( !it.current()->msgPart().isComplete() &&
01946 !it.current()->msgPart().partSpecifier().isEmpty() )
01947 {
01948
01949 ++mNeedsRetrieval;
01950 KMFolder* curFolder = mMsg->parent();
01951 if ( curFolder )
01952 {
01953 FolderJob *job = curFolder->createJob( mMsg, FolderJob::tGetMessage,
01954 0, it.current()->msgPart().partSpecifier() );
01955 connect( job, SIGNAL(messageUpdated(KMMessage*, QString)),
01956 this, SLOT(slotPartRetrieved(KMMessage*, QString)) );
01957 job->start();
01958 } else
01959 kdWarning(5006) << "KMLoadPartsCommand - msg has no parent" << endl;
01960 }
01961 ++it;
01962 }
01963 if ( mNeedsRetrieval == 0 )
01964 execute();
01965 }
01966
01967 void KMLoadPartsCommand::slotPartRetrieved( KMMessage* msg, QString partSpecifier )
01968 {
01969 DwBodyPart* part = msg->findDwBodyPart( msg->getFirstDwBodyPart(), partSpecifier );
01970 if ( part )
01971 {
01972
01973 QPtrListIterator<partNode> it( mParts );
01974 while ( it.current() )
01975 {
01976 if ( it.current()->dwPart() == part )
01977 it.current()->setDwPart( part );
01978 ++it;
01979 }
01980 } else
01981 kdWarning(5006) << "KMLoadPartsCommand::slotPartRetrieved - could not find bodypart!" << endl;
01982 --mNeedsRetrieval;
01983 if ( mNeedsRetrieval == 0 )
01984 execute();
01985 }
01986
01987 void KMLoadPartsCommand::execute()
01988 {
01989 emit partsRetrieved();
01990 delete this;
01991 }
01992