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 #include "kmcommands.h"
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034
00035 #include <errno.h>
00036 #include <mimelib/enum.h>
00037 #include <mimelib/field.h>
00038 #include <mimelib/mimepp.h>
00039 #include <mimelib/string.h>
00040 #include <kapplication.h>
00041 #include <dcopclient.h>
00042
00043 #include <qtextcodec.h>
00044
00045 #include <libkdepim/email.h>
00046 #include <kdebug.h>
00047 #include <kfiledialog.h>
00048 #include <kio/netaccess.h>
00049 #include <kabc/stdaddressbook.h>
00050 #include <kabc/addresseelist.h>
00051 #include <klocale.h>
00052 #include <kmessagebox.h>
00053 #include <kparts/browserextension.h>
00054 #include <kprogress.h>
00055 #include <krun.h>
00056 #include <kbookmarkmanager.h>
00057 #include <kstandarddirs.h>
00058 #include <ktempfile.h>
00059 #include "actionscheduler.h"
00060 using KMail::ActionScheduler;
00061 #include "mailinglist-magic.h"
00062 #include "kmaddrbook.h"
00063 #include <kaddrbook.h>
00064 #include "kmcomposewin.h"
00065 #include "kmfiltermgr.h"
00066 #include "kmfoldermbox.h"
00067 #include "kmfolderimap.h"
00068 #include "kmfoldermgr.h"
00069 #include "kmheaders.h"
00070 #include "kmmainwidget.h"
00071 #include "kmmsgdict.h"
00072 #include "kmsender.h"
00073 #include "undostack.h"
00074 #include "kcursorsaver.h"
00075 #include "partNode.h"
00076 #include "objecttreeparser.h"
00077 using KMail::ObjectTreeParser;
00078 using KMail::FolderJob;
00079 #include "mailsourceviewer.h"
00080 using KMail::MailSourceViewer;
00081 #include "kmreadermainwin.h"
00082 #include "secondarywindow.h"
00083 using KMail::SecondaryWindow;
00084 #include "kimproxy.h"
00085
00086 #include "progressmanager.h"
00087 using KPIM::ProgressManager;
00088 using KPIM::ProgressItem;
00089
00090 #include "broadcaststatus.h"
00091
00092 #include "kmcommands.moc"
00093
00094 KMCommand::KMCommand( QWidget *parent )
00095 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00096 mEmitsCompletedItself( false ), mParent( parent )
00097 {
00098 }
00099
00100 KMCommand::KMCommand( QWidget *parent, const QPtrList<KMMsgBase> &msgList )
00101 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00102 mEmitsCompletedItself( false ), mParent( parent ), mMsgList( msgList )
00103 {
00104 }
00105
00106 KMCommand::KMCommand( QWidget *parent, KMMsgBase *msgBase )
00107 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00108 mEmitsCompletedItself( false ), mParent( parent )
00109 {
00110 mMsgList.append( msgBase );
00111 }
00112
00113 KMCommand::KMCommand( QWidget *parent, KMMessage *msg )
00114 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00115 mEmitsCompletedItself( false ), mParent( parent )
00116 {
00117 mMsgList.append( &msg->toMsgBase() );
00118 }
00119
00120 KMCommand::~KMCommand()
00121 {
00122 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00123 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00124 if (!(*fit))
00125 continue;
00126 (*fit)->close();
00127 }
00128 }
00129
00130 KMCommand::Result KMCommand::result()
00131 {
00132 if ( mResult == Undefined )
00133 kdDebug(5006) << k_funcinfo << "mResult is Undefined" << endl;
00134 return mResult;
00135 }
00136
00137 void KMCommand::start()
00138 {
00139 QTimer::singleShot( 0, this, SLOT( slotStart() ) );
00140 }
00141
00142
00143 const QPtrList<KMMessage> KMCommand::retrievedMsgs() const
00144 {
00145 return mRetrievedMsgs;
00146 }
00147
00148 KMMessage *KMCommand::retrievedMessage() const
00149 {
00150 return mRetrievedMsgs.getFirst();
00151 }
00152
00153 QWidget *KMCommand::parentWidget() const
00154 {
00155 return mParent;
00156 }
00157
00158 int KMCommand::mCountJobs = 0;
00159
00160 void KMCommand::slotStart()
00161 {
00162 connect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00163 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00164 kmkernel->filterMgr()->ref();
00165
00166 if (mMsgList.find(0) != -1) {
00167 emit messagesTransfered( Failed );
00168 return;
00169 }
00170
00171 if ((mMsgList.count() == 1) &&
00172 (mMsgList.getFirst()->isMessage()) &&
00173 (mMsgList.getFirst()->parent() == 0))
00174 {
00175
00176 mRetrievedMsgs.append((KMMessage*)mMsgList.getFirst());
00177 emit messagesTransfered( OK );
00178 return;
00179 }
00180
00181 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00182 if (!mb->parent()) {
00183 emit messagesTransfered( Failed );
00184 return;
00185 } else {
00186 mFolders.append( mb->parent() );
00187 mb->parent()->open();
00188 }
00189
00190
00191 transferSelectedMsgs();
00192 }
00193
00194 void KMCommand::slotPostTransfer( KMCommand::Result result )
00195 {
00196 disconnect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00197 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00198 if ( result == OK )
00199 result = execute();
00200 mResult = result;
00201 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00202 KMMessage* msg;
00203 while ( (msg = it.current()) != 0 )
00204 {
00205 ++it;
00206 if (msg->parent())
00207 msg->setTransferInProgress(false);
00208 }
00209 kmkernel->filterMgr()->deref();
00210 if ( !emitsCompletedItself() )
00211 emit completed( this );
00212 if ( !deletesItself() )
00213 delete this;
00214 }
00215
00216 void KMCommand::transferSelectedMsgs()
00217 {
00218
00219 if (KMCommand::mCountJobs > 0) {
00220 emit messagesTransfered( Failed );
00221 return;
00222 }
00223
00224 bool complete = true;
00225 KMCommand::mCountJobs = 0;
00226 mCountMsgs = 0;
00227 mRetrievedMsgs.clear();
00228 mCountMsgs = mMsgList.count();
00229 uint totalSize = 0;
00230
00231
00232
00233
00234 if ( mCountMsgs > 0 ) {
00235 mProgressDialog = new KProgressDialog(mParent, "transferProgress",
00236 i18n("Please wait"),
00237 i18n("Please wait while the message is transferred",
00238 "Please wait while the %n messages are transferred", mMsgList.count()),
00239 true);
00240 mProgressDialog->setMinimumDuration(1000);
00241 }
00242 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00243 {
00244
00245 KMMessage *thisMsg = 0;
00246 if ( mb->isMessage() )
00247 thisMsg = static_cast<KMMessage*>(mb);
00248 else
00249 {
00250 KMFolder *folder = mb->parent();
00251 int idx = folder->find(mb);
00252 if (idx < 0) continue;
00253 thisMsg = folder->getMsg(idx);
00254 }
00255 if (!thisMsg) continue;
00256 if ( thisMsg->transferInProgress() &&
00257 thisMsg->parent()->folderType() == KMFolderTypeImap )
00258 {
00259 thisMsg->setTransferInProgress( false, true );
00260 thisMsg->parent()->ignoreJobsForMessage( thisMsg );
00261 }
00262
00263 if ( thisMsg->parent() && !thisMsg->isComplete() &&
00264 ( !mProgressDialog || !mProgressDialog->wasCancelled() ) )
00265 {
00266 kdDebug(5006)<<"### INCOMPLETE\n";
00267
00268 complete = false;
00269 KMCommand::mCountJobs++;
00270 FolderJob *job = thisMsg->parent()->createJob(thisMsg);
00271 job->setCancellable( false );
00272 totalSize += thisMsg->msgSizeServer();
00273
00274 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00275 this, SLOT(slotMsgTransfered(KMMessage*)));
00276
00277 connect(job, SIGNAL(finished()),
00278 this, SLOT(slotJobFinished()));
00279 connect(job, SIGNAL(progress(unsigned long, unsigned long)),
00280 this, SLOT(slotProgress(unsigned long, unsigned long)));
00281
00282 thisMsg->setTransferInProgress(true);
00283 job->start();
00284 } else {
00285 thisMsg->setTransferInProgress(true);
00286 mRetrievedMsgs.append(thisMsg);
00287 }
00288 }
00289
00290 if (complete)
00291 {
00292 delete mProgressDialog;
00293 emit messagesTransfered( OK );
00294 } else {
00295
00296 if ( mProgressDialog ) {
00297 connect(mProgressDialog, SIGNAL(cancelClicked()),
00298 this, SLOT(slotTransferCancelled()));
00299 mProgressDialog->progressBar()->setTotalSteps(totalSize);
00300 }
00301 }
00302 }
00303
00304 void KMCommand::slotMsgTransfered(KMMessage* msg)
00305 {
00306 if ( mProgressDialog && mProgressDialog->wasCancelled() ) {
00307 emit messagesTransfered( Canceled );
00308 return;
00309 }
00310
00311
00312 mRetrievedMsgs.append(msg);
00313 }
00314
00315 void KMCommand::slotProgress( unsigned long done, unsigned long )
00316 {
00317 mProgressDialog->progressBar()->setProgress( done );
00318 }
00319
00320 void KMCommand::slotJobFinished()
00321 {
00322
00323 KMCommand::mCountJobs--;
00324
00325 if ( mProgressDialog && mProgressDialog->wasCancelled() ) return;
00326
00327 if ( (mCountMsgs - static_cast<int>(mRetrievedMsgs.count())) > KMCommand::mCountJobs )
00328 {
00329
00330 if ( mProgressDialog )
00331 mProgressDialog->hide();
00332 slotTransferCancelled();
00333 return;
00334 }
00335
00336 if ( mProgressDialog ) {
00337 mProgressDialog->setLabel(i18n("Please wait while the message is transferred",
00338 "Please wait while the %n messages are transferred", KMCommand::mCountJobs));
00339 }
00340 if (KMCommand::mCountJobs == 0)
00341 {
00342
00343 delete mProgressDialog;
00344 emit messagesTransfered( OK );
00345 }
00346 }
00347
00348 void KMCommand::slotTransferCancelled()
00349 {
00350
00351 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00352 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00353 if (!(*fit))
00354 continue;
00355 KMFolder *folder = *fit;
00356 KMFolderImap *imapFolder = dynamic_cast<KMFolderImap*>(folder);
00357 if (imapFolder && imapFolder->account()) {
00358 imapFolder->account()->killAllJobs();
00359 }
00360 }
00361
00362 KMCommand::mCountJobs = 0;
00363 mCountMsgs = 0;
00364
00365 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00366 KMMessage* msg;
00367 while ( (msg = it.current()) != 0 )
00368 {
00369 KMFolder *folder = msg->parent();
00370 ++it;
00371 if (!folder)
00372 continue;
00373 msg->setTransferInProgress(false);
00374 int idx = folder->find(msg);
00375 if (idx > 0) folder->unGetMsg(idx);
00376 }
00377 mRetrievedMsgs.clear();
00378 emit messagesTransfered( Canceled );
00379 }
00380
00381 void KMCommand::keepFolderOpen( KMFolder *folder )
00382 {
00383 folder->open();
00384 mFolders.append( folder );
00385 }
00386
00387 KMMailtoComposeCommand::KMMailtoComposeCommand( const KURL &url,
00388 KMMessage *msg )
00389 :mUrl( url ), mMessage( msg )
00390 {
00391 }
00392
00393 KMCommand::Result KMMailtoComposeCommand::execute()
00394 {
00395 KMComposeWin *win;
00396 KMMessage *msg = new KMMessage;
00397 uint id = 0;
00398
00399 if ( mMessage && mMessage->parent() )
00400 id = mMessage->parent()->identity();
00401
00402 msg->initHeader(id);
00403 msg->setCharset("utf-8");
00404 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00405
00406 win = new KMComposeWin(msg, id);
00407 win->setCharset("", TRUE);
00408 win->setFocusToSubject();
00409 win->show();
00410
00411 return OK;
00412 }
00413
00414
00415 KMMailtoReplyCommand::KMMailtoReplyCommand( QWidget *parent,
00416 const KURL &url, KMMessage *msg, const QString &selection )
00417 :KMCommand( parent, msg ), mUrl( url ), mSelection( selection )
00418 {
00419 }
00420
00421 KMCommand::Result KMMailtoReplyCommand::execute()
00422 {
00423
00424 KMMessage *msg = retrievedMessage();
00425 KMComposeWin *win;
00426 KMMessage *rmsg = msg->createReply( KMail::ReplyNone, mSelection );
00427 rmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00428
00429 win = new KMComposeWin(rmsg, 0);
00430 win->setCharset(msg->codec()->mimeName(), TRUE);
00431 win->setReplyFocus();
00432 win->show();
00433
00434 return OK;
00435 }
00436
00437
00438 KMMailtoForwardCommand::KMMailtoForwardCommand( QWidget *parent,
00439 const KURL &url, KMMessage *msg )
00440 :KMCommand( parent, msg ), mUrl( url )
00441 {
00442 }
00443
00444 KMCommand::Result KMMailtoForwardCommand::execute()
00445 {
00446
00447 KMMessage *msg = retrievedMessage();
00448 KMComposeWin *win;
00449 KMMessage *fmsg = msg->createForward();
00450 fmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00451
00452 win = new KMComposeWin(fmsg);
00453 win->setCharset(msg->codec()->mimeName(), TRUE);
00454 win->show();
00455
00456 return OK;
00457 }
00458
00459
00460 KMAddBookmarksCommand::KMAddBookmarksCommand( const KURL &url, QWidget *parent )
00461 : KMCommand( parent ), mUrl( url )
00462 {
00463 }
00464
00465 KMCommand::Result KMAddBookmarksCommand::execute()
00466 {
00467 QString filename = locateLocal( "data", QString::fromLatin1("konqueror/bookmarks.xml") );
00468 KBookmarkManager *bookManager = KBookmarkManager::managerForFile( filename,
00469 false );
00470 KBookmarkGroup group = bookManager->root();
00471 group.addBookmark( bookManager, mUrl.path(), KURL( mUrl ) );
00472 if( bookManager->save() ) {
00473 bookManager->emitChanged( group );
00474 }
00475
00476 return OK;
00477 }
00478
00479 KMMailtoAddAddrBookCommand::KMMailtoAddAddrBookCommand( const KURL &url,
00480 QWidget *parent )
00481 : KMCommand( parent ), mUrl( url )
00482 {
00483 }
00484
00485 KMCommand::Result KMMailtoAddAddrBookCommand::execute()
00486 {
00487 KAddrBookExternal::addEmail( KMMessage::decodeMailtoUrl( mUrl.path() ),
00488 parentWidget() );
00489
00490 return OK;
00491 }
00492
00493
00494 KMMailtoOpenAddrBookCommand::KMMailtoOpenAddrBookCommand( const KURL &url,
00495 QWidget *parent )
00496 : KMCommand( parent ), mUrl( url )
00497 {
00498 }
00499
00500 KMCommand::Result KMMailtoOpenAddrBookCommand::execute()
00501 {
00502 QString addr = KMMessage::decodeMailtoUrl( mUrl.path() );
00503 KAddrBookExternal::openEmail( KPIM::getEmailAddr(addr), addr ,
00504 parentWidget() );
00505
00506 return OK;
00507 }
00508
00509
00510 KMUrlCopyCommand::KMUrlCopyCommand( const KURL &url, KMMainWidget *mainWidget )
00511 :mUrl( url ), mMainWidget( mainWidget )
00512 {
00513 }
00514
00515 KMCommand::Result KMUrlCopyCommand::execute()
00516 {
00517 QClipboard* clip = QApplication::clipboard();
00518
00519 if (mUrl.protocol() == "mailto") {
00520
00521 QString address = KMMessage::decodeMailtoUrl( mUrl.path() );
00522 clip->setSelectionMode( true );
00523 clip->setText( address );
00524 clip->setSelectionMode( false );
00525 clip->setText( address );
00526 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ));
00527 } else {
00528
00529 clip->setSelectionMode( true );
00530 clip->setText( mUrl.url() );
00531 clip->setSelectionMode( false );
00532 clip->setText( mUrl.url() );
00533 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "URL copied to clipboard." ));
00534 }
00535
00536 return OK;
00537 }
00538
00539
00540 KMUrlOpenCommand::KMUrlOpenCommand( const KURL &url, KMReaderWin *readerWin )
00541 :mUrl( url ), mReaderWin( readerWin )
00542 {
00543 }
00544
00545 KMCommand::Result KMUrlOpenCommand::execute()
00546 {
00547 if ( !mUrl.isEmpty() )
00548 mReaderWin->slotUrlOpen( mUrl, KParts::URLArgs() );
00549
00550 return OK;
00551 }
00552
00553
00554 KMUrlSaveCommand::KMUrlSaveCommand( const KURL &url, QWidget *parent )
00555 : KMCommand( parent ), mUrl( url )
00556 {
00557 }
00558
00559 KMCommand::Result KMUrlSaveCommand::execute()
00560 {
00561 if ( mUrl.isEmpty() )
00562 return OK;
00563 KURL saveUrl = KFileDialog::getSaveURL(mUrl.fileName(), QString::null,
00564 parentWidget() );
00565 if ( saveUrl.isEmpty() )
00566 return Canceled;
00567 if ( KIO::NetAccess::exists( saveUrl, false, parentWidget() ) )
00568 {
00569 if (KMessageBox::warningContinueCancel(0,
00570 i18n("<qt>File <b>%1</b> exists.<br>Do you want to replace it?</qt>")
00571 .arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00572 != KMessageBox::Continue)
00573 return Canceled;
00574 }
00575 KIO::Job *job = KIO::file_copy(mUrl, saveUrl, -1, true);
00576 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotUrlSaveResult(KIO::Job*)));
00577 setEmitsCompletedItself( true );
00578 return OK;
00579 }
00580
00581 void KMUrlSaveCommand::slotUrlSaveResult( KIO::Job *job )
00582 {
00583 if ( job->error() ) {
00584 job->showErrorDialog();
00585 setResult( Failed );
00586 emit completed( this );
00587 }
00588 else {
00589 setResult( OK );
00590 emit completed( this );
00591 }
00592 }
00593
00594
00595 KMEditMsgCommand::KMEditMsgCommand( QWidget *parent, KMMessage *msg )
00596 :KMCommand( parent, msg )
00597 {
00598 }
00599
00600 KMCommand::Result KMEditMsgCommand::execute()
00601 {
00602 KMMessage *msg = retrievedMessage();
00603 if (!msg || !msg->parent() ||
00604 !kmkernel->folderIsDraftOrOutbox( msg->parent() ))
00605 return Failed;
00606
00607
00608
00609
00610 KMFolder *parent = msg->parent();
00611 if ( parent )
00612 parent->take( parent->find( msg ) );
00613
00614 KMComposeWin *win = new KMComposeWin();
00615 msg->setTransferInProgress(false);
00616 win->setMsg(msg, FALSE, TRUE);
00617 win->setFolder( parent );
00618 win->show();
00619
00620 return OK;
00621 }
00622
00623
00624 KMShowMsgSrcCommand::KMShowMsgSrcCommand( KMMessage *msg, bool fixedFont )
00625 : mFixedFont( fixedFont ), mMsg ( msg )
00626 {
00627 }
00628
00629 void KMShowMsgSrcCommand::start()
00630 {
00631 QString str = mMsg->codec()->toUnicode( mMsg->asString() );
00632
00633 MailSourceViewer *viewer = new MailSourceViewer();
00634 viewer->setCaption( i18n("Message as Plain Text") );
00635 viewer->setText(str);
00636 if( mFixedFont )
00637 viewer->setFont(KGlobalSettings::fixedFont());
00638
00639
00640
00641
00642 if (QApplication::desktop()->isVirtualDesktop()) {
00643 int scnum = QApplication::desktop()->screenNumber(QCursor::pos());
00644 viewer->resize(QApplication::desktop()->screenGeometry(scnum).width()/2,
00645 2*QApplication::desktop()->screenGeometry(scnum).height()/3);
00646 } else {
00647 viewer->resize(QApplication::desktop()->geometry().width()/2,
00648 2*QApplication::desktop()->geometry().height()/3);
00649 }
00650 viewer->show();
00651 }
00652
00653 static KURL subjectToUrl( const QString & subject ) {
00654 return KFileDialog::getSaveURL( subject.stripWhiteSpace()
00655 .replace( QDir::separator(), '_' ),
00656 QString::null );
00657 }
00658
00659 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent, KMMessage * msg )
00660 : KMCommand( parent ),
00661 mMsgListIndex( 0 ),
00662 mOffset( 0 ),
00663 mTotalSize( msg ? msg->msgSize() : 0 )
00664 {
00665 if ( !msg ) return;
00666 setDeletesItself( true );
00667 mMsgList.append( msg->getMsgSerNum() );
00668 mUrl = subjectToUrl( msg->cleanSubject() );
00669 }
00670
00671 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent,
00672 const QPtrList<KMMsgBase> &msgList )
00673 : KMCommand( parent ),
00674 mMsgListIndex( 0 ),
00675 mOffset( 0 ),
00676 mTotalSize( 0 )
00677 {
00678 if (!msgList.getFirst())
00679 return;
00680 setDeletesItself( true );
00681 KMMsgBase *msgBase = msgList.getFirst();
00682
00683
00684
00685
00686 QPtrListIterator<KMMsgBase> it(msgList);
00687 while ( it.current() ) {
00688 mMsgList.append( (*it)->getMsgSerNum() );
00689 mTotalSize += (*it)->msgSize();
00690 if ((*it)->parent() != 0)
00691 (*it)->parent()->open();
00692 ++it;
00693 }
00694 mMsgListIndex = 0;
00695 mUrl = subjectToUrl( msgBase->cleanSubject() );
00696 }
00697
00698 KURL KMSaveMsgCommand::url()
00699 {
00700 return mUrl;
00701 }
00702
00703 KMCommand::Result KMSaveMsgCommand::execute()
00704 {
00705 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, false, false );
00706 mJob->slotTotalSize( mTotalSize );
00707 mJob->setAsyncDataEnabled( true );
00708 mJob->setReportDataSent( true );
00709 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00710 SLOT(slotSaveDataReq()));
00711 connect(mJob, SIGNAL(result(KIO::Job*)),
00712 SLOT(slotSaveResult(KIO::Job*)));
00713 setEmitsCompletedItself( true );
00714 return OK;
00715 }
00716
00717 void KMSaveMsgCommand::slotSaveDataReq()
00718 {
00719 int remainingBytes = mData.size() - mOffset;
00720 if ( remainingBytes > 0 ) {
00721
00722 if ( remainingBytes > MAX_CHUNK_SIZE )
00723 remainingBytes = MAX_CHUNK_SIZE;
00724
00725 QByteArray data;
00726 data.duplicate( mData.data() + mOffset, remainingBytes );
00727 mJob->sendAsyncData( data );
00728 mOffset += remainingBytes;
00729 return;
00730 }
00731
00732 if ( mMsgListIndex < mMsgList.size() ) {
00733 KMMessage *msg = 0;
00734 int idx = -1;
00735 KMFolder * p = 0;
00736 kmkernel->msgDict()->getLocation( mMsgList[mMsgListIndex], &p, &idx );
00737 assert( p );
00738 assert( idx >= 0 );
00739 msg = p->getMsg(idx);
00740
00741 if (msg->transferInProgress()) {
00742 QByteArray data = QByteArray();
00743 mJob->sendAsyncData( data );
00744 }
00745 msg->setTransferInProgress( true );
00746 if (msg->isComplete() ) {
00747 slotMessageRetrievedForSaving(msg);
00748 } else {
00749
00750 if (msg->parent() && !msg->isComplete() ) {
00751 FolderJob *job = msg->parent()->createJob(msg);
00752 job->setCancellable( false );
00753 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00754 this, SLOT(slotMessageRetrievedForSaving(KMMessage*)));
00755 job->start();
00756 }
00757 }
00758 } else {
00759
00760 QByteArray data = QByteArray();
00761 mJob->sendAsyncData( data );
00762 }
00763 }
00764
00765 void KMSaveMsgCommand::slotMessageRetrievedForSaving(KMMessage *msg)
00766 {
00767 QCString str( msg->mboxMessageSeparator() );
00768 str += KMFolderMbox::escapeFrom( msg->asString() );
00769 str += "\n";
00770 msg->setTransferInProgress(false);
00771
00772 mData = str;
00773 mData.resize(mData.size() - 1);
00774 mOffset = 0;
00775 QByteArray data;
00776 int size;
00777
00778 if( mData.size() > (unsigned int) MAX_CHUNK_SIZE )
00779 size = MAX_CHUNK_SIZE;
00780 else
00781 size = mData.size();
00782
00783 data.duplicate( mData, size );
00784 mJob->sendAsyncData( data );
00785 mOffset += size;
00786 ++mMsgListIndex;
00787
00788 if (msg->parent()) {
00789 int idx = -1;
00790 KMFolder * p = 0;
00791 kmkernel->msgDict()->getLocation( msg, &p, &idx );
00792 assert( p == msg->parent() ); assert( idx >= 0 );
00793 p->unGetMsg( idx );
00794 p->close();
00795 }
00796 }
00797
00798 void KMSaveMsgCommand::slotSaveResult(KIO::Job *job)
00799 {
00800 if (job->error())
00801 {
00802 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST)
00803 {
00804 if (KMessageBox::warningContinueCancel(0,
00805 i18n("File %1 exists.\nDo you want to replace it?")
00806 .arg(mUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00807 == KMessageBox::Continue) {
00808 mOffset = 0;
00809
00810 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, true, false );
00811 mJob->slotTotalSize( mTotalSize );
00812 mJob->setAsyncDataEnabled( true );
00813 mJob->setReportDataSent( true );
00814 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00815 SLOT(slotSaveDataReq()));
00816 connect(mJob, SIGNAL(result(KIO::Job*)),
00817 SLOT(slotSaveResult(KIO::Job*)));
00818 }
00819 }
00820 else
00821 {
00822 job->showErrorDialog();
00823 setResult( Failed );
00824 emit completed( this );
00825 delete this;
00826 }
00827 } else {
00828 setResult( OK );
00829 emit completed( this );
00830 delete this;
00831 }
00832 }
00833
00834
00835
00836 KMOpenMsgCommand::KMOpenMsgCommand( QWidget *parent, const KURL & url )
00837 : KMCommand( parent ),
00838 mUrl( url )
00839 {
00840 setDeletesItself( true );
00841 }
00842
00843 KMCommand::Result KMOpenMsgCommand::execute()
00844 {
00845 if ( mUrl.isEmpty() ) {
00846 mUrl = KFileDialog::getOpenURL( ":OpenMessage", "message/rfc822",
00847 parentWidget(), i18n("Open Message") );
00848 }
00849 if ( mUrl.isEmpty() ) {
00850 setDeletesItself( false );
00851 return Canceled;
00852 }
00853 mJob = KIO::get( mUrl, false, false );
00854 mJob->setReportDataSent( true );
00855 connect( mJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
00856 this, SLOT( slotDataArrived( KIO::Job*, const QByteArray & ) ) );
00857 connect( mJob, SIGNAL( result( KIO::Job * ) ),
00858 SLOT( slotResult( KIO::Job * ) ) );
00859 setEmitsCompletedItself( true );
00860 return OK;
00861 }
00862
00863 void KMOpenMsgCommand::slotDataArrived( KIO::Job *, const QByteArray & data )
00864 {
00865 if ( data.isEmpty() )
00866 return;
00867
00868 mMsgString.append( data.data(), data.size() );
00869 }
00870
00871 void KMOpenMsgCommand::slotResult( KIO::Job *job )
00872 {
00873 if ( job->error() ) {
00874
00875 job->showErrorDialog();
00876 setResult( Failed );
00877 emit completed( this );
00878 }
00879 else {
00880 int startOfMessage = 0;
00881 if ( mMsgString.compare( 0, 5, "From ", 5 ) == 0 ) {
00882 startOfMessage = mMsgString.find( '\n' );
00883 if ( startOfMessage == -1 ) {
00884 KMessageBox::sorry( parentWidget(),
00885 i18n( "The file doesn't contain a message." ) );
00886 setResult( Failed );
00887 emit completed( this );
00888
00889
00890
00891 SecondaryWindow *win = new SecondaryWindow();
00892 win->close();
00893 win->deleteLater();
00894 deleteLater();
00895 return;
00896 }
00897 startOfMessage += 1;
00898 }
00899
00900 bool multipleMessages = true;
00901 int endOfMessage = mMsgString.find( "\nFrom " );
00902 if ( endOfMessage == -1 ) {
00903 endOfMessage = mMsgString.length();
00904 multipleMessages = false;
00905 }
00906 DwMessage *dwMsg = new DwMessage;
00907 dwMsg->FromString( mMsgString.substr( startOfMessage,
00908 endOfMessage - startOfMessage ) );
00909 dwMsg->Parse();
00910
00911 if ( dwMsg->Headers().NumFields() == 0 ) {
00912 KMessageBox::sorry( parentWidget(),
00913 i18n( "The file doesn't contain a message." ) );
00914 delete dwMsg; dwMsg = 0;
00915 setResult( Failed );
00916 emit completed( this );
00917
00918 SecondaryWindow *win = new SecondaryWindow();
00919 win->close();
00920 win->deleteLater();
00921 deleteLater();
00922 return;
00923 }
00924 KMMessage *msg = new KMMessage( dwMsg );
00925 msg->setReadyToShow( true );
00926 KMReaderMainWin *win = new KMReaderMainWin();
00927 win->showMsg( kmkernel->networkCodec(), msg );
00928 win->show();
00929 if ( multipleMessages )
00930 KMessageBox::information( win,
00931 i18n( "The file contains multiple messages. "
00932 "Only the first message is shown." ) );
00933 setResult( OK );
00934 emit completed( this );
00935 }
00936 delete this;
00937 }
00938
00939
00940
00941
00942
00943 KMReplyToCommand::KMReplyToCommand( QWidget *parent, KMMessage *msg,
00944 const QString &selection )
00945 : KMCommand( parent, msg ), mSelection( selection )
00946 {
00947 }
00948
00949 KMCommand::Result KMReplyToCommand::execute()
00950 {
00951 KCursorSaver busy(KBusyPtr::busy());
00952 KMMessage *msg = retrievedMessage();
00953 KMMessage *reply = msg->createReply( KMail::ReplySmart, mSelection );
00954 KMComposeWin *win = new KMComposeWin( reply );
00955 win->setCharset( msg->codec()->mimeName(), TRUE );
00956 win->setReplyFocus();
00957 win->show();
00958
00959 return OK;
00960 }
00961
00962
00963 KMNoQuoteReplyToCommand::KMNoQuoteReplyToCommand( QWidget *parent,
00964 KMMessage *msg )
00965 : KMCommand( parent, msg )
00966 {
00967 }
00968
00969 KMCommand::Result KMNoQuoteReplyToCommand::execute()
00970 {
00971 KCursorSaver busy(KBusyPtr::busy());
00972 KMMessage *msg = retrievedMessage();
00973 KMMessage *reply = msg->createReply( KMail::ReplySmart, "", TRUE);
00974 KMComposeWin *win = new KMComposeWin( reply );
00975 win->setCharset(msg->codec()->mimeName(), TRUE);
00976 win->setReplyFocus(false);
00977 win->show();
00978
00979 return OK;
00980 }
00981
00982
00983 KMReplyListCommand::KMReplyListCommand( QWidget *parent,
00984 KMMessage *msg, const QString &selection )
00985 : KMCommand( parent, msg ), mSelection( selection )
00986 {
00987 }
00988
00989 KMCommand::Result KMReplyListCommand::execute()
00990 {
00991 KCursorSaver busy(KBusyPtr::busy());
00992 KMMessage *msg = retrievedMessage();
00993 KMMessage *reply = msg->createReply( KMail::ReplyList, mSelection);
00994 KMComposeWin *win = new KMComposeWin( reply );
00995 win->setCharset(msg->codec()->mimeName(), TRUE);
00996 win->setReplyFocus(false);
00997 win->show();
00998
00999 return OK;
01000 }
01001
01002
01003 KMReplyToAllCommand::KMReplyToAllCommand( QWidget *parent,
01004 KMMessage *msg, const QString &selection )
01005 :KMCommand( parent, msg ), mSelection( selection )
01006 {
01007 }
01008
01009 KMCommand::Result KMReplyToAllCommand::execute()
01010 {
01011 KCursorSaver busy(KBusyPtr::busy());
01012 KMMessage *msg = retrievedMessage();
01013 KMMessage *reply = msg->createReply( KMail::ReplyAll, mSelection );
01014 KMComposeWin *win = new KMComposeWin( reply );
01015 win->setCharset( msg->codec()->mimeName(), TRUE );
01016 win->setReplyFocus();
01017 win->show();
01018
01019 return OK;
01020 }
01021
01022
01023 KMReplyAuthorCommand::KMReplyAuthorCommand( QWidget *parent, KMMessage *msg,
01024 const QString &selection )
01025 : KMCommand( parent, msg ), mSelection( selection )
01026 {
01027 }
01028
01029 KMCommand::Result KMReplyAuthorCommand::execute()
01030 {
01031 KCursorSaver busy(KBusyPtr::busy());
01032 KMMessage *msg = retrievedMessage();
01033 KMMessage *reply = msg->createReply( KMail::ReplyAuthor, mSelection );
01034 KMComposeWin *win = new KMComposeWin( reply );
01035 win->setCharset( msg->codec()->mimeName(), TRUE );
01036 win->setReplyFocus();
01037 win->show();
01038
01039 return OK;
01040 }
01041
01042
01043 KMForwardCommand::KMForwardCommand( QWidget *parent,
01044 const QPtrList<KMMsgBase> &msgList, uint identity )
01045 : KMCommand( parent, msgList ),
01046 mIdentity( identity )
01047 {
01048 }
01049
01050 KMForwardCommand::KMForwardCommand( QWidget *parent, KMMessage *msg,
01051 uint identity )
01052 : KMCommand( parent, msg ),
01053 mIdentity( identity )
01054 {
01055 }
01056
01057 KMCommand::Result KMForwardCommand::execute()
01058 {
01059 KMComposeWin *win;
01060 QPtrList<KMMessage> msgList = retrievedMsgs();
01061
01062 if (msgList.count() >= 2) {
01063
01064
01065 if (KMessageBox::questionYesNo( parentWidget(),
01066 i18n("Forward selected messages as "
01067 "a MIME digest?") )
01068 == KMessageBox::Yes) {
01069 uint id = 0;
01070 KMMessage *fwdMsg = new KMMessage;
01071 KMMessagePart *msgPart = new KMMessagePart;
01072 QString msgPartText;
01073 int msgCnt = 0;
01074
01075
01076
01077 fwdMsg->initHeader(id);
01078 fwdMsg->setAutomaticFields(true);
01079 fwdMsg->mMsg->Headers().ContentType().CreateBoundary(1);
01080 QCString boundary( fwdMsg->mMsg->Headers().ContentType().Boundary().c_str() );
01081 msgPartText = i18n("\nThis is a MIME digest forward. The content of the"
01082 " message is contained in the attachment(s).\n\n\n");
01083
01084 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01085
01086 if (id == 0)
01087 id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
01088
01089 msgPartText += "--";
01090 msgPartText += QString::fromLatin1( boundary );
01091 msgPartText += "\nContent-Type: MESSAGE/RFC822";
01092 msgPartText += QString("; CHARSET=%1").arg(msg->charset());
01093 msgPartText += "\n";
01094 DwHeaders dwh;
01095 dwh.MessageId().CreateDefault();
01096 msgPartText += QString("Content-ID: %1\n").arg(dwh.MessageId().AsString().c_str());
01097 msgPartText += QString("Content-Description: %1").arg(msg->subject());
01098 if (!msg->subject().contains("(fwd)"))
01099 msgPartText += " (fwd)";
01100 msgPartText += "\n\n";
01101
01102 msg->removePrivateHeaderFields();
01103 msg->removeHeaderField("BCC");
01104
01105 msgPartText += msg->headerAsString();
01106 msgPartText += "\n";
01107 msgPartText += msg->body();
01108 msgPartText += "\n";
01109 msgCnt++;
01110 fwdMsg->link(msg, KMMsgStatusForwarded);
01111 }
01112 if ( id == 0 )
01113 id = mIdentity;
01114 fwdMsg->initHeader(id);
01115 msgPartText += "--";
01116 msgPartText += QString::fromLatin1( boundary );
01117 msgPartText += "--\n";
01118 QCString tmp;
01119 msgPart->setTypeStr("MULTIPART");
01120 tmp.sprintf( "Digest; boundary=\"%s\"", boundary.data() );
01121 msgPart->setSubtypeStr( tmp );
01122 msgPart->setName("unnamed");
01123 msgPart->setCte(DwMime::kCte7bit);
01124 msgPart->setContentDescription(QString("Digest of %1 messages.").arg(msgCnt));
01125
01126 msgPart->setBodyEncoded(QCString(msgPartText.ascii()));
01127 KCursorSaver busy(KBusyPtr::busy());
01128 win = new KMComposeWin(fwdMsg, id);
01129 win->addAttach(msgPart);
01130 win->show();
01131 return OK;
01132 } else {
01133 uint id = 0;
01134 QCString msgText = "";
01135 QPtrList<KMMessage> linklist;
01136 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01137
01138 if (id == 0)
01139 id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
01140
01141 msgText += msg->createForwardBody();
01142 linklist.append(msg);
01143 }
01144 if ( id == 0 )
01145 id = mIdentity;
01146 KMMessage *fwdMsg = new KMMessage;
01147 fwdMsg->initHeader(id);
01148 fwdMsg->setAutomaticFields(true);
01149 fwdMsg->setCharset("utf-8");
01150 fwdMsg->setBody(msgText);
01151
01152 for (KMMessage *msg = linklist.first(); msg; msg = linklist.next())
01153 fwdMsg->link(msg, KMMsgStatusForwarded);
01154
01155 KCursorSaver busy(KBusyPtr::busy());
01156 win = new KMComposeWin(fwdMsg, id);
01157 win->setCharset("");
01158 win->show();
01159 return OK;
01160 }
01161 }
01162
01163
01164
01165 KMMessage *msg = msgList.getFirst();
01166 if ( !msg || !msg->codec() )
01167 return Failed;
01168
01169 KCursorSaver busy(KBusyPtr::busy());
01170 win = new KMComposeWin(msg->createForward());
01171 win->setCharset(msg->codec()->mimeName(), TRUE);
01172 win->show();
01173
01174 return OK;
01175 }
01176
01177
01178 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
01179 const QPtrList<KMMsgBase> &msgList, uint identity, KMComposeWin *win )
01180 : KMCommand( parent, msgList ), mIdentity( identity ),
01181 mWin( QGuardedPtr< KMComposeWin >( win ))
01182 {
01183 }
01184
01185 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
01186 KMMessage * msg, uint identity, KMComposeWin *win )
01187 : KMCommand( parent, msg ), mIdentity( identity ),
01188 mWin( QGuardedPtr< KMComposeWin >( win ))
01189 {
01190 }
01191
01192 KMCommand::Result KMForwardAttachedCommand::execute()
01193 {
01194 QPtrList<KMMessage> msgList = retrievedMsgs();
01195 KMMessage *fwdMsg = new KMMessage;
01196
01197 if (msgList.count() >= 2) {
01198
01199
01200 fwdMsg->initHeader(mIdentity);
01201 }
01202 else if (msgList.count() == 1) {
01203 KMMessage *msg = msgList.getFirst();
01204 fwdMsg->initFromMessage(msg);
01205 fwdMsg->setSubject( msg->forwardSubject() );
01206 }
01207
01208 fwdMsg->setAutomaticFields(true);
01209
01210 KCursorSaver busy(KBusyPtr::busy());
01211 if (!mWin)
01212 mWin = new KMComposeWin(fwdMsg, mIdentity);
01213
01214
01215 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01216
01217 msg->removePrivateHeaderFields();
01218 msg->removeHeaderField("BCC");
01219
01220 KMMessagePart *msgPart = new KMMessagePart;
01221 msgPart->setTypeStr("message");
01222 msgPart->setSubtypeStr("rfc822");
01223 msgPart->setCharset(msg->charset());
01224 msgPart->setName("forwarded message");
01225 msgPart->setContentDescription(msg->from()+": "+msg->subject());
01226 msgPart->setContentDisposition( "inline" );
01227
01228 QValueList<int> dummy;
01229 msgPart->setBodyAndGuessCte(msg->asString(), dummy, true);
01230 msgPart->setCharset("");
01231
01232 fwdMsg->link(msg, KMMsgStatusForwarded);
01233 mWin->addAttach(msgPart);
01234 }
01235
01236 mWin->show();
01237
01238 return OK;
01239 }
01240
01241
01242 KMRedirectCommand::KMRedirectCommand( QWidget *parent,
01243 KMMessage *msg )
01244 : KMCommand( parent, msg )
01245 {
01246 }
01247
01248 KMCommand::Result KMRedirectCommand::execute()
01249 {
01250
01251 KMComposeWin *win;
01252 KMMessage *msg = retrievedMessage();
01253 if ( !msg || !msg->codec() )
01254 return Failed;
01255
01256 KCursorSaver busy(KBusyPtr::busy());
01257 win = new KMComposeWin();
01258 win->setMsg(msg->createRedirect(), FALSE);
01259 win->setCharset(msg->codec()->mimeName());
01260 win->show();
01261
01262 return OK;
01263 }
01264
01265
01266 KMBounceCommand::KMBounceCommand( QWidget *parent,
01267 KMMessage *msg )
01268 : KMCommand( parent, msg )
01269 {
01270 }
01271
01272 KMCommand::Result KMBounceCommand::execute()
01273 {
01274 KMMessage *msg = retrievedMessage();
01275 KMMessage *newMsg = msg->createBounce( TRUE );
01276 if (newMsg)
01277 kmkernel->msgSender()->send(newMsg, kmkernel->msgSender()->sendImmediate());
01278
01279 return OK;
01280 }
01281
01282
01283 KMPrintCommand::KMPrintCommand( QWidget *parent,
01284 KMMessage *msg, bool htmlOverride, const QTextCodec* codec )
01285 : KMCommand( parent, msg ), mHtmlOverride( htmlOverride ), mCodec( codec )
01286 {
01287 }
01288
01289 KMCommand::Result KMPrintCommand::execute()
01290 {
01291 KMReaderWin printWin( 0, 0, 0 );
01292 printWin.setPrinting(TRUE);
01293 printWin.readConfig();
01294 printWin.setHtmlOverride( mHtmlOverride );
01295 printWin.setOverrideCodec( mCodec );
01296 printWin.setMsg(retrievedMessage(), TRUE);
01297 printWin.printMsg();
01298
01299 return OK;
01300 }
01301
01302
01303 KMSetStatusCommand::KMSetStatusCommand( KMMsgStatus status,
01304 const QValueList<Q_UINT32> &serNums, bool toggle )
01305 : mStatus( status ), mSerNums( serNums ), mToggle( toggle )
01306 {
01307 }
01308
01309 KMCommand::Result KMSetStatusCommand::execute()
01310 {
01311 QValueListIterator<Q_UINT32> it;
01312 int idx = -1;
01313 KMFolder *folder = 0;
01314 bool parentStatus = false;
01315
01316
01317
01318 if (mToggle) {
01319 KMMsgBase *msg;
01320 kmkernel->msgDict()->getLocation( *mSerNums.begin(), &folder, &idx );
01321 if (folder) {
01322 msg = folder->getMsgBase(idx);
01323 if (msg && (msg->status()&mStatus))
01324 parentStatus = true;
01325 else
01326 parentStatus = false;
01327 }
01328 }
01329 QMap< KMFolder*, QValueList<int> > folderMap;
01330 for ( it = mSerNums.begin(); it != mSerNums.end(); ++it ) {
01331 kmkernel->msgDict()->getLocation( *it, &folder, &idx );
01332 if (folder) {
01333 if (mToggle) {
01334 KMMsgBase *msg = folder->getMsgBase(idx);
01335
01336 if (msg) {
01337 bool myStatus;
01338 if (msg->status()&mStatus)
01339 myStatus = true;
01340 else
01341 myStatus = false;
01342 if (myStatus != parentStatus)
01343 continue;
01344 }
01345 }
01346
01347
01348 folderMap[folder].append(idx);
01349 }
01350 }
01351 QMapIterator< KMFolder*, QValueList<int> > it2 = folderMap.begin();
01352 while ( it2 != folderMap.end() ) {
01353 KMFolder *f = it2.key();
01354 f->setStatus( (*it2), mStatus, mToggle );
01355 ++it2;
01356 }
01357
01358
01359 return OK;
01360 }
01361
01362
01363 KMFilterCommand::KMFilterCommand( const QCString &field, const QString &value )
01364 : mField( field ), mValue( value )
01365 {
01366 }
01367
01368 KMCommand::Result KMFilterCommand::execute()
01369 {
01370 kmkernel->filterMgr()->createFilter( mField, mValue );
01371
01372 return OK;
01373 }
01374
01375
01376 KMFilterActionCommand::KMFilterActionCommand( QWidget *parent,
01377 const QPtrList<KMMsgBase> &msgList,
01378 KMFilter *filter )
01379 : KMCommand( parent, msgList ), mFilter( filter )
01380 {
01381 }
01382
01383 KMCommand::Result KMFilterActionCommand::execute()
01384 {
01385 QPtrList<KMMessage> msgList = retrievedMsgs();
01386
01387 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next())
01388 if( msg->parent() )
01389 kmkernel->filterMgr()->tempOpenFolder(msg->parent());
01390
01391 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01392 msg->setTransferInProgress(false);
01393
01394 int filterResult = kmkernel->filterMgr()->process(msg, mFilter);
01395 if (filterResult == 2) {
01396
01397 perror("Critical error");
01398 kmkernel->emergencyExit( i18n("Not enough free disk space?" ));
01399 }
01400 msg->setTransferInProgress(true);
01401 }
01402
01403 return OK;
01404 }
01405
01406
01407 KMMetaFilterActionCommand::KMMetaFilterActionCommand( KMFilter *filter,
01408 KMHeaders *headers,
01409 KMMainWidget *main )
01410 : QObject( main ),
01411 mFilter( filter ), mHeaders( headers ), mMainWidget( main )
01412 {
01413 }
01414
01415 void KMMetaFilterActionCommand::start()
01416 {
01417 #if 0 // use action scheduler
01418 KMFilterMgr::FilterSet set = KMFilterMgr::All;
01419 QPtrList<KMFilter> filters;
01420 filters.append( mFilter );
01421 ActionScheduler *scheduler = new ActionScheduler( set, filters, mHeaders );
01422 scheduler->setAlwaysMatch( true );
01423 scheduler->setAutoDestruct( true );
01424
01425 int contentX, contentY;
01426 KMHeaderItem *nextItem = mHeaders->prepareMove( &contentX, &contentY );
01427 QPtrList<KMMsgBase> msgList = *mHeaders->selectedMsgs(true);
01428 mHeaders->finalizeMove( nextItem, contentX, contentY );
01429
01430
01431 for (KMMsgBase *msg = msgList.first(); msg; msg = msgList.next())
01432 scheduler->execFilters( msg );
01433 #else
01434 KMCommand *filterCommand = new KMFilterActionCommand( mMainWidget,
01435 *mHeaders->selectedMsgs(), mFilter);
01436 filterCommand->start();
01437 int contentX, contentY;
01438 KMHeaderItem *item = mHeaders->prepareMove( &contentX, &contentY );
01439 mHeaders->finalizeMove( item, contentX, contentY );
01440 #endif
01441 }
01442
01443
01444 KMMailingListFilterCommand::KMMailingListFilterCommand( QWidget *parent,
01445 KMMessage *msg )
01446 : KMCommand( parent, msg )
01447 {
01448 }
01449
01450 KMCommand::Result KMMailingListFilterCommand::execute()
01451 {
01452 QCString name;
01453 QString value;
01454 KMMessage *msg = retrievedMessage();
01455 if (!msg)
01456 return Failed;
01457
01458 if ( !MailingList::name( msg, name, value ).isEmpty() ) {
01459 kmkernel->filterMgr()->createFilter( name, value );
01460 return OK;
01461 }
01462 else
01463 return Failed;
01464 }
01465
01466
01467 void KMMenuCommand::folderToPopupMenu(bool move,
01468 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01469 {
01470 while ( menu->count() )
01471 {
01472 QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
01473 if (popup)
01474 delete popup;
01475 else
01476 menu->removeItemAt( 0 );
01477 }
01478
01479 if (!kmkernel->imapFolderMgr()->dir().first() &&
01480 !kmkernel->dimapFolderMgr()->dir().first())
01481 {
01482 makeFolderMenu( &kmkernel->folderMgr()->dir(), move,
01483 receiver, aMenuToFolder, menu );
01484 } else {
01485
01486 QPopupMenu* subMenu = new QPopupMenu(menu);
01487 makeFolderMenu( &kmkernel->folderMgr()->dir(),
01488 move, receiver, aMenuToFolder, subMenu );
01489 menu->insertItem( i18n( "Local Folders" ), subMenu );
01490 KMFolderDir* fdir = &kmkernel->imapFolderMgr()->dir();
01491 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01492 if (node->isDir())
01493 continue;
01494 subMenu = new QPopupMenu(menu);
01495 makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01496 menu->insertItem( node->label(), subMenu );
01497 }
01498 fdir = &kmkernel->dimapFolderMgr()->dir();
01499 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01500 if (node->isDir())
01501 continue;
01502 subMenu = new QPopupMenu(menu);
01503 makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01504 menu->insertItem( node->label(), subMenu );
01505 }
01506 }
01507 }
01508
01509 void KMMenuCommand::makeFolderMenu(KMFolderNode* node, bool move,
01510 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01511 {
01512
01513 if (move)
01514 {
01515 disconnect(menu, SIGNAL(activated(int)), receiver,
01516 SLOT(moveSelectedToFolder(int)));
01517 connect(menu, SIGNAL(activated(int)), receiver,
01518 SLOT(moveSelectedToFolder(int)));
01519 } else {
01520 disconnect(menu, SIGNAL(activated(int)), receiver,
01521 SLOT(copySelectedToFolder(int)));
01522 connect(menu, SIGNAL(activated(int)), receiver,
01523 SLOT(copySelectedToFolder(int)));
01524 }
01525
01526 KMFolder *folder = 0;
01527 KMFolderDir *folderDir = 0;
01528 if (node->isDir()) {
01529 folderDir = static_cast<KMFolderDir*>(node);
01530 } else {
01531 folder = static_cast<KMFolder*>(node);
01532 folderDir = folder->child();
01533 }
01534
01535 if (folder && !folder->noContent())
01536 {
01537 int menuId;
01538 if (move)
01539 menuId = menu->insertItem(i18n("Move to This Folder"));
01540 else
01541 menuId = menu->insertItem(i18n("Copy to This Folder"));
01542 aMenuToFolder->insert( menuId, folder );
01543 menu->setItemEnabled( menuId, !folder->isReadOnly() );
01544 menu->insertSeparator();
01545 }
01546
01547 if (!folderDir)
01548 return;
01549
01550 for (KMFolderNode *it = folderDir->first(); it; it = folderDir->next() ) {
01551 if (it->isDir())
01552 continue;
01553 KMFolder *child = static_cast<KMFolder*>(it);
01554 QString label = child->label();
01555 label.replace("&","&&");
01556 if (child->child() && child->child()->first()) {
01557
01558 QPopupMenu *subMenu = new QPopupMenu(menu, "subMenu");
01559 makeFolderMenu( child, move, receiver,
01560 aMenuToFolder, subMenu );
01561 menu->insertItem( label, subMenu );
01562 } else {
01563
01564 int menuId = menu->insertItem( label );
01565 aMenuToFolder->insert( menuId, child );
01566 menu->setItemEnabled( menuId, !child->isReadOnly() );
01567 }
01568 }
01569 return;
01570 }
01571
01572
01573 KMCopyCommand::KMCopyCommand( KMFolder* destFolder,
01574 const QPtrList<KMMsgBase> &msgList )
01575 :mDestFolder( destFolder ), mMsgList( msgList )
01576 {
01577 }
01578
01579 KMCopyCommand::KMCopyCommand( KMFolder* destFolder, KMMessage * msg )
01580 :mDestFolder( destFolder )
01581 {
01582 mMsgList.append( &msg->toMsgBase() );
01583 }
01584
01585 KMCommand::Result KMCopyCommand::execute()
01586 {
01587 KMMsgBase *msgBase;
01588 KMMessage *msg, *newMsg;
01589 int idx = -1;
01590 bool isMessage;
01591 QPtrList<KMMessage> list;
01592
01593 if (mDestFolder && mDestFolder->open() != 0)
01594 return Failed;
01595
01596 KCursorSaver busy(KBusyPtr::busy());
01597
01598 for (msgBase = mMsgList.first(); msgBase; msgBase = mMsgList.next() )
01599 {
01600 KMFolder *srcFolder = msgBase->parent();
01601 if (isMessage = msgBase->isMessage())
01602 {
01603 msg = static_cast<KMMessage*>(msgBase);
01604 } else {
01605 idx = srcFolder->find(msgBase);
01606 assert(idx != -1);
01607 msg = srcFolder->getMsg(idx);
01608 }
01609
01610 if (srcFolder &&
01611 (srcFolder->folderType()== KMFolderTypeImap) &&
01612 (mDestFolder->folderType() == KMFolderTypeImap) &&
01613 (static_cast<KMFolderImap*>(srcFolder->storage())->account() ==
01614 static_cast<KMFolderImap*>(mDestFolder->storage())->account()))
01615 {
01616 list.append(msg);
01617 } else {
01618 newMsg = new KMMessage;
01619 newMsg->setComplete(msg->isComplete());
01620
01621 if (!newMsg->isComplete())
01622 newMsg->setReadyToShow(false);
01623 newMsg->fromString(msg->asString());
01624 newMsg->setStatus(msg->status());
01625
01626 if (srcFolder && !newMsg->isComplete())
01627 {
01628 newMsg->setParent(msg->parent());
01629 FolderJob *job = srcFolder->createJob(newMsg);
01630 job->setCancellable( false );
01631 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
01632 mDestFolder, SLOT(reallyAddCopyOfMsg(KMMessage*)));
01633
01634 newMsg->setTransferInProgress(true);
01635 job->start();
01636 } else {
01637 int rc, index;
01638 mDestFolder->open();
01639 rc = mDestFolder->addMsg(newMsg, &index);
01640 if (rc == 0 && index != -1)
01641 mDestFolder->unGetMsg( mDestFolder->count() - 1 );
01642 mDestFolder->close();
01643 }
01644 }
01645
01646 if (!isMessage && list.isEmpty())
01647 {
01648 assert(idx != -1);
01649 srcFolder->unGetMsg( idx );
01650 }
01651
01652 }
01653 mDestFolder->close();
01654
01655
01656
01657
01658 if (!list.isEmpty())
01659 {
01660
01661 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(mDestFolder->storage());
01662 imapDestFolder->copyMsg(list);
01663 imapDestFolder->getFolder();
01664 }
01665
01666 return OK;
01667 }
01668
01669
01670 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01671 const QPtrList<KMMsgBase> &msgList)
01672 :mDestFolder( destFolder ), mMsgList( msgList ), mProgressItem( 0 )
01673 {
01674 setDeletesItself( true );
01675 }
01676
01677 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01678 KMMessage *msg )
01679 :mDestFolder( destFolder ), mProgressItem( 0 )
01680 {
01681 setDeletesItself( true );
01682 mMsgList.append( &msg->toMsgBase() );
01683 }
01684
01685 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01686 KMMsgBase *msgBase )
01687 :mDestFolder( destFolder ), mProgressItem( 0 )
01688 {
01689 setDeletesItself( true );
01690 mMsgList.append( msgBase );
01691 }
01692
01693 KMMoveCommand::KMMoveCommand( Q_UINT32 )
01694 :mProgressItem( 0 )
01695 {
01696 setDeletesItself( true );
01697 }
01698
01699 KMCommand::Result KMMoveCommand::execute()
01700 {
01701 setEmitsCompletedItself( true );
01702 typedef QMap< KMFolder*, QPtrList<KMMessage>* > FolderToMessageListMap;
01703 FolderToMessageListMap folderDeleteList;
01704
01705 if (mDestFolder && mDestFolder->open() != 0) {
01706 completeMove( Failed );
01707 return Failed;
01708 }
01709 KCursorSaver busy(KBusyPtr::busy());
01710
01711
01712 Q_ASSERT( !mProgressItem );
01713 mProgressItem =
01714 ProgressManager::createProgressItem (
01715 "move"+ProgressManager::getUniqueID(),
01716 mDestFolder ? i18n( "Moving messages" ) : i18n( "Deleting messages" ) );
01717 connect( mProgressItem, SIGNAL( progressItemCanceled( ProgressItem* ) ),
01718 this, SLOT( slotMoveCanceled() ) );
01719
01720 KMMessage *msg;
01721 KMMsgBase *msgBase;
01722 int rc = 0;
01723 int index;
01724 QPtrList<KMMessage> list;
01725 int undoId = -1;
01726
01727 if (mDestFolder) {
01728 connect (mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
01729 this, SLOT(slotMsgAddedToDestFolder(KMFolder*, Q_UINT32)));
01730
01731 }
01732 for ( msgBase=mMsgList.first(); msgBase; msgBase=mMsgList.next() ) {
01733 mLostBoys.append( msgBase->getMsgSerNum() );
01734 }
01735 mProgressItem->setTotalItems( mMsgList.count() );
01736
01737 for (msgBase=mMsgList.first(); msgBase && !rc; msgBase=mMsgList.next()) {
01738 KMFolder *srcFolder = msgBase->parent();
01739 if (srcFolder == mDestFolder)
01740 continue;
01741 bool undo = msgBase->enableUndo();
01742 int idx = srcFolder->find(msgBase);
01743 assert(idx != -1);
01744 if ( msgBase->isMessage() )
01745 msg = static_cast<KMMessage*>(msgBase);
01746 else
01747 msg = srcFolder->getMsg(idx);
01748
01749 if ( msg->transferInProgress() &&
01750 srcFolder->folderType() == KMFolderTypeImap )
01751 {
01752
01753 msg->setTransferInProgress( false, true );
01754 static_cast<KMFolderImap*>(srcFolder->storage())->ignoreJobsForMessage( msg );
01755 }
01756
01757 if (mDestFolder) {
01758 if (mDestFolder->folderType() == KMFolderTypeImap) {
01759
01760
01761
01762 KMFolderImap *imapFolder = static_cast<KMFolderImap*> ( mDestFolder->storage() );
01763 disconnect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
01764 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
01765
01766 connect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
01767 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
01768 list.append(msg);
01769 } else {
01770
01771 mDestFolder->open();
01772 rc = mDestFolder->moveMsg(msg, &index);
01773 if (rc == 0 && index != -1) {
01774 KMMsgBase *mb = mDestFolder->unGetMsg( mDestFolder->count() - 1 );
01775 if (undo && mb)
01776 {
01777 if ( undoId == -1 )
01778 undoId = kmkernel->undoStack()->newUndoAction( srcFolder, mDestFolder );
01779 kmkernel->undoStack()->addMsgToAction( undoId, mb->getMsgSerNum() );
01780 }
01781 mDestFolder->close();
01782 } else if (rc != 0) {
01783
01784
01785 completeMove( Failed );
01786 mDestFolder->close();
01787 return Failed;
01788 }
01789 }
01790 } else {
01791
01792
01793 if (srcFolder->folderType() == KMFolderTypeImap) {
01794 if (!folderDeleteList[srcFolder])
01795 folderDeleteList[srcFolder] = new QPtrList<KMMessage>;
01796 folderDeleteList[srcFolder]->append( msg );
01797 } else {
01798 srcFolder->removeMsg(idx);
01799 delete msg;
01800 }
01801 }
01802 }
01803 if (!list.isEmpty() && mDestFolder) {
01804 mDestFolder->moveMsg(list, &index);
01805 } else {
01806 FolderToMessageListMap::Iterator it;
01807 for ( it = folderDeleteList.begin(); it != folderDeleteList.end(); ++it ) {
01808 it.key()->removeMsg(*it.data());
01809 delete it.data();
01810 }
01811
01812
01813
01814 KMFolder *srcFolder = 0;
01815 if ( mMsgList.first() ) {
01816 srcFolder = mMsgList.first()->parent();
01817 if ( mDestFolder && mDestFolder == srcFolder ) {
01818 completeMove( OK );
01819 }
01820 }
01821 if ( !mDestFolder ) {
01822 completeMove( OK );
01823 }
01824 }
01825
01826 return OK;
01827 }
01828
01829 void KMMoveCommand::slotImapFolderCompleted(KMFolderImap *, bool success)
01830 {
01831 if ( success ) {
01832
01833
01834
01835
01836
01837
01838 if ( !mLostBoys.isEmpty() ) {
01839 kdDebug(5006) << "### Not all moved messages reported back that they were " << endl
01840 << "### added to the target folder. Did uidValidity change? " << endl;
01841 }
01842 completeMove( OK );
01843 } else {
01844
01845 completeMove( Failed );
01846 }
01847 }
01848
01849 void KMMoveCommand::slotMsgAddedToDestFolder(KMFolder *folder, Q_UINT32 serNum)
01850 {
01851 if (folder != mDestFolder || !mLostBoys.contains( serNum ) ) {
01852 kdDebug(5006) << "KMMoveCommand::msgAddedToDestFolder different "
01853 "folder or invalid serial number." << endl;
01854 return;
01855 }
01856 mLostBoys.remove(serNum);
01857 if ( mLostBoys.isEmpty() ) {
01858
01859 if (mDestFolder && mDestFolder->folderType() != KMFolderTypeImap) {
01860 mDestFolder->sync();
01861 }
01862 completeMove( OK );
01863 } else {
01864 mProgressItem->incCompletedItems();
01865 mProgressItem->updateProgress();
01866 }
01867 }
01868
01869 void KMMoveCommand::completeMove( Result result )
01870 {
01871 if ( mDestFolder )
01872 mDestFolder->close();
01873 while ( !mOpenedFolders.empty() ) {
01874 KMFolder *folder = mOpenedFolders.back();
01875 mOpenedFolders.pop_back();
01876 folder->close();
01877 }
01878 if ( mProgressItem )
01879 mProgressItem->setComplete();
01880 setResult( result );
01881 emit completed( this );
01882 deleteLater();
01883 }
01884
01885 void KMMoveCommand::slotMoveCanceled()
01886 {
01887 completeMove( Canceled );
01888 }
01889
01890
01891 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder,
01892 const QPtrList<KMMsgBase> &msgList )
01893 :KMMoveCommand( findTrashFolder( srcFolder ), msgList)
01894 {
01895 srcFolder->open();
01896 mOpenedFolders.push_back( srcFolder );
01897 }
01898
01899 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder, KMMessage * msg )
01900 :KMMoveCommand( findTrashFolder( srcFolder ), msg)
01901 {
01902 srcFolder->open();
01903 mOpenedFolders.push_back( srcFolder );
01904 }
01905
01906 KMDeleteMsgCommand::KMDeleteMsgCommand( Q_UINT32 sernum )
01907 :KMMoveCommand( sernum )
01908 {
01909 KMFolder *srcFolder;
01910 int idx;
01911 kmkernel->msgDict()->getLocation( sernum, &srcFolder, &idx );
01912 KMMsgBase *msg = srcFolder->getMsgBase( idx );
01913 srcFolder->open();
01914 mOpenedFolders.push_back( srcFolder );
01915 addMsg( msg );
01916 setDestFolder( findTrashFolder( srcFolder ) );
01917 }
01918
01919 KMFolder * KMDeleteMsgCommand::findTrashFolder( KMFolder * folder )
01920 {
01921 KMFolder* trash = folder->trashFolder();
01922 if( !trash )
01923 trash = kmkernel->trashFolder();
01924 if( trash != folder )
01925 return trash;
01926 return 0;
01927 }
01928
01929
01930 KMUrlClickedCommand::KMUrlClickedCommand( const KURL &url, uint identity,
01931 KMReaderWin *readerWin, bool htmlPref, KMMainWidget *mainWidget )
01932 :mUrl( url ), mIdentity( identity ), mReaderWin( readerWin ),
01933 mHtmlPref( htmlPref ), mMainWidget( mainWidget )
01934 {
01935 }
01936
01937 KMCommand::Result KMUrlClickedCommand::execute()
01938 {
01939 KMComposeWin *win;
01940 KMMessage* msg;
01941
01942 if (mUrl.protocol() == "mailto")
01943 {
01944 msg = new KMMessage;
01945 msg->initHeader(mIdentity);
01946 msg->setCharset("utf-8");
01947 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
01948 QString query=mUrl.query();
01949 while (!query.isEmpty()) {
01950 QString queryPart;
01951 int secondQuery = query.find('?',1);
01952 if (secondQuery != -1)
01953 queryPart = query.left(secondQuery);
01954 else
01955 queryPart = query;
01956 query = query.mid(queryPart.length());
01957
01958 if (queryPart.left(9) == "?subject=")
01959 msg->setSubject( KURL::decode_string(queryPart.mid(9)) );
01960 else if (queryPart.left(6) == "?body=")
01961
01962
01963 msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() );
01964 else if (queryPart.left(4) == "?cc=")
01965 msg->setCc( KURL::decode_string(queryPart.mid(4)) );
01966 }
01967
01968 win = new KMComposeWin(msg, mIdentity);
01969 win->setCharset("", TRUE);
01970 win->show();
01971 }
01972 else if ( mUrl.protocol() == "im" )
01973 {
01974 kmkernel->imProxy()->chatWithContact( mUrl.path() );
01975 }
01976 else if ((mUrl.protocol() == "http") || (mUrl.protocol() == "https") ||
01977 (mUrl.protocol() == "ftp") || (mUrl.protocol() == "file") ||
01978 (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
01979 (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
01980 (mUrl.protocol() == "smb"))
01981 {
01982 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n("Opening URL..."));
01983 KMimeType::Ptr mime = KMimeType::findByURL( mUrl );
01984 if (mime->name() == "application/x-desktop" ||
01985 mime->name() == "application/x-executable" ||
01986 mime->name() == "application/x-msdos-program" ||
01987 mime->name() == "application/x-shellscript" )
01988 {
01989 if (KMessageBox::warningYesNo( 0, i18n( "<qt>Do you really want to execute <b>%1</b>?</qt>" )
01990 .arg( mUrl.prettyURL() ) ) != KMessageBox::Yes)
01991 return Canceled;
01992 }
01993 (void) new KRun( mUrl );
01994 }
01995 else
01996 return Failed;
01997
01998 return OK;
01999 }
02000
02001 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, KMMessage *msg )
02002 : KMCommand( parent, msg ), mImplicitAttachments( true ), mEncoded( false )
02003 {
02004 }
02005
02006 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, const QPtrList<KMMsgBase>& msgs )
02007 : KMCommand( parent, msgs ), mImplicitAttachments( true ), mEncoded( false )
02008 {
02009 }
02010
02011 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, QPtrList<partNode>& attachments,
02012 KMMessage *msg, bool encoded )
02013 : KMCommand( parent, msg ), mImplicitAttachments( false ),
02014 mEncoded( encoded )
02015 {
02016
02017 msg->setComplete( true );
02018 for ( QPtrListIterator<partNode> it( attachments ); it.current(); ++it ) {
02019 mAttachmentMap.insert( it.current(), msg );
02020 }
02021 }
02022
02023 KMCommand::Result KMSaveAttachmentsCommand::execute()
02024 {
02025 setEmitsCompletedItself( true );
02026 if ( mImplicitAttachments ) {
02027 QPtrList<KMMessage> msgList = retrievedMsgs();
02028 KMMessage *msg;
02029 for ( QPtrListIterator<KMMessage> itr( msgList );
02030 ( msg = itr.current() );
02031 ++itr ) {
02032 partNode *rootNode = partNode::fromMessage( msg );
02033 for ( partNode *child = rootNode; child;
02034 child = child->firstChild() ) {
02035 for ( partNode *node = child; node; node = node->nextSibling() ) {
02036 if ( node->type() != DwMime::kTypeMultipart )
02037 mAttachmentMap.insert( node, msg );
02038 }
02039 }
02040 }
02041 }
02042 setDeletesItself( true );
02043
02044 KMLoadPartsCommand *command = new KMLoadPartsCommand( mAttachmentMap );
02045 connect( command, SIGNAL( partsRetrieved() ),
02046 this, SLOT( slotSaveAll() ) );
02047 command->start();
02048
02049 return OK;
02050 }
02051
02052 void KMSaveAttachmentsCommand::slotSaveAll()
02053 {
02054
02055
02056
02057 if ( mImplicitAttachments ) {
02058 for ( PartNodeMessageMap::iterator it = mAttachmentMap.begin();
02059 it != mAttachmentMap.end(); ) {
02060
02061
02062
02063 if ( it.key()->msgPart().fileName().stripWhiteSpace().isEmpty() &&
02064 ( it.key()->msgPart().name().stripWhiteSpace().isEmpty() ||
02065 !it.key()->parentNode() ) ) {
02066 PartNodeMessageMap::iterator delIt = it;
02067 ++it;
02068 mAttachmentMap.remove( delIt );
02069 }
02070 else
02071 ++it;
02072 }
02073 if ( mAttachmentMap.isEmpty() ) {
02074 KMessageBox::information( 0, i18n("Found no attachments to save.") );
02075 setResult( OK );
02076 emit completed( this );
02077 delete this;
02078 return;
02079 }
02080 }
02081
02082 KURL url, dirUrl;
02083 if ( mAttachmentMap.count() > 1 ) {
02084
02085 KFileDialog fdlg( ":saveAttachments", QString::null, parentWidget(),
02086 "save attachments dialog", true );
02087 fdlg.setCaption( i18n("Save Attachments To") );
02088 fdlg.setOperationMode( KFileDialog::Saving );
02089 fdlg.setMode( (unsigned int) KFile::Directory );
02090 if ( fdlg.exec() == QDialog::Rejected || !fdlg.selectedURL().isValid() ) {
02091 setResult( Canceled );
02092 emit completed( this );
02093 delete this;
02094 return;
02095 }
02096 dirUrl = fdlg.selectedURL();
02097 }
02098 else {
02099
02100 partNode *node = mAttachmentMap.begin().key();
02101
02102 QString s =
02103 node->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02104 if ( s.isEmpty() )
02105 s = node->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02106 if ( s.isEmpty() )
02107 s = i18n("filename for an unnamed attachment", "attachment.1");
02108 url = KFileDialog::getSaveURL( s, QString::null, parentWidget(),
02109 QString::null );
02110 if ( url.isEmpty() ) {
02111 setResult( Canceled );
02112 emit completed( this );
02113 delete this;
02114 return;
02115 }
02116 }
02117
02118 Result globalResult = OK;
02119 int unnamedAtmCount = 0;
02120 for ( PartNodeMessageMap::const_iterator it = mAttachmentMap.begin();
02121 it != mAttachmentMap.end();
02122 ++it ) {
02123 KURL curUrl;
02124 if ( !dirUrl.isEmpty() ) {
02125 curUrl = dirUrl;
02126 QString s =
02127 it.key()->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02128 if ( s.isEmpty() )
02129 s = it.key()->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02130 if ( s.isEmpty() ) {
02131 ++unnamedAtmCount;
02132 s = i18n("filename for the %1-th unnamed attachment",
02133 "attachment.%1")
02134 .arg( unnamedAtmCount );
02135 }
02136 curUrl.setFileName( s );
02137 } else {
02138 curUrl = url;
02139 }
02140
02141 if ( !curUrl.isEmpty() ) {
02142 if ( KIO::NetAccess::exists( curUrl, false, parentWidget() ) ) {
02143 if ( KMessageBox::warningContinueCancel( parentWidget(),
02144 i18n( "A file named %1 already exists. Do you want to overwrite it?" )
02145 .arg( curUrl.fileName() ),
02146 i18n( "File Already Exists" ), i18n("Overwrite") ) == KMessageBox::Cancel) {
02147 continue;
02148 }
02149 }
02150
02151 const Result result = saveItem( it.key(), curUrl );
02152 if ( result != OK )
02153 globalResult = result;
02154 }
02155 }
02156 setResult( globalResult );
02157 emit completed( this );
02158 delete this;
02159 }
02160
02161 KMCommand::Result KMSaveAttachmentsCommand::saveItem( partNode *node,
02162 const KURL& url )
02163 {
02164 bool bSaveEncrypted = false;
02165 bool bEncryptedParts = node->encryptionState() != KMMsgNotEncrypted;
02166 if( bEncryptedParts )
02167 if( KMessageBox::questionYesNo( parentWidget(),
02168 i18n( "The part %1 of the message is encrypted. Do you want to keep the encryption when saving?" ).
02169 arg( url.fileName() ),
02170 i18n( "KMail Question" ) ) ==
02171 KMessageBox::Yes )
02172 bSaveEncrypted = true;
02173
02174 bool bSaveWithSig = true;
02175 if( node->signatureState() != KMMsgNotSigned )
02176 if( KMessageBox::questionYesNo( parentWidget(),
02177 i18n( "The part %1 of the message is signed. Do you want to keep the signature when saving?" ).
02178 arg( url.fileName() ),
02179 i18n( "KMail Question" ) ) !=
02180 KMessageBox::Yes )
02181 bSaveWithSig = false;
02182
02183 QByteArray data;
02184 if ( mEncoded )
02185 {
02186
02187
02188 QCString cstr( node->msgPart().body() );
02189 data = cstr;
02190 data.resize(data.size() - 1);
02191 }
02192 else
02193 {
02194 if( bSaveEncrypted || !bEncryptedParts) {
02195 partNode *dataNode = node;
02196 QCString rawReplyString;
02197 bool gotRawReplyString = false;
02198 if( !bSaveWithSig ) {
02199 if( DwMime::kTypeMultipart == node->type() &&
02200 DwMime::kSubtypeSigned == node->subType() ){
02201
02202 if( node->findType( DwMime::kTypeApplication,
02203 DwMime::kSubtypePgpSignature,
02204 TRUE, false ) ){
02205 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02206 DwMime::kSubtypePgpSignature,
02207 TRUE, false );
02208 }else if( node->findType( DwMime::kTypeApplication,
02209 DwMime::kSubtypePkcs7Mime,
02210 TRUE, false ) ){
02211 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02212 DwMime::kSubtypePkcs7Mime,
02213 TRUE, false );
02214 }else{
02215 dataNode = node->findTypeNot( DwMime::kTypeMultipart,
02216 DwMime::kSubtypeUnknown,
02217 TRUE, false );
02218 }
02219 }else{
02220 ObjectTreeParser otp( 0, 0, false, false, false );
02221
02222
02223 dataNode->setProcessed( false, true );
02224 otp.parseObjectTree( dataNode );
02225
02226 rawReplyString = otp.rawReplyString();
02227 gotRawReplyString = true;
02228 }
02229 }
02230 QByteArray cstr = gotRawReplyString
02231 ? rawReplyString
02232 : dataNode->msgPart().bodyDecodedBinary();
02233 data = cstr;
02234 size_t size = cstr.size();
02235 if ( dataNode->msgPart().type() == DwMime::kTypeText ) {
02236
02237 size = KMFolder::crlf2lf( cstr.data(), size );
02238 }
02239 data.resize( size );
02240 }
02241 }
02242 QDataStream ds;
02243 QFile file;
02244 KTempFile tf;
02245 tf.setAutoDelete( true );
02246 if ( url.isLocalFile() )
02247 {
02248
02249 file.setName( url.path() );
02250 if ( !file.open( IO_WriteOnly ) )
02251 {
02252 KMessageBox::error( parentWidget(),
02253 i18n( "%2 is detailed error description",
02254 "Could not write the file %1:\n%2" )
02255 .arg( file.name() )
02256 .arg( QString::fromLocal8Bit( strerror( errno ) ) ),
02257 i18n( "KMail Error" ) );
02258 return Failed;
02259 }
02260 fchmod( file.handle(), S_IRUSR | S_IWUSR );
02261 ds.setDevice( &file );
02262 } else
02263 {
02264
02265 ds.setDevice( tf.file() );
02266 }
02267
02268 ds.writeRawBytes( data.data(), data.size() );
02269 if ( !url.isLocalFile() )
02270 {
02271 tf.close();
02272 if ( !KIO::NetAccess::upload( tf.name(), url, parentWidget() ) )
02273 {
02274 KMessageBox::error( parentWidget(),
02275 i18n( "Could not write the file %1." )
02276 .arg( url.path() ),
02277 i18n( "KMail Error" ) );
02278 return Failed;
02279 }
02280 } else
02281 file.close();
02282 return OK;
02283 }
02284
02285 KMLoadPartsCommand::KMLoadPartsCommand( QPtrList<partNode>& parts, KMMessage *msg )
02286 : mNeedsRetrieval( 0 )
02287 {
02288 for ( QPtrListIterator<partNode> it( parts ); it.current(); ++it ) {
02289 mPartMap.insert( it.current(), msg );
02290 }
02291 }
02292
02293 KMLoadPartsCommand::KMLoadPartsCommand( partNode *node, KMMessage *msg )
02294 : mNeedsRetrieval( 0 )
02295 {
02296 mPartMap.insert( node, msg );
02297 }
02298
02299 KMLoadPartsCommand::KMLoadPartsCommand( PartNodeMessageMap& partMap )
02300 : mNeedsRetrieval( 0 ), mPartMap( partMap )
02301 {
02302 }
02303
02304 void KMLoadPartsCommand::slotStart()
02305 {
02306 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02307 it != mPartMap.end();
02308 ++it ) {
02309 if ( !it.key()->msgPart().isComplete() &&
02310 !it.key()->msgPart().partSpecifier().isEmpty() ) {
02311
02312 ++mNeedsRetrieval;
02313 KMFolder* curFolder = it.data()->parent();
02314 if ( curFolder ) {
02315 FolderJob *job =
02316 curFolder->createJob( it.data(), FolderJob::tGetMessage,
02317 0, it.key()->msgPart().partSpecifier() );
02318 job->setCancellable( false );
02319 connect( job, SIGNAL(messageUpdated(KMMessage*, QString)),
02320 this, SLOT(slotPartRetrieved(KMMessage*, QString)) );
02321 job->start();
02322 } else
02323 kdWarning(5006) << "KMLoadPartsCommand - msg has no parent" << endl;
02324 }
02325 }
02326 if ( mNeedsRetrieval == 0 )
02327 execute();
02328 }
02329
02330 void KMLoadPartsCommand::slotPartRetrieved( KMMessage *msg,
02331 QString partSpecifier )
02332 {
02333 DwBodyPart *part =
02334 msg->findDwBodyPart( msg->getFirstDwBodyPart(), partSpecifier );
02335 if ( part ) {
02336
02337 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02338 it != mPartMap.end();
02339 ++it ) {
02340 if ( it.key()->dwPart()->partId() == part->partId() )
02341 it.key()->setDwPart( part );
02342 }
02343 } else
02344 kdWarning(5006) << "KMLoadPartsCommand::slotPartRetrieved - could not find bodypart!" << endl;
02345 --mNeedsRetrieval;
02346 if ( mNeedsRetrieval == 0 )
02347 execute();
02348 }
02349
02350 KMCommand::Result KMLoadPartsCommand::execute()
02351 {
02352 emit partsRetrieved();
02353 setResult( OK );
02354 emit completed( this );
02355 deleteLater();
02356 return OK;
02357 }
02358
02359 KMResendMessageCommand::KMResendMessageCommand( QWidget *parent,
02360 KMMessage *msg )
02361 :KMCommand( parent, msg )
02362 {
02363 }
02364
02365 KMCommand::Result KMResendMessageCommand::execute()
02366 {
02367 KMComposeWin *win;
02368 KMMessage *msg = retrievedMessage();
02369
02370 KMMessage *newMsg = new KMMessage(*msg);
02371 newMsg->setCharset(msg->codec()->mimeName());
02372
02373 newMsg->removeHeaderField( "Message-Id" );
02374 newMsg->setParent( 0 );
02375
02376
02377 newMsg->removeHeaderField( "Date" );
02378
02379 win = new KMComposeWin();
02380 win->setMsg(newMsg, false, true);
02381 win->show();
02382
02383 return OK;
02384 }
02385
02386 KMMailingListCommand::KMMailingListCommand( QWidget *parent, KMFolder *folder )
02387 : KMCommand( parent ), mFolder( folder )
02388 {
02389 }
02390
02391 KMCommand::Result KMMailingListCommand::execute()
02392 {
02393 KURL::List lst = urls();
02394 QString handler = ( mFolder->mailingList().handler() == MailingList::KMail )
02395 ? "mailto" : "https";
02396
02397 KMCommand *command = 0;
02398 for ( KURL::List::Iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
02399 if ( handler == (*itr).protocol() ) {
02400 command = new KMUrlClickedCommand( *itr, mFolder->identity(), 0, false );
02401 }
02402 }
02403 if ( !command && !lst.empty() ) {
02404 command =
02405 new KMUrlClickedCommand( lst.first(), mFolder->identity(), 0, false );
02406 }
02407 if ( command ) {
02408 connect( command, SIGNAL( completed( KMCommand * ) ),
02409 this, SLOT( commandCompleted( KMCommand * ) ) );
02410 setDeletesItself( true );
02411 setEmitsCompletedItself( true );
02412 command->start();
02413 return OK;
02414 }
02415 return Failed;
02416 }
02417
02418 void KMMailingListCommand::commandCompleted( KMCommand *command )
02419 {
02420 setResult( command->result() );
02421 emit completed( this );
02422 delete this;
02423 }
02424
02425 KMMailingListPostCommand::KMMailingListPostCommand( QWidget *parent, KMFolder *folder )
02426 : KMMailingListCommand( parent, folder )
02427 {
02428 }
02429 KURL::List KMMailingListPostCommand::urls() const
02430 {
02431 return mFolder->mailingList().postURLS();
02432 }
02433
02434 KMMailingListSubscribeCommand::KMMailingListSubscribeCommand( QWidget *parent, KMFolder *folder )
02435 : KMMailingListCommand( parent, folder )
02436 {
02437 }
02438 KURL::List KMMailingListSubscribeCommand::urls() const
02439 {
02440 return mFolder->mailingList().subscribeURLS();
02441 }
02442
02443 KMMailingListUnsubscribeCommand::KMMailingListUnsubscribeCommand( QWidget *parent, KMFolder *folder )
02444 : KMMailingListCommand( parent, folder )
02445 {
02446 }
02447 KURL::List KMMailingListUnsubscribeCommand::urls() const
02448 {
02449 return mFolder->mailingList().unsubscribeURLS();
02450 }
02451
02452 KMMailingListArchivesCommand::KMMailingListArchivesCommand( QWidget *parent, KMFolder *folder )
02453 : KMMailingListCommand( parent, folder )
02454 {
02455 }
02456 KURL::List KMMailingListArchivesCommand::urls() const
02457 {
02458 return mFolder->mailingList().archiveURLS();
02459 }
02460
02461 KMMailingListHelpCommand::KMMailingListHelpCommand( QWidget *parent, KMFolder *folder )
02462 : KMMailingListCommand( parent, folder )
02463 {
02464 }
02465 KURL::List KMMailingListHelpCommand::urls() const
02466 {
02467 return mFolder->mailingList().helpURLS();
02468 }
02469
02470 KMIMChatCommand::KMIMChatCommand( const KURL &url, KMMessage *msg )
02471 :mUrl( url ), mMessage( msg )
02472 {
02473 }
02474
02475 KMCommand::Result KMIMChatCommand::execute()
02476 {
02477 kdDebug( 5006 ) << k_funcinfo << " URL is: " << mUrl << endl;
02478
02479 KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
02480 KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getEmailAddr( mUrl.path() ) ) ;
02481
02482
02483 if( addresses.count() == 1 ) {
02484 kmkernel->imProxy()->chatWithContact( addresses[0].uid() );
02485 return OK;
02486 }
02487 else
02488 {
02489 kdDebug( 5006 ) << "Didn't find exactly one addressee, couldn't tell who to chat to for that email address. Count = " << addresses.count() << endl;
02490
02491 QString apology;
02492 if ( addresses.isEmpty() )
02493 apology = i18n( "There is no Address Book entry for this email address. Add them to the Address Book and then add instant messaging addresses using your preferred messaging client." );
02494 else
02495 {
02496 apology = i18n( "More than one Address Book entry uses this email address:\n %1\n it is not possible to determine who to chat with." );
02497 QStringList nameList;
02498 KABC::AddresseeList::const_iterator it = addresses.begin();
02499 KABC::AddresseeList::const_iterator end = addresses.end();
02500 for ( ; it != end; ++it )
02501 {
02502 nameList.append( (*it).realName() );
02503 }
02504 QString names = nameList.join( QString::fromLatin1( ",\n" ) );
02505 apology = apology.arg( names );
02506 }
02507
02508 KMessageBox::sorry( parentWidget(), apology );
02509 return Failed;
02510 }
02511 }