00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "kmcommands.h"
00044
00045 #ifdef HAVE_CONFIG_H
00046 #include <config.h>
00047 #endif
00048
00049 #include <errno.h>
00050 #include <mimelib/enum.h>
00051 #include <mimelib/field.h>
00052 #include <mimelib/mimepp.h>
00053 #include <mimelib/string.h>
00054 #include <kapplication.h>
00055 #include <dcopclient.h>
00056
00057 #include <qtextcodec.h>
00058 #include <qpopupmenu.h>
00059 #include <qeventloop.h>
00060
00061 #include <libemailfunctions/email.h>
00062 #include <kdebug.h>
00063 #include <kfiledialog.h>
00064 #include <kabc/stdaddressbook.h>
00065 #include <kabc/addresseelist.h>
00066 #include <kdirselectdialog.h>
00067 #include <klocale.h>
00068 #include <kmessagebox.h>
00069 #include <kparts/browserextension.h>
00070 #include <kprogress.h>
00071 #include <krun.h>
00072 #include <kbookmarkmanager.h>
00073 #include <kstandarddirs.h>
00074 #include <ktempfile.h>
00075 #include <kimproxy.h>
00076 #include <kuserprofile.h>
00077
00078 #include <kio/job.h>
00079 #include <kio/netaccess.h>
00080
00081 #include "actionscheduler.h"
00082 using KMail::ActionScheduler;
00083 #include "mailinglist-magic.h"
00084 #include "kmaddrbook.h"
00085 #include <kaddrbook.h>
00086 #include "composer.h"
00087 #include "kmfiltermgr.h"
00088 #include "kmfoldermbox.h"
00089 #include "kmfolderimap.h"
00090 #include "kmfoldermgr.h"
00091 #include "kmheaders.h"
00092 #include "headeritem.h"
00093 #include "kmmainwidget.h"
00094 #include "kmmsgdict.h"
00095 #include "messagesender.h"
00096 #include "kmmsgpartdlg.h"
00097 #include "undostack.h"
00098 #include "kcursorsaver.h"
00099 #include "partNode.h"
00100 #include "objecttreeparser.h"
00101 using KMail::ObjectTreeParser;
00102 using KMail::FolderJob;
00103 #include "chiasmuskeyselector.h"
00104 #include "mailsourceviewer.h"
00105 using KMail::MailSourceViewer;
00106 #include "kmreadermainwin.h"
00107 #include "secondarywindow.h"
00108 using KMail::SecondaryWindow;
00109 #include "redirectdialog.h"
00110 using KMail::RedirectDialog;
00111 #include "util.h"
00112 #include "templateparser.h"
00113
00114 #include "broadcaststatus.h"
00115 #include "globalsettings.h"
00116
00117 #include <libkdepim/kfileio.h>
00118
00119 #include "progressmanager.h"
00120 using KPIM::ProgressManager;
00121 using KPIM::ProgressItem;
00122 #include <kmime_mdn.h>
00123 using namespace KMime;
00124
00125 #include <kleo/specialjob.h>
00126 #include <kleo/cryptobackend.h>
00127 #include <kleo/cryptobackendfactory.h>
00128
00129 #include <qclipboard.h>
00130
00131 #include <memory>
00132
00133 class LaterDeleterWithCommandCompletion : public KMail::Util::LaterDeleter
00134 {
00135 public:
00136 LaterDeleterWithCommandCompletion( KMCommand* command )
00137 :LaterDeleter( command ), m_result( KMCommand::Failed )
00138 {
00139 }
00140 ~LaterDeleterWithCommandCompletion()
00141 {
00142 setResult( m_result );
00143 KMCommand *command = static_cast<KMCommand*>( m_object );
00144 emit command->completed( command );
00145 }
00146 void setResult( KMCommand::Result v ) { m_result = v; }
00147 private:
00148 KMCommand::Result m_result;
00149 };
00150
00151
00152 KMCommand::KMCommand( QWidget *parent )
00153 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00154 mEmitsCompletedItself( false ), mParent( parent )
00155 {
00156 }
00157
00158 KMCommand::KMCommand( QWidget *parent, const QPtrList<KMMsgBase> &msgList )
00159 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00160 mEmitsCompletedItself( false ), mParent( parent ), mMsgList( msgList )
00161 {
00162 }
00163
00164 KMCommand::KMCommand( QWidget *parent, KMMsgBase *msgBase )
00165 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00166 mEmitsCompletedItself( false ), mParent( parent )
00167 {
00168 mMsgList.append( msgBase );
00169 }
00170
00171 KMCommand::KMCommand( QWidget *parent, KMMessage *msg )
00172 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00173 mEmitsCompletedItself( false ), mParent( parent )
00174 {
00175 if (msg)
00176 mMsgList.append( &msg->toMsgBase() );
00177 }
00178
00179 KMCommand::~KMCommand()
00180 {
00181 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00182 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00183 if (!(*fit))
00184 continue;
00185 (*fit)->close();
00186 }
00187 }
00188
00189 KMCommand::Result KMCommand::result()
00190 {
00191 if ( mResult == Undefined )
00192 kdDebug(5006) << k_funcinfo << "mResult is Undefined" << endl;
00193 return mResult;
00194 }
00195
00196 void KMCommand::start()
00197 {
00198 QTimer::singleShot( 0, this, SLOT( slotStart() ) );
00199 }
00200
00201
00202 const QPtrList<KMMessage> KMCommand::retrievedMsgs() const
00203 {
00204 return mRetrievedMsgs;
00205 }
00206
00207 KMMessage *KMCommand::retrievedMessage() const
00208 {
00209 return mRetrievedMsgs.getFirst();
00210 }
00211
00212 QWidget *KMCommand::parentWidget() const
00213 {
00214 return mParent;
00215 }
00216
00217 int KMCommand::mCountJobs = 0;
00218
00219 void KMCommand::slotStart()
00220 {
00221 connect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00222 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00223 kmkernel->filterMgr()->ref();
00224
00225 if (mMsgList.find(0) != -1) {
00226 emit messagesTransfered( Failed );
00227 return;
00228 }
00229
00230 if ((mMsgList.count() == 1) &&
00231 (mMsgList.getFirst()->isMessage()) &&
00232 (mMsgList.getFirst()->parent() == 0))
00233 {
00234
00235 mRetrievedMsgs.append((KMMessage*)mMsgList.getFirst());
00236 emit messagesTransfered( OK );
00237 return;
00238 }
00239
00240 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00241 if (!mb->parent()) {
00242 emit messagesTransfered( Failed );
00243 return;
00244 } else {
00245 keepFolderOpen( mb->parent() );
00246 }
00247
00248
00249 transferSelectedMsgs();
00250 }
00251
00252 void KMCommand::slotPostTransfer( KMCommand::Result result )
00253 {
00254 disconnect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00255 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00256 if ( result == OK )
00257 result = execute();
00258 mResult = result;
00259 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00260 KMMessage* msg;
00261 while ( (msg = it.current()) != 0 )
00262 {
00263 ++it;
00264 if (msg->parent())
00265 msg->setTransferInProgress(false);
00266 }
00267 kmkernel->filterMgr()->deref();
00268 if ( !emitsCompletedItself() )
00269 emit completed( this );
00270 if ( !deletesItself() )
00271 deleteLater();
00272 }
00273
00274 void KMCommand::transferSelectedMsgs()
00275 {
00276
00277 if (KMCommand::mCountJobs > 0) {
00278 emit messagesTransfered( Failed );
00279 return;
00280 }
00281
00282 bool complete = true;
00283 KMCommand::mCountJobs = 0;
00284 mCountMsgs = 0;
00285 mRetrievedMsgs.clear();
00286 mCountMsgs = mMsgList.count();
00287 uint totalSize = 0;
00288
00289
00290
00291
00292 if ( mCountMsgs > 0 ) {
00293 mProgressDialog = new KProgressDialog(mParent, "transferProgress",
00294 i18n("Please wait"),
00295 i18n("Please wait while the message is transferred",
00296 "Please wait while the %n messages are transferred", mMsgList.count()),
00297 true);
00298 mProgressDialog->setMinimumDuration(1000);
00299 }
00300 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00301 {
00302
00303 KMMessage *thisMsg = 0;
00304 if ( mb->isMessage() )
00305 thisMsg = static_cast<KMMessage*>(mb);
00306 else
00307 {
00308 KMFolder *folder = mb->parent();
00309 int idx = folder->find(mb);
00310 if (idx < 0) continue;
00311 thisMsg = folder->getMsg(idx);
00312 }
00313 if (!thisMsg) continue;
00314 if ( thisMsg->transferInProgress() &&
00315 thisMsg->parent()->folderType() == KMFolderTypeImap )
00316 {
00317 thisMsg->setTransferInProgress( false, true );
00318 thisMsg->parent()->ignoreJobsForMessage( thisMsg );
00319 }
00320
00321 if ( thisMsg->parent() && !thisMsg->isComplete() &&
00322 ( !mProgressDialog || !mProgressDialog->wasCancelled() ) )
00323 {
00324 kdDebug(5006)<<"### INCOMPLETE\n";
00325
00326 complete = false;
00327 KMCommand::mCountJobs++;
00328 FolderJob *job = thisMsg->parent()->createJob(thisMsg);
00329 job->setCancellable( false );
00330 totalSize += thisMsg->msgSizeServer();
00331
00332 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00333 this, SLOT(slotMsgTransfered(KMMessage*)));
00334
00335 connect(job, SIGNAL(finished()),
00336 this, SLOT(slotJobFinished()));
00337 connect(job, SIGNAL(progress(unsigned long, unsigned long)),
00338 this, SLOT(slotProgress(unsigned long, unsigned long)));
00339
00340 thisMsg->setTransferInProgress(true);
00341 job->start();
00342 } else {
00343 thisMsg->setTransferInProgress(true);
00344 mRetrievedMsgs.append(thisMsg);
00345 }
00346 }
00347
00348 if (complete)
00349 {
00350 delete mProgressDialog;
00351 mProgressDialog = 0;
00352 emit messagesTransfered( OK );
00353 } else {
00354
00355 if ( mProgressDialog ) {
00356 connect(mProgressDialog, SIGNAL(cancelClicked()),
00357 this, SLOT(slotTransferCancelled()));
00358 mProgressDialog->progressBar()->setTotalSteps(totalSize);
00359 }
00360 }
00361 }
00362
00363 void KMCommand::slotMsgTransfered(KMMessage* msg)
00364 {
00365 if ( mProgressDialog && mProgressDialog->wasCancelled() ) {
00366 emit messagesTransfered( Canceled );
00367 return;
00368 }
00369
00370
00371 mRetrievedMsgs.append(msg);
00372 }
00373
00374 void KMCommand::slotProgress( unsigned long done, unsigned long )
00375 {
00376 mProgressDialog->progressBar()->setProgress( done );
00377 }
00378
00379 void KMCommand::slotJobFinished()
00380 {
00381
00382 KMCommand::mCountJobs--;
00383
00384 if ( mProgressDialog && mProgressDialog->wasCancelled() ) return;
00385
00386 if ( (mCountMsgs - static_cast<int>(mRetrievedMsgs.count())) > KMCommand::mCountJobs )
00387 {
00388
00389 if ( mProgressDialog )
00390 mProgressDialog->hide();
00391 slotTransferCancelled();
00392 return;
00393 }
00394
00395 if ( mProgressDialog ) {
00396 mProgressDialog->setLabel(i18n("Please wait while the message is transferred",
00397 "Please wait while the %n messages are transferred", KMCommand::mCountJobs));
00398 }
00399 if (KMCommand::mCountJobs == 0)
00400 {
00401
00402 delete mProgressDialog;
00403 mProgressDialog = 0;
00404 emit messagesTransfered( OK );
00405 }
00406 }
00407
00408 void KMCommand::slotTransferCancelled()
00409 {
00410
00411 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00412 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00413 if (!(*fit))
00414 continue;
00415 KMFolder *folder = *fit;
00416 KMFolderImap *imapFolder = dynamic_cast<KMFolderImap*>(folder);
00417 if (imapFolder && imapFolder->account()) {
00418 imapFolder->account()->killAllJobs();
00419 }
00420 }
00421
00422 KMCommand::mCountJobs = 0;
00423 mCountMsgs = 0;
00424
00425 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00426 KMMessage* msg;
00427 while ( (msg = it.current()) != 0 )
00428 {
00429 KMFolder *folder = msg->parent();
00430 ++it;
00431 if (!folder)
00432 continue;
00433 msg->setTransferInProgress(false);
00434 int idx = folder->find(msg);
00435 if (idx > 0) folder->unGetMsg(idx);
00436 }
00437 mRetrievedMsgs.clear();
00438 emit messagesTransfered( Canceled );
00439 }
00440
00441 void KMCommand::keepFolderOpen( KMFolder *folder )
00442 {
00443 folder->open();
00444 mFolders.append( folder );
00445 }
00446
00447 KMMailtoComposeCommand::KMMailtoComposeCommand( const KURL &url,
00448 KMMessage *msg )
00449 :mUrl( url ), mMessage( msg )
00450 {
00451 }
00452
00453 KMCommand::Result KMMailtoComposeCommand::execute()
00454 {
00455 KMMessage *msg = new KMMessage;
00456 uint id = 0;
00457
00458 if ( mMessage && mMessage->parent() )
00459 id = mMessage->parent()->identity();
00460
00461 msg->initHeader(id);
00462 msg->setCharset("utf-8");
00463 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00464
00465 KMail::Composer * win = KMail::makeComposer( msg, id );
00466 win->setCharset("", TRUE);
00467 win->setFocusToSubject();
00468 win->show();
00469
00470 return OK;
00471 }
00472
00473
00474 KMMailtoReplyCommand::KMMailtoReplyCommand( QWidget *parent,
00475 const KURL &url, KMMessage *msg, const QString &selection )
00476 :KMCommand( parent, msg ), mUrl( url ), mSelection( selection )
00477 {
00478 }
00479
00480 KMCommand::Result KMMailtoReplyCommand::execute()
00481 {
00482
00483 KMMessage *msg = retrievedMessage();
00484 KMMessage *rmsg = msg->createReply( KMail::ReplyNone, mSelection );
00485 rmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00486
00487 KMail::Composer * win = KMail::makeComposer( rmsg, 0 );
00488 win->setCharset(msg->codec()->mimeName(), TRUE);
00489 win->setReplyFocus();
00490 win->show();
00491
00492 return OK;
00493 }
00494
00495
00496 KMMailtoForwardCommand::KMMailtoForwardCommand( QWidget *parent,
00497 const KURL &url, KMMessage *msg )
00498 :KMCommand( parent, msg ), mUrl( url )
00499 {
00500 }
00501
00502 KMCommand::Result KMMailtoForwardCommand::execute()
00503 {
00504
00505 KMMessage *msg = retrievedMessage();
00506 KMMessage *fmsg = msg->createForward();
00507 fmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00508
00509 KMail::Composer * win = KMail::makeComposer( fmsg );
00510 win->setCharset(msg->codec()->mimeName(), TRUE);
00511 win->show();
00512
00513 return OK;
00514 }
00515
00516
00517 KMAddBookmarksCommand::KMAddBookmarksCommand( const KURL &url, QWidget *parent )
00518 : KMCommand( parent ), mUrl( url )
00519 {
00520 }
00521
00522 KMCommand::Result KMAddBookmarksCommand::execute()
00523 {
00524 QString filename = locateLocal( "data", QString::fromLatin1("konqueror/bookmarks.xml") );
00525 KBookmarkManager *bookManager = KBookmarkManager::managerForFile( filename,
00526 false );
00527 KBookmarkGroup group = bookManager->root();
00528 group.addBookmark( bookManager, mUrl.path(), KURL( mUrl ) );
00529 if( bookManager->save() ) {
00530 bookManager->emitChanged( group );
00531 }
00532
00533 return OK;
00534 }
00535
00536 KMMailtoAddAddrBookCommand::KMMailtoAddAddrBookCommand( const KURL &url,
00537 QWidget *parent )
00538 : KMCommand( parent ), mUrl( url )
00539 {
00540 }
00541
00542 KMCommand::Result KMMailtoAddAddrBookCommand::execute()
00543 {
00544 KAddrBookExternal::addEmail( KMMessage::decodeMailtoUrl( mUrl.path() ),
00545 parentWidget() );
00546
00547 return OK;
00548 }
00549
00550
00551 KMMailtoOpenAddrBookCommand::KMMailtoOpenAddrBookCommand( const KURL &url,
00552 QWidget *parent )
00553 : KMCommand( parent ), mUrl( url )
00554 {
00555 }
00556
00557 KMCommand::Result KMMailtoOpenAddrBookCommand::execute()
00558 {
00559 KAddrBookExternal::openEmail( KMMessage::decodeMailtoUrl( mUrl.path() ),
00560 parentWidget() );
00561
00562 return OK;
00563 }
00564
00565
00566 KMUrlCopyCommand::KMUrlCopyCommand( const KURL &url, KMMainWidget *mainWidget )
00567 :mUrl( url ), mMainWidget( mainWidget )
00568 {
00569 }
00570
00571 KMCommand::Result KMUrlCopyCommand::execute()
00572 {
00573 QClipboard* clip = QApplication::clipboard();
00574
00575 if (mUrl.protocol() == "mailto") {
00576
00577 QString address = KMMessage::decodeMailtoUrl( mUrl.path() );
00578 clip->setSelectionMode( true );
00579 clip->setText( address );
00580 clip->setSelectionMode( false );
00581 clip->setText( address );
00582 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ));
00583 } else {
00584
00585 clip->setSelectionMode( true );
00586 clip->setText( mUrl.url() );
00587 clip->setSelectionMode( false );
00588 clip->setText( mUrl.url() );
00589 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "URL copied to clipboard." ));
00590 }
00591
00592 return OK;
00593 }
00594
00595
00596 KMUrlOpenCommand::KMUrlOpenCommand( const KURL &url, KMReaderWin *readerWin )
00597 :mUrl( url ), mReaderWin( readerWin )
00598 {
00599 }
00600
00601 KMCommand::Result KMUrlOpenCommand::execute()
00602 {
00603 if ( !mUrl.isEmpty() )
00604 mReaderWin->slotUrlOpen( mUrl, KParts::URLArgs() );
00605
00606 return OK;
00607 }
00608
00609
00610 KMUrlSaveCommand::KMUrlSaveCommand( const KURL &url, QWidget *parent )
00611 : KMCommand( parent ), mUrl( url )
00612 {
00613 }
00614
00615 KMCommand::Result KMUrlSaveCommand::execute()
00616 {
00617 if ( mUrl.isEmpty() )
00618 return OK;
00619 KURL saveUrl = KFileDialog::getSaveURL(mUrl.fileName(), QString::null,
00620 parentWidget() );
00621 if ( saveUrl.isEmpty() )
00622 return Canceled;
00623 if ( KIO::NetAccess::exists( saveUrl, false, parentWidget() ) )
00624 {
00625 if (KMessageBox::warningContinueCancel(0,
00626 i18n("<qt>File <b>%1</b> exists.<br>Do you want to replace it?</qt>")
00627 .arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00628 != KMessageBox::Continue)
00629 return Canceled;
00630 }
00631 KIO::Job *job = KIO::file_copy(mUrl, saveUrl, -1, true);
00632 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotUrlSaveResult(KIO::Job*)));
00633 setEmitsCompletedItself( true );
00634 return OK;
00635 }
00636
00637 void KMUrlSaveCommand::slotUrlSaveResult( KIO::Job *job )
00638 {
00639 if ( job->error() ) {
00640 job->showErrorDialog();
00641 setResult( Failed );
00642 emit completed( this );
00643 }
00644 else {
00645 setResult( OK );
00646 emit completed( this );
00647 }
00648 }
00649
00650
00651 KMEditMsgCommand::KMEditMsgCommand( QWidget *parent, KMMessage *msg )
00652 :KMCommand( parent, msg )
00653 {
00654 }
00655
00656 KMCommand::Result KMEditMsgCommand::execute()
00657 {
00658 KMMessage *msg = retrievedMessage();
00659 if ( !msg || !msg->parent() ||
00660 ( !kmkernel->folderIsDraftOrOutbox( msg->parent() ) &&
00661 !kmkernel->folderIsTemplates( msg->parent() ) ) )
00662 return Failed;
00663
00664
00665
00666
00667 KMFolder *parent = msg->parent();
00668 if ( parent )
00669 parent->take( parent->find( msg ) );
00670
00671 KMail::Composer * win = KMail::makeComposer();
00672 msg->setTransferInProgress(false);
00673 win->setMsg(msg, FALSE, TRUE);
00674 win->setFolder( parent );
00675 win->show();
00676
00677 return OK;
00678 }
00679
00680 KMUseTemplateCommand::KMUseTemplateCommand( QWidget *parent, KMMessage *msg )
00681 :KMCommand( parent, msg )
00682 {
00683 }
00684
00685 KMCommand::Result KMUseTemplateCommand::execute()
00686 {
00687 KMMessage *msg = retrievedMessage();
00688 if ( !msg || !msg->parent() ||
00689 !kmkernel->folderIsTemplates( msg->parent() ) )
00690 return Failed;
00691
00692
00693 KMMessage *newMsg = new KMMessage( new DwMessage( *msg->asDwMessage() ) );
00694 newMsg->setComplete( msg->isComplete() );
00695
00696 KMail::Composer *win = KMail::makeComposer();
00697 newMsg->setTransferInProgress( false );
00698 win->setMsg( newMsg, FALSE, TRUE );
00699 win->show();
00700
00701 return OK;
00702 }
00703
00704 KMShowMsgSrcCommand::KMShowMsgSrcCommand( QWidget *parent,
00705 KMMessage *msg, bool fixedFont )
00706 :KMCommand( parent, msg ), mFixedFont( fixedFont )
00707 {
00708
00709 mMsgWasComplete = msg->isComplete();
00710 }
00711
00712 KMCommand::Result KMShowMsgSrcCommand::execute()
00713 {
00714 KMMessage *msg = retrievedMessage();
00715 if ( msg->isComplete() && !mMsgWasComplete )
00716 msg->notify();
00717 QString str = msg->codec()->toUnicode( msg->asString() );
00718
00719 MailSourceViewer *viewer = new MailSourceViewer();
00720 viewer->setCaption( i18n("Message as Plain Text") );
00721 viewer->setText(str);
00722 if( mFixedFont )
00723 viewer->setFont(KGlobalSettings::fixedFont());
00724
00725
00726
00727
00728 if (QApplication::desktop()->isVirtualDesktop()) {
00729 int scnum = QApplication::desktop()->screenNumber(QCursor::pos());
00730 viewer->resize(QApplication::desktop()->screenGeometry(scnum).width()/2,
00731 2*QApplication::desktop()->screenGeometry(scnum).height()/3);
00732 } else {
00733 viewer->resize(QApplication::desktop()->geometry().width()/2,
00734 2*QApplication::desktop()->geometry().height()/3);
00735 }
00736 viewer->show();
00737
00738 return OK;
00739 }
00740
00741 static KURL subjectToUrl( const QString & subject ) {
00742 return KFileDialog::getSaveURL( subject.stripWhiteSpace()
00743 .replace( QDir::separator(), '_' ),
00744 QString::null );
00745 }
00746
00747 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent, KMMessage * msg )
00748 : KMCommand( parent ),
00749 mMsgListIndex( 0 ),
00750 mStandAloneMessage( 0 ),
00751 mOffset( 0 ),
00752 mTotalSize( msg ? msg->msgSize() : 0 )
00753 {
00754 if ( !msg ) return;
00755 setDeletesItself( true );
00756
00757
00758
00759
00760 if ( msg->getMsgSerNum() != 0 ) {
00761 mMsgList.append( msg->getMsgSerNum() );
00762 } else {
00763 mStandAloneMessage = msg;
00764 }
00765 mUrl = subjectToUrl( msg->cleanSubject() );
00766 }
00767
00768 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent,
00769 const QPtrList<KMMsgBase> &msgList )
00770 : KMCommand( parent ),
00771 mMsgListIndex( 0 ),
00772 mStandAloneMessage( 0 ),
00773 mOffset( 0 ),
00774 mTotalSize( 0 )
00775 {
00776 if (!msgList.getFirst())
00777 return;
00778 setDeletesItself( true );
00779 KMMsgBase *msgBase = msgList.getFirst();
00780
00781
00782
00783
00784 QPtrListIterator<KMMsgBase> it(msgList);
00785 while ( it.current() ) {
00786 mMsgList.append( (*it)->getMsgSerNum() );
00787 mTotalSize += (*it)->msgSize();
00788 if ((*it)->parent() != 0)
00789 (*it)->parent()->open();
00790 ++it;
00791 }
00792 mMsgListIndex = 0;
00793 mUrl = subjectToUrl( msgBase->cleanSubject() );
00794 }
00795
00796 KURL KMSaveMsgCommand::url()
00797 {
00798 return mUrl;
00799 }
00800
00801 KMCommand::Result KMSaveMsgCommand::execute()
00802 {
00803 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, false, false );
00804 mJob->slotTotalSize( mTotalSize );
00805 mJob->setAsyncDataEnabled( true );
00806 mJob->setReportDataSent( true );
00807 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00808 SLOT(slotSaveDataReq()));
00809 connect(mJob, SIGNAL(result(KIO::Job*)),
00810 SLOT(slotSaveResult(KIO::Job*)));
00811 setEmitsCompletedItself( true );
00812 return OK;
00813 }
00814
00815 void KMSaveMsgCommand::slotSaveDataReq()
00816 {
00817 int remainingBytes = mData.size() - mOffset;
00818 if ( remainingBytes > 0 ) {
00819
00820 if ( remainingBytes > MAX_CHUNK_SIZE )
00821 remainingBytes = MAX_CHUNK_SIZE;
00822
00823 QByteArray data;
00824 data.duplicate( mData.data() + mOffset, remainingBytes );
00825 mJob->sendAsyncData( data );
00826 mOffset += remainingBytes;
00827 return;
00828 }
00829
00830 if ( mMsgListIndex < mMsgList.size() ) {
00831 KMMessage *msg = 0;
00832 int idx = -1;
00833 KMFolder * p = 0;
00834 KMMsgDict::instance()->getLocation( mMsgList[mMsgListIndex], &p, &idx );
00835 assert( p );
00836 assert( idx >= 0 );
00837 msg = p->getMsg(idx);
00838
00839 if ( msg ) {
00840 if ( msg->transferInProgress() ) {
00841 QByteArray data = QByteArray();
00842 mJob->sendAsyncData( data );
00843 }
00844 msg->setTransferInProgress( true );
00845 if (msg->isComplete() ) {
00846 slotMessageRetrievedForSaving( msg );
00847 } else {
00848
00849 if ( msg->parent() && !msg->isComplete() ) {
00850 FolderJob *job = msg->parent()->createJob( msg );
00851 job->setCancellable( false );
00852 connect(job, SIGNAL( messageRetrieved( KMMessage* ) ),
00853 this, SLOT( slotMessageRetrievedForSaving( KMMessage* ) ) );
00854 job->start();
00855 }
00856 }
00857 } else {
00858 mJob->slotError( KIO::ERR_ABORTED,
00859 i18n("The message was removed while saving it. "
00860 "It has not been saved.") );
00861 }
00862 } else {
00863 if ( mStandAloneMessage ) {
00864
00865 slotMessageRetrievedForSaving( mStandAloneMessage );
00866 mStandAloneMessage = 0;
00867 } else {
00868
00869 QByteArray data = QByteArray();
00870 mJob->sendAsyncData( data );
00871 }
00872 }
00873 }
00874
00875 void KMSaveMsgCommand::slotMessageRetrievedForSaving(KMMessage *msg)
00876 {
00877 if ( msg ) {
00878 mData = KMFolderMbox::escapeFrom( msg->asDwString() );
00879 KMail::Util::insert( mData, 0, msg->mboxMessageSeparator() );
00880 KMail::Util::append( mData, "\n" );
00881 msg->setTransferInProgress(false);
00882
00883 mOffset = 0;
00884 QByteArray data;
00885 int size;
00886
00887 if( mData.size() > (unsigned int) MAX_CHUNK_SIZE )
00888 size = MAX_CHUNK_SIZE;
00889 else
00890 size = mData.size();
00891
00892 data.duplicate( mData, size );
00893 mJob->sendAsyncData( data );
00894 mOffset += size;
00895 }
00896 ++mMsgListIndex;
00897
00898 if ( msg && msg->parent() && msg->getMsgSerNum() ) {
00899 int idx = -1;
00900 KMFolder * p = 0;
00901 KMMsgDict::instance()->getLocation( msg, &p, &idx );
00902 assert( p == msg->parent() ); assert( idx >= 0 );
00903 p->unGetMsg( idx );
00904 p->close();
00905 }
00906 }
00907
00908 void KMSaveMsgCommand::slotSaveResult(KIO::Job *job)
00909 {
00910 if (job->error())
00911 {
00912 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST)
00913 {
00914 if (KMessageBox::warningContinueCancel(0,
00915 i18n("File %1 exists.\nDo you want to replace it?")
00916 .arg(mUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00917 == KMessageBox::Continue) {
00918 mOffset = 0;
00919
00920 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, true, false );
00921 mJob->slotTotalSize( mTotalSize );
00922 mJob->setAsyncDataEnabled( true );
00923 mJob->setReportDataSent( true );
00924 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00925 SLOT(slotSaveDataReq()));
00926 connect(mJob, SIGNAL(result(KIO::Job*)),
00927 SLOT(slotSaveResult(KIO::Job*)));
00928 }
00929 }
00930 else
00931 {
00932 job->showErrorDialog();
00933 setResult( Failed );
00934 emit completed( this );
00935 deleteLater();
00936 }
00937 } else {
00938 setResult( OK );
00939 emit completed( this );
00940 deleteLater();
00941 }
00942 }
00943
00944
00945
00946 KMOpenMsgCommand::KMOpenMsgCommand( QWidget *parent, const KURL & url,
00947 const QString & encoding )
00948 : KMCommand( parent ),
00949 mUrl( url ),
00950 mEncoding( encoding )
00951 {
00952 setDeletesItself( true );
00953 }
00954
00955 KMCommand::Result KMOpenMsgCommand::execute()
00956 {
00957 if ( mUrl.isEmpty() ) {
00958 mUrl = KFileDialog::getOpenURL( ":OpenMessage", "message/rfc822",
00959 parentWidget(), i18n("Open Message") );
00960 }
00961 if ( mUrl.isEmpty() ) {
00962 setDeletesItself( false );
00963 return Canceled;
00964 }
00965 mJob = KIO::get( mUrl, false, false );
00966 mJob->setReportDataSent( true );
00967 connect( mJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
00968 this, SLOT( slotDataArrived( KIO::Job*, const QByteArray & ) ) );
00969 connect( mJob, SIGNAL( result( KIO::Job * ) ),
00970 SLOT( slotResult( KIO::Job * ) ) );
00971 setEmitsCompletedItself( true );
00972 return OK;
00973 }
00974
00975 void KMOpenMsgCommand::slotDataArrived( KIO::Job *, const QByteArray & data )
00976 {
00977 if ( data.isEmpty() )
00978 return;
00979
00980 mMsgString.append( data.data(), data.size() );
00981 }
00982
00983 void KMOpenMsgCommand::slotResult( KIO::Job *job )
00984 {
00985 if ( job->error() ) {
00986
00987 job->showErrorDialog();
00988 setResult( Failed );
00989 emit completed( this );
00990 }
00991 else {
00992 int startOfMessage = 0;
00993 if ( mMsgString.compare( 0, 5, "From ", 5 ) == 0 ) {
00994 startOfMessage = mMsgString.find( '\n' );
00995 if ( startOfMessage == -1 ) {
00996 KMessageBox::sorry( parentWidget(),
00997 i18n( "The file does not contain a message." ) );
00998 setResult( Failed );
00999 emit completed( this );
01000
01001
01002
01003 SecondaryWindow *win = new SecondaryWindow();
01004 win->close();
01005 win->deleteLater();
01006 deleteLater();
01007 return;
01008 }
01009 startOfMessage += 1;
01010 }
01011
01012 bool multipleMessages = true;
01013 int endOfMessage = mMsgString.find( "\nFrom " );
01014 if ( endOfMessage == -1 ) {
01015 endOfMessage = mMsgString.length();
01016 multipleMessages = false;
01017 }
01018 DwMessage *dwMsg = new DwMessage;
01019 dwMsg->FromString( mMsgString.substr( startOfMessage,
01020 endOfMessage - startOfMessage ) );
01021 dwMsg->Parse();
01022
01023 if ( dwMsg->Headers().NumFields() == 0 ) {
01024 KMessageBox::sorry( parentWidget(),
01025 i18n( "The file does not contain a message." ) );
01026 delete dwMsg; dwMsg = 0;
01027 setResult( Failed );
01028 emit completed( this );
01029
01030 SecondaryWindow *win = new SecondaryWindow();
01031 win->close();
01032 win->deleteLater();
01033 deleteLater();
01034 return;
01035 }
01036 KMMessage *msg = new KMMessage( dwMsg );
01037 msg->setReadyToShow( true );
01038 KMReaderMainWin *win = new KMReaderMainWin();
01039 win->showMsg( mEncoding, msg );
01040 win->show();
01041 if ( multipleMessages )
01042 KMessageBox::information( win,
01043 i18n( "The file contains multiple messages. "
01044 "Only the first message is shown." ) );
01045 setResult( OK );
01046 emit completed( this );
01047 }
01048 deleteLater();
01049 }
01050
01051
01052
01053
01054
01055 KMReplyToCommand::KMReplyToCommand( QWidget *parent, KMMessage *msg,
01056 const QString &selection )
01057 : KMCommand( parent, msg ), mSelection( selection )
01058 {
01059 }
01060
01061 KMCommand::Result KMReplyToCommand::execute()
01062 {
01063 KCursorSaver busy(KBusyPtr::busy());
01064 KMMessage *msg = retrievedMessage();
01065 KMMessage *reply = msg->createReply( KMail::ReplySmart, mSelection );
01066 KMail::Composer * win = KMail::makeComposer( reply );
01067 win->setCharset( msg->codec()->mimeName(), TRUE );
01068 win->setReplyFocus();
01069 win->show();
01070
01071 return OK;
01072 }
01073
01074
01075 KMNoQuoteReplyToCommand::KMNoQuoteReplyToCommand( QWidget *parent,
01076 KMMessage *msg )
01077 : KMCommand( parent, msg )
01078 {
01079 }
01080
01081 KMCommand::Result KMNoQuoteReplyToCommand::execute()
01082 {
01083 KCursorSaver busy(KBusyPtr::busy());
01084 KMMessage *msg = retrievedMessage();
01085 KMMessage *reply = msg->createReply( KMail::ReplySmart, "", TRUE);
01086 KMail::Composer * win = KMail::makeComposer( reply );
01087 win->setCharset(msg->codec()->mimeName(), TRUE);
01088 win->setReplyFocus(false);
01089 win->show();
01090
01091 return OK;
01092 }
01093
01094
01095 KMReplyListCommand::KMReplyListCommand( QWidget *parent,
01096 KMMessage *msg, const QString &selection )
01097 : KMCommand( parent, msg ), mSelection( selection )
01098 {
01099 }
01100
01101 KMCommand::Result KMReplyListCommand::execute()
01102 {
01103 KCursorSaver busy(KBusyPtr::busy());
01104 KMMessage *msg = retrievedMessage();
01105 KMMessage *reply = msg->createReply( KMail::ReplyList, mSelection);
01106 KMail::Composer * win = KMail::makeComposer( reply );
01107 win->setCharset(msg->codec()->mimeName(), TRUE);
01108 win->setReplyFocus(false);
01109 win->show();
01110
01111 return OK;
01112 }
01113
01114
01115 KMReplyToAllCommand::KMReplyToAllCommand( QWidget *parent,
01116 KMMessage *msg, const QString &selection )
01117 :KMCommand( parent, msg ), mSelection( selection )
01118 {
01119 }
01120
01121 KMCommand::Result KMReplyToAllCommand::execute()
01122 {
01123 KCursorSaver busy(KBusyPtr::busy());
01124 KMMessage *msg = retrievedMessage();
01125 KMMessage *reply = msg->createReply( KMail::ReplyAll, mSelection );
01126 KMail::Composer * win = KMail::makeComposer( reply );
01127 win->setCharset( msg->codec()->mimeName(), TRUE );
01128 win->setReplyFocus();
01129 win->show();
01130
01131 return OK;
01132 }
01133
01134
01135 KMReplyAuthorCommand::KMReplyAuthorCommand( QWidget *parent, KMMessage *msg,
01136 const QString &selection )
01137 : KMCommand( parent, msg ), mSelection( selection )
01138 {
01139 }
01140
01141 KMCommand::Result KMReplyAuthorCommand::execute()
01142 {
01143 KCursorSaver busy(KBusyPtr::busy());
01144 KMMessage *msg = retrievedMessage();
01145 KMMessage *reply = msg->createReply( KMail::ReplyAuthor, mSelection );
01146 KMail::Composer * win = KMail::makeComposer( reply );
01147 win->setCharset( msg->codec()->mimeName(), TRUE );
01148 win->setReplyFocus();
01149 win->show();
01150
01151 return OK;
01152 }
01153
01154
01155 KMForwardInlineCommand::KMForwardInlineCommand( QWidget *parent,
01156 const QPtrList<KMMsgBase> &msgList, uint identity )
01157 : KMCommand( parent, msgList ),
01158 mIdentity( identity )
01159 {
01160 }
01161
01162 KMForwardInlineCommand::KMForwardInlineCommand( QWidget *parent,
01163 KMMessage *msg, uint identity )
01164 : KMCommand( parent, msg ),
01165 mIdentity( identity )
01166 {
01167 }
01168
01169 KMCommand::Result KMForwardInlineCommand::execute()
01170 {
01171 QPtrList<KMMessage> msgList = retrievedMsgs();
01172
01173 if (msgList.count() >= 2) {
01174
01175 uint id = 0;
01176 QPtrList<KMMessage> linklist;
01177 for ( KMMessage *msg = msgList.first(); msg; msg = msgList.next() ) {
01178
01179 if (id == 0)
01180 id = msg->headerField( "X-KMail-Identity" ).stripWhiteSpace().toUInt();
01181
01182
01183 linklist.append( msg );
01184 }
01185 if ( id == 0 )
01186 id = mIdentity;
01187 KMMessage *fwdMsg = new KMMessage;
01188 fwdMsg->initHeader( id );
01189 fwdMsg->setAutomaticFields( true );
01190 fwdMsg->setCharset( "utf-8" );
01191
01192
01193 for ( KMMessage *msg = linklist.first(); msg; msg = linklist.next() ) {
01194 TemplateParser parser( fwdMsg, TemplateParser::Forward,
01195 msg->body(), false, false, false, false);
01196 parser.process( msg, 0, true );
01197
01198 fwdMsg->link( msg, KMMsgStatusForwarded );
01199 }
01200
01201 KCursorSaver busy( KBusyPtr::busy() );
01202 KMail::Composer * win = KMail::makeComposer( fwdMsg, id );
01203 win->setCharset("");
01204 win->show();
01205
01206 } else {
01207
01208 KMMessage *msg = msgList.getFirst();
01209 if ( !msg || !msg->codec() )
01210 return Failed;
01211
01212 KCursorSaver busy( KBusyPtr::busy() );
01213 KMMessage *fwdMsg = msg->createForward();
01214
01215 uint id = msg->headerField( "X-KMail-Identity" ).stripWhiteSpace().toUInt();
01216 if ( id == 0 )
01217 id = mIdentity;
01218 {
01219 KMail::Composer * win = KMail::makeComposer( fwdMsg, id );
01220 win->setCharset( fwdMsg->codec()->mimeName(), true );
01221
01222 win->show();
01223 }
01224 }
01225 return OK;
01226 }
01227
01228
01229 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
01230 const QPtrList<KMMsgBase> &msgList, uint identity, KMail::Composer *win )
01231 : KMCommand( parent, msgList ), mIdentity( identity ),
01232 mWin( QGuardedPtr<KMail::Composer>( win ))
01233 {
01234 }
01235
01236 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
01237 KMMessage * msg, uint identity, KMail::Composer *win )
01238 : KMCommand( parent, msg ), mIdentity( identity ),
01239 mWin( QGuardedPtr< KMail::Composer >( win ))
01240 {
01241 }
01242
01243 KMCommand::Result KMForwardAttachedCommand::execute()
01244 {
01245 QPtrList<KMMessage> msgList = retrievedMsgs();
01246 KMMessage *fwdMsg = new KMMessage;
01247
01248 if (msgList.count() >= 2) {
01249
01250
01251 fwdMsg->initHeader(mIdentity);
01252 }
01253 else if (msgList.count() == 1) {
01254 KMMessage *msg = msgList.getFirst();
01255 fwdMsg->initFromMessage(msg);
01256 fwdMsg->setSubject( msg->forwardSubject() );
01257 }
01258
01259 fwdMsg->setAutomaticFields(true);
01260
01261 KCursorSaver busy(KBusyPtr::busy());
01262 if (!mWin)
01263 mWin = KMail::makeComposer(fwdMsg, mIdentity);
01264
01265
01266 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01267
01268 msg->removePrivateHeaderFields();
01269 msg->removeHeaderField("BCC");
01270
01271 KMMessagePart *msgPart = new KMMessagePart;
01272 msgPart->setTypeStr("message");
01273 msgPart->setSubtypeStr("rfc822");
01274 msgPart->setCharset(msg->charset());
01275 msgPart->setName("forwarded message");
01276 msgPart->setContentDescription(msg->from()+": "+msg->subject());
01277 msgPart->setContentDisposition( "inline" );
01278
01279 QValueList<int> dummy;
01280 msgPart->setBodyAndGuessCte(msg->asString(), dummy, true);
01281 msgPart->setCharset("");
01282
01283 fwdMsg->link(msg, KMMsgStatusForwarded);
01284 mWin->addAttach(msgPart);
01285 }
01286
01287 mWin->show();
01288
01289 return OK;
01290 }
01291
01292
01293 KMForwardDigestCommand::KMForwardDigestCommand( QWidget *parent,
01294 const QPtrList<KMMsgBase> &msgList, uint identity, KMail::Composer *win )
01295 : KMCommand( parent, msgList ), mIdentity( identity ),
01296 mWin( QGuardedPtr<KMail::Composer>( win ))
01297 {
01298 }
01299
01300 KMForwardDigestCommand::KMForwardDigestCommand( QWidget *parent,
01301 KMMessage * msg, uint identity, KMail::Composer *win )
01302 : KMCommand( parent, msg ), mIdentity( identity ),
01303 mWin( QGuardedPtr< KMail::Composer >( win ))
01304 {
01305 }
01306
01307 KMCommand::Result KMForwardDigestCommand::execute()
01308 {
01309 QPtrList<KMMessage> msgList = retrievedMsgs();
01310
01311 if ( msgList.count() < 2 )
01312 return Undefined;
01313
01314 uint id = 0;
01315 KMMessage *fwdMsg = new KMMessage;
01316 KMMessagePart *msgPart = new KMMessagePart;
01317 QString msgPartText;
01318 int msgCnt = 0;
01319
01320
01321
01322 fwdMsg->initHeader( id );
01323 fwdMsg->setAutomaticFields( true );
01324 fwdMsg->mMsg->Headers().ContentType().CreateBoundary( 1 );
01325 QCString boundary( fwdMsg->mMsg->Headers().ContentType().Boundary().c_str() );
01326 msgPartText = i18n("\nThis is a MIME digest forward. The content of the"
01327 " message is contained in the attachment(s).\n\n\n");
01328
01329 for ( KMMessage *msg = msgList.first(); msg; msg = msgList.next() ) {
01330
01331 if ( id == 0 )
01332 id = msg->headerField( "X-KMail-Identity" ).stripWhiteSpace().toUInt();
01333
01334 msgPartText += "--";
01335 msgPartText += QString::fromLatin1( boundary );
01336 msgPartText += "\nContent-Type: MESSAGE/RFC822";
01337 msgPartText += QString( "; CHARSET=%1" ).arg( msg->charset() );
01338 msgPartText += '\n';
01339 DwHeaders dwh;
01340 dwh.MessageId().CreateDefault();
01341 msgPartText += QString( "Content-ID: %1\n" ).arg( dwh.MessageId().AsString().c_str() );
01342 msgPartText += QString( "Content-Description: %1" ).arg( msg->subject() );
01343 if ( !msg->subject().contains( "(fwd)" ) )
01344 msgPartText += " (fwd)";
01345 msgPartText += "\n\n";
01346
01347 msg->removePrivateHeaderFields();
01348 msg->removeHeaderField( "BCC" );
01349
01350 msgPartText += msg->headerAsString();
01351 msgPartText += '\n';
01352 msgPartText += msg->body();
01353 msgPartText += '\n';
01354 msgCnt++;
01355 fwdMsg->link( msg, KMMsgStatusForwarded );
01356 }
01357
01358 if ( id == 0 )
01359 id = mIdentity;
01360 fwdMsg->initHeader( id );
01361 msgPartText += "--";
01362 msgPartText += QString::fromLatin1( boundary );
01363 msgPartText += "--\n";
01364 QCString tmp;
01365 msgPart->setTypeStr( "MULTIPART" );
01366 tmp.sprintf( "Digest; boundary=\"%s\"", boundary.data() );
01367 msgPart->setSubtypeStr( tmp );
01368 msgPart->setName( "unnamed" );
01369 msgPart->setCte( DwMime::kCte7bit );
01370 msgPart->setContentDescription( QString( "Digest of %1 messages." ).arg( msgCnt ) );
01371
01372 msgPart->setBodyEncoded( QCString( msgPartText.ascii() ) );
01373 KCursorSaver busy( KBusyPtr::busy() );
01374 KMail::Composer * win = KMail::makeComposer( fwdMsg, id );
01375 win->addAttach( msgPart );
01376 win->show();
01377 return OK;
01378 }
01379
01380 KMRedirectCommand::KMRedirectCommand( QWidget *parent,
01381 KMMessage *msg )
01382 : KMCommand( parent, msg )
01383 {
01384 }
01385
01386 KMCommand::Result KMRedirectCommand::execute()
01387 {
01388 KMMessage *msg = retrievedMessage();
01389 if ( !msg || !msg->codec() )
01390 return Failed;
01391
01392 RedirectDialog dlg( parentWidget(), "redirect", true,
01393 kmkernel->msgSender()->sendImmediate() );
01394 if (dlg.exec()==QDialog::Rejected) return Failed;
01395
01396 KMMessage *newMsg = msg->createRedirect( dlg.to() );
01397 KMFilterAction::sendMDN( msg, KMime::MDN::Dispatched );
01398
01399 const KMail::MessageSender::SendMethod method = dlg.sendImmediate()
01400 ? KMail::MessageSender::SendImmediate
01401 : KMail::MessageSender::SendLater;
01402 if ( !kmkernel->msgSender()->send( newMsg, method ) ) {
01403 kdDebug(5006) << "KMRedirectCommand: could not redirect message (sending failed)" << endl;
01404 return Failed;
01405 }
01406 return OK;
01407 }
01408
01409
01410 KMCustomReplyToCommand::KMCustomReplyToCommand( QWidget *parent, KMMessage *msg,
01411 const QString &selection,
01412 const QString &tmpl )
01413 : KMCommand( parent, msg ), mSelection( selection ), mTemplate( tmpl )
01414 {
01415 }
01416
01417 KMCommand::Result KMCustomReplyToCommand::execute()
01418 {
01419 KCursorSaver busy(KBusyPtr::busy());
01420 KMMessage *msg = retrievedMessage();
01421 KMMessage *reply = msg->createReply( KMail::ReplySmart, mSelection,
01422 false, true, false, mTemplate );
01423 KMail::Composer * win = KMail::makeComposer( reply );
01424 win->setCharset( msg->codec()->mimeName(), TRUE );
01425 win->setReplyFocus();
01426 win->show();
01427
01428 return OK;
01429 }
01430
01431
01432 KMCustomReplyAllToCommand::KMCustomReplyAllToCommand( QWidget *parent, KMMessage *msg,
01433 const QString &selection,
01434 const QString &tmpl )
01435 : KMCommand( parent, msg ), mSelection( selection ), mTemplate( tmpl )
01436 {
01437 }
01438
01439 KMCommand::Result KMCustomReplyAllToCommand::execute()
01440 {
01441 KCursorSaver busy(KBusyPtr::busy());
01442 KMMessage *msg = retrievedMessage();
01443 KMMessage *reply = msg->createReply( KMail::ReplyAll, mSelection,
01444 false, true, false, mTemplate );
01445 KMail::Composer * win = KMail::makeComposer( reply );
01446 win->setCharset( msg->codec()->mimeName(), TRUE );
01447 win->setReplyFocus();
01448 win->show();
01449
01450 return OK;
01451 }
01452
01453
01454 KMCustomForwardCommand::KMCustomForwardCommand( QWidget *parent,
01455 const QPtrList<KMMsgBase> &msgList, uint identity, const QString &tmpl )
01456 : KMCommand( parent, msgList ),
01457 mIdentity( identity ), mTemplate( tmpl )
01458 {
01459 }
01460
01461 KMCustomForwardCommand::KMCustomForwardCommand( QWidget *parent,
01462 KMMessage *msg, uint identity, const QString &tmpl )
01463 : KMCommand( parent, msg ),
01464 mIdentity( identity ), mTemplate( tmpl )
01465 {
01466 }
01467
01468 KMCommand::Result KMCustomForwardCommand::execute()
01469 {
01470 QPtrList<KMMessage> msgList = retrievedMsgs();
01471
01472 if (msgList.count() >= 2) {
01473
01474 uint id = 0;
01475 QPtrList<KMMessage> linklist;
01476 for ( KMMessage *msg = msgList.first(); msg; msg = msgList.next() ) {
01477
01478 if (id == 0)
01479 id = msg->headerField( "X-KMail-Identity" ).stripWhiteSpace().toUInt();
01480
01481
01482 linklist.append( msg );
01483 }
01484 if ( id == 0 )
01485 id = mIdentity;
01486 KMMessage *fwdMsg = new KMMessage;
01487 fwdMsg->initHeader( id );
01488 fwdMsg->setAutomaticFields( true );
01489 fwdMsg->setCharset( "utf-8" );
01490
01491
01492 for ( KMMessage *msg = linklist.first(); msg; msg = linklist.next() ) {
01493 TemplateParser parser( fwdMsg, TemplateParser::Forward,
01494 msg->body(), false, false, false, false);
01495 parser.process( msg, 0, true );
01496
01497 fwdMsg->link( msg, KMMsgStatusForwarded );
01498 }
01499
01500 KCursorSaver busy( KBusyPtr::busy() );
01501 KMail::Composer * win = KMail::makeComposer( fwdMsg, id );
01502 win->setCharset("");
01503 win->show();
01504
01505 } else {
01506
01507 KMMessage *msg = msgList.getFirst();
01508 if ( !msg || !msg->codec() )
01509 return Failed;
01510
01511 KCursorSaver busy( KBusyPtr::busy() );
01512 KMMessage *fwdMsg = msg->createForward( mTemplate );
01513
01514 uint id = msg->headerField( "X-KMail-Identity" ).stripWhiteSpace().toUInt();
01515 if ( id == 0 )
01516 id = mIdentity;
01517 {
01518 KMail::Composer * win = KMail::makeComposer( fwdMsg, id );
01519 win->setCharset( fwdMsg->codec()->mimeName(), true );
01520 win->show();
01521 }
01522 }
01523 return OK;
01524 }
01525
01526
01527 KMPrintCommand::KMPrintCommand( QWidget *parent,
01528 KMMessage *msg, bool htmlOverride, bool htmlLoadExtOverride,
01529 bool useFixedFont, const QString & encoding )
01530 : KMCommand( parent, msg ), mHtmlOverride( htmlOverride ),
01531 mHtmlLoadExtOverride( htmlLoadExtOverride ),
01532 mUseFixedFont( useFixedFont ), mEncoding( encoding )
01533 {
01534 }
01535
01536 KMCommand::Result KMPrintCommand::execute()
01537 {
01538 KMReaderWin printWin( 0, 0, 0 );
01539 printWin.setPrinting( true );
01540 printWin.readConfig();
01541 printWin.setHtmlOverride( mHtmlOverride );
01542 printWin.setHtmlLoadExtOverride( mHtmlLoadExtOverride );
01543 printWin.setUseFixedFont( mUseFixedFont );
01544 printWin.setOverrideEncoding( mEncoding );
01545 printWin.setMsg( retrievedMessage(), true );
01546 printWin.printMsg();
01547
01548 return OK;
01549 }
01550
01551
01552 KMSetStatusCommand::KMSetStatusCommand( KMMsgStatus status,
01553 const QValueList<Q_UINT32> &serNums, bool toggle )
01554 : mStatus( status ), mSerNums( serNums ), mToggle( toggle )
01555 {
01556 }
01557
01558 KMCommand::Result KMSetStatusCommand::execute()
01559 {
01560 QValueListIterator<Q_UINT32> it;
01561 int idx = -1;
01562 KMFolder *folder = 0;
01563 bool parentStatus = false;
01564
01565
01566
01567 if (mToggle) {
01568 KMMsgBase *msg;
01569 KMMsgDict::instance()->getLocation( *mSerNums.begin(), &folder, &idx );
01570 if (folder) {
01571 msg = folder->getMsgBase(idx);
01572 if (msg && (msg->status()&mStatus))
01573 parentStatus = true;
01574 else
01575 parentStatus = false;
01576 }
01577 }
01578 QMap< KMFolder*, QValueList<int> > folderMap;
01579 for ( it = mSerNums.begin(); it != mSerNums.end(); ++it ) {
01580 KMMsgDict::instance()->getLocation( *it, &folder, &idx );
01581 if (folder) {
01582 if (mToggle) {
01583 KMMsgBase *msg = folder->getMsgBase(idx);
01584
01585 if (msg) {
01586 bool myStatus;
01587 if (msg->status()&mStatus)
01588 myStatus = true;
01589 else
01590 myStatus = false;
01591 if (myStatus != parentStatus)
01592 continue;
01593 }
01594 }
01595
01596
01597 folderMap[folder].append(idx);
01598 }
01599 }
01600 QMapIterator< KMFolder*, QValueList<int> > it2 = folderMap.begin();
01601 while ( it2 != folderMap.end() ) {
01602 KMFolder *f = it2.key();
01603 f->setStatus( (*it2), mStatus, mToggle );
01604 ++it2;
01605 }
01606
01607
01608 return OK;
01609 }
01610
01611
01612 KMFilterCommand::KMFilterCommand( const QCString &field, const QString &value )
01613 : mField( field ), mValue( value )
01614 {
01615 }
01616
01617 KMCommand::Result KMFilterCommand::execute()
01618 {
01619 kmkernel->filterMgr()->createFilter( mField, mValue );
01620
01621 return OK;
01622 }
01623
01624
01625 KMFilterActionCommand::KMFilterActionCommand( QWidget *parent,
01626 const QPtrList<KMMsgBase> &msgList,
01627 KMFilter *filter )
01628 : KMCommand( parent, msgList ), mFilter( filter )
01629 {
01630 QPtrListIterator<KMMsgBase> it(msgList);
01631 while ( it.current() ) {
01632 serNumList.append( (*it)->getMsgSerNum() );
01633 ++it;
01634 }
01635 }
01636
01637 KMCommand::Result KMFilterActionCommand::execute()
01638 {
01639 KCursorSaver busy( KBusyPtr::busy() );
01640
01641 int msgCount = 0;
01642 int msgCountToFilter = serNumList.count();
01643 ProgressItem* progressItem =
01644 ProgressManager::createProgressItem ( "filter"+ProgressManager::getUniqueID(),
01645 i18n( "Filtering messages" ) );
01646 progressItem->setTotalItems( msgCountToFilter );
01647 QValueList<Q_UINT32>::const_iterator it;
01648 for ( it = serNumList.begin(); it != serNumList.end(); it++ ) {
01649 Q_UINT32 serNum = *it;
01650 int diff = msgCountToFilter - ++msgCount;
01651 if ( diff < 10 || !( msgCount % 20 ) || msgCount <= 10 ) {
01652 progressItem->updateProgress();
01653 QString statusMsg = i18n("Filtering message %1 of %2");
01654 statusMsg = statusMsg.arg( msgCount ).arg( msgCountToFilter );
01655 KPIM::BroadcastStatus::instance()->setStatusMsg( statusMsg );
01656 KApplication::kApplication()->eventLoop()->processEvents( QEventLoop::ExcludeUserInput, 50 );
01657 }
01658
01659 int filterResult = kmkernel->filterMgr()->process( serNum, mFilter );
01660 if (filterResult == 2) {
01661
01662 perror("Critical error");
01663 kmkernel->emergencyExit( i18n("Not enough free disk space?" ));
01664 }
01665 progressItem->incCompletedItems();
01666 }
01667
01668 progressItem->setComplete();
01669 progressItem = 0;
01670 return OK;
01671 }
01672
01673
01674 KMMetaFilterActionCommand::KMMetaFilterActionCommand( KMFilter *filter,
01675 KMHeaders *headers,
01676 KMMainWidget *main )
01677 : QObject( main ),
01678 mFilter( filter ), mHeaders( headers ), mMainWidget( main )
01679 {
01680 }
01681
01682 void KMMetaFilterActionCommand::start()
01683 {
01684 if (ActionScheduler::isEnabled() ) {
01685
01686 KMFilterMgr::FilterSet set = KMFilterMgr::All;
01687 QValueList<KMFilter*> filters;
01688 filters.append( mFilter );
01689 ActionScheduler *scheduler = new ActionScheduler( set, filters, mHeaders );
01690 scheduler->setAlwaysMatch( true );
01691 scheduler->setAutoDestruct( true );
01692
01693 int contentX, contentY;
01694 HeaderItem *nextItem = mHeaders->prepareMove( &contentX, &contentY );
01695 QPtrList<KMMsgBase> msgList = *mHeaders->selectedMsgs(true);
01696 mHeaders->finalizeMove( nextItem, contentX, contentY );
01697
01698 for (KMMsgBase *msg = msgList.first(); msg; msg = msgList.next())
01699 scheduler->execFilters( msg );
01700 } else {
01701 KMCommand *filterCommand =
01702 new KMFilterActionCommand( mMainWidget,
01703 *mHeaders->selectedMsgs(), mFilter );
01704 filterCommand->start();
01705 int contentX, contentY;
01706 HeaderItem *item = mHeaders->prepareMove( &contentX, &contentY );
01707 mHeaders->finalizeMove( item, contentX, contentY );
01708 }
01709 }
01710
01711 FolderShortcutCommand::FolderShortcutCommand( KMMainWidget *mainwidget,
01712 KMFolder *folder )
01713 : mMainWidget( mainwidget ), mFolder( folder ), mAction( 0 )
01714 {
01715 }
01716
01717
01718 FolderShortcutCommand::~FolderShortcutCommand()
01719 {
01720 if ( mAction ) mAction->unplugAll();
01721 delete mAction;
01722 }
01723
01724 void FolderShortcutCommand::start()
01725 {
01726 mMainWidget->slotSelectFolder( mFolder );
01727 }
01728
01729 void FolderShortcutCommand::setAction( KAction* action )
01730 {
01731 mAction = action;
01732 }
01733
01734 KMMailingListFilterCommand::KMMailingListFilterCommand( QWidget *parent,
01735 KMMessage *msg )
01736 : KMCommand( parent, msg )
01737 {
01738 }
01739
01740 KMCommand::Result KMMailingListFilterCommand::execute()
01741 {
01742 QCString name;
01743 QString value;
01744 KMMessage *msg = retrievedMessage();
01745 if (!msg)
01746 return Failed;
01747
01748 if ( !MailingList::name( msg, name, value ).isEmpty() ) {
01749 kmkernel->filterMgr()->createFilter( name, value );
01750 return OK;
01751 }
01752 else
01753 return Failed;
01754 }
01755
01756
01757 void KMMenuCommand::folderToPopupMenu(bool move,
01758 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01759 {
01760 while ( menu->count() )
01761 {
01762 QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
01763 if (popup)
01764 delete popup;
01765 else
01766 menu->removeItemAt( 0 );
01767 }
01768
01769 if (!kmkernel->imapFolderMgr()->dir().first() &&
01770 !kmkernel->dimapFolderMgr()->dir().first())
01771 {
01772 makeFolderMenu( &kmkernel->folderMgr()->dir(), move,
01773 receiver, aMenuToFolder, menu );
01774 } else {
01775
01776 QPopupMenu* subMenu = new QPopupMenu(menu);
01777 makeFolderMenu( &kmkernel->folderMgr()->dir(),
01778 move, receiver, aMenuToFolder, subMenu );
01779 menu->insertItem( i18n( "Local Folders" ), subMenu );
01780 KMFolderDir* fdir = &kmkernel->imapFolderMgr()->dir();
01781 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01782 if (node->isDir())
01783 continue;
01784 subMenu = new QPopupMenu(menu);
01785 makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01786 menu->insertItem( node->label(), subMenu );
01787 }
01788 fdir = &kmkernel->dimapFolderMgr()->dir();
01789 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01790 if (node->isDir())
01791 continue;
01792 subMenu = new QPopupMenu(menu);
01793 makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01794 menu->insertItem( node->label(), subMenu );
01795 }
01796 }
01797 }
01798
01799 void KMMenuCommand::makeFolderMenu(KMFolderNode* node, bool move,
01800 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01801 {
01802
01803 if (move)
01804 {
01805 disconnect(menu, SIGNAL(activated(int)), receiver,
01806 SLOT(moveSelectedToFolder(int)));
01807 connect(menu, SIGNAL(activated(int)), receiver,
01808 SLOT(moveSelectedToFolder(int)));
01809 } else {
01810 disconnect(menu, SIGNAL(activated(int)), receiver,
01811 SLOT(copySelectedToFolder(int)));
01812 connect(menu, SIGNAL(activated(int)), receiver,
01813 SLOT(copySelectedToFolder(int)));
01814 }
01815
01816 KMFolder *folder = 0;
01817 KMFolderDir *folderDir = 0;
01818 if (node->isDir()) {
01819 folderDir = static_cast<KMFolderDir*>(node);
01820 } else {
01821 folder = static_cast<KMFolder*>(node);
01822 folderDir = folder->child();
01823 }
01824
01825 if (folder && !folder->noContent())
01826 {
01827 int menuId;
01828 if (move)
01829 menuId = menu->insertItem(i18n("Move to This Folder"));
01830 else
01831 menuId = menu->insertItem(i18n("Copy to This Folder"));
01832 aMenuToFolder->insert( menuId, folder );
01833 menu->setItemEnabled( menuId, !folder->isReadOnly() );
01834 menu->insertSeparator();
01835 }
01836
01837 if (!folderDir)
01838 return;
01839
01840 for (KMFolderNode *it = folderDir->first(); it; it = folderDir->next() ) {
01841 if (it->isDir())
01842 continue;
01843 KMFolder *child = static_cast<KMFolder*>(it);
01844 QString label = child->label();
01845 label.replace("&","&&");
01846 if (child->child() && child->child()->first()) {
01847
01848 QPopupMenu *subMenu = new QPopupMenu(menu, "subMenu");
01849 makeFolderMenu( child, move, receiver,
01850 aMenuToFolder, subMenu );
01851 menu->insertItem( label, subMenu );
01852 } else {
01853
01854 int menuId = menu->insertItem( label );
01855 aMenuToFolder->insert( menuId, child );
01856 menu->setItemEnabled( menuId, !child->isReadOnly() );
01857 }
01858 }
01859 return;
01860 }
01861
01862
01863 KMCopyCommand::KMCopyCommand( KMFolder* destFolder,
01864 const QPtrList<KMMsgBase> &msgList )
01865 :mDestFolder( destFolder ), mMsgList( msgList )
01866 {
01867 setDeletesItself( true );
01868 }
01869
01870 KMCopyCommand::KMCopyCommand( KMFolder* destFolder, KMMessage * msg )
01871 :mDestFolder( destFolder )
01872 {
01873 setDeletesItself( true );
01874 mMsgList.append( &msg->toMsgBase() );
01875 }
01876
01877 KMCommand::Result KMCopyCommand::execute()
01878 {
01879 KMMsgBase *msgBase;
01880 KMMessage *msg, *newMsg;
01881 int idx = -1;
01882 bool isMessage;
01883 QPtrList<KMMessage> list;
01884 QPtrList<KMMessage> localList;
01885
01886 if (mDestFolder && mDestFolder->open() != 0)
01887 {
01888 deleteLater();
01889 return Failed;
01890 }
01891
01892 KCursorSaver busy(KBusyPtr::busy());
01893
01894 mWaitingForMsgs.clear();
01895 for (msgBase = mMsgList.first(); msgBase; msgBase = mMsgList.next() )
01896 {
01897 KMFolder *srcFolder = msgBase->parent();
01898 if (isMessage = msgBase->isMessage())
01899 {
01900 msg = static_cast<KMMessage*>(msgBase);
01901 } else {
01902 idx = srcFolder->find(msgBase);
01903 assert(idx != -1);
01904 msg = srcFolder->getMsg(idx);
01905 }
01906
01907 if (srcFolder && mDestFolder &&
01908 (srcFolder->folderType()== KMFolderTypeImap) &&
01909 (mDestFolder->folderType() == KMFolderTypeImap) &&
01910 (static_cast<KMFolderImap*>(srcFolder->storage())->account() ==
01911 static_cast<KMFolderImap*>(mDestFolder->storage())->account()))
01912 {
01913
01914 list.append(msg);
01915 } else {
01916 newMsg = new KMMessage( new DwMessage( *msg->asDwMessage() ) );
01917 newMsg->setComplete(msg->isComplete());
01918
01919 if (!newMsg->isComplete())
01920 newMsg->setReadyToShow(false);
01921 newMsg->setStatus(msg->status());
01922
01923 if (srcFolder && !newMsg->isComplete())
01924 {
01925
01926 mWaitingForMsgs.append( msg->getMsgSerNum() );
01927 disconnect(mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
01928 this, SLOT(slotMsgAdded(KMFolder*, Q_UINT32)));
01929 connect(mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
01930 this, SLOT(slotMsgAdded(KMFolder*, Q_UINT32)));
01931 newMsg->setParent(msg->parent());
01932 FolderJob *job = srcFolder->createJob(newMsg);
01933 job->setCancellable( false );
01934 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
01935 mDestFolder, SLOT(reallyAddCopyOfMsg(KMMessage*)));
01936 job->start();
01937 } else {
01938
01939 localList.append(newMsg);
01940 }
01941 }
01942
01943 if (srcFolder && !isMessage && list.isEmpty())
01944 {
01945 assert(idx != -1);
01946 srcFolder->unGetMsg( idx );
01947 }
01948
01949 }
01950
01951 bool deleteNow = false;
01952 if (!localList.isEmpty())
01953 {
01954 QValueList<int> index;
01955 mDestFolder->addMsg( localList, index );
01956 for ( QValueListIterator<int> it = index.begin(); it != index.end(); ++it ) {
01957 mDestFolder->unGetMsg( *it );
01958 }
01959 if ( mDestFolder->folderType() == KMFolderTypeImap ) {
01960 if ( mWaitingForMsgs.isEmpty() ) {
01961
01962 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(mDestFolder->storage());
01963 connect( imapDestFolder, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
01964 this, SLOT( slotFolderComplete() ) );
01965 }
01966 } else {
01967 deleteNow = true;
01968 }
01969 }
01970
01971
01972
01973 if (!list.isEmpty())
01974 {
01975
01976 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(mDestFolder->storage());
01977 connect( imapDestFolder, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
01978 this, SLOT( slotFolderComplete() ) );
01979 imapDestFolder->copyMsg(list);
01980 imapDestFolder->getFolder();
01981 }
01982
01983
01984
01985 if ( deleteNow )
01986 {
01987 mDestFolder->close();
01988 deleteLater();
01989 }
01990
01991 return OK;
01992 }
01993
01994 void KMCopyCommand::slotMsgAdded( KMFolder*, Q_UINT32 serNum )
01995 {
01996 mWaitingForMsgs.remove( serNum );
01997 if ( mWaitingForMsgs.isEmpty() )
01998 {
01999 mDestFolder->close();
02000 deleteLater();
02001 }
02002 }
02003
02004 void KMCopyCommand::slotFolderComplete()
02005 {
02006 mDestFolder->close();
02007 deleteLater();
02008 }
02009
02010
02011 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
02012 const QPtrList<KMMsgBase> &msgList)
02013 : mDestFolder( destFolder ), mMsgList( msgList ), mProgressItem( 0 )
02014 {
02015 }
02016
02017 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
02018 KMMessage *msg )
02019 : mDestFolder( destFolder ), mProgressItem( 0 )
02020 {
02021 mMsgList.append( &msg->toMsgBase() );
02022 }
02023
02024 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
02025 KMMsgBase *msgBase )
02026 : mDestFolder( destFolder ), mProgressItem( 0 )
02027 {
02028 mMsgList.append( msgBase );
02029 }
02030
02031 KMMoveCommand::KMMoveCommand( Q_UINT32 )
02032 : mProgressItem( 0 )
02033 {
02034 }
02035
02036 KMCommand::Result KMMoveCommand::execute()
02037 {
02038 setEmitsCompletedItself( true );
02039 setDeletesItself( true );
02040 typedef QMap< KMFolder*, QPtrList<KMMessage>* > FolderToMessageListMap;
02041 FolderToMessageListMap folderDeleteList;
02042
02043 if (mDestFolder && mDestFolder->open() != 0) {
02044 completeMove( Failed );
02045 return Failed;
02046 }
02047 KCursorSaver busy(KBusyPtr::busy());
02048
02049
02050 Q_ASSERT( !mProgressItem );
02051 mProgressItem =
02052 ProgressManager::createProgressItem (
02053 "move"+ProgressManager::getUniqueID(),
02054 mDestFolder ? i18n( "Moving messages" ) : i18n( "Deleting messages" ) );
02055 connect( mProgressItem, SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
02056 this, SLOT( slotMoveCanceled() ) );
02057
02058 KMMessage *msg;
02059 KMMsgBase *msgBase;
02060 int rc = 0;
02061 int index;
02062 QPtrList<KMMessage> list;
02063 int undoId = -1;
02064 mCompleteWithAddedMsg = false;
02065
02066 if (mDestFolder) {
02067 connect (mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
02068 this, SLOT(slotMsgAddedToDestFolder(KMFolder*, Q_UINT32)));
02069 for ( msgBase=mMsgList.first(); msgBase; msgBase=mMsgList.next() ) {
02070 mLostBoys.append( msgBase->getMsgSerNum() );
02071 }
02072 }
02073 mProgressItem->setTotalItems( mMsgList.count() );
02074
02075 for (msgBase=mMsgList.first(); msgBase && !rc; msgBase=mMsgList.next()) {
02076 KMFolder *srcFolder = msgBase->parent();
02077 if (srcFolder == mDestFolder)
02078 continue;
02079 bool undo = msgBase->enableUndo();
02080 int idx = srcFolder->find(msgBase);
02081 assert(idx != -1);
02082 if ( msgBase->isMessage() ) {
02083 msg = static_cast<KMMessage*>(msgBase);
02084 } else {
02085 msg = srcFolder->getMsg(idx);
02086 }
02087
02088 if ( msg && msg->transferInProgress() &&
02089 srcFolder->folderType() == KMFolderTypeImap )
02090 {
02091
02092 msg->setTransferInProgress( false, true );
02093 static_cast<KMFolderImap*>(srcFolder->storage())->ignoreJobsForMessage( msg );
02094 }
02095
02096 if (mDestFolder) {
02097 if (mDestFolder->folderType() == KMFolderTypeImap) {
02098
02099
02100
02101 KMFolderImap *imapFolder = static_cast<KMFolderImap*> ( mDestFolder->storage() );
02102 disconnect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
02103 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
02104
02105 connect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
02106 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
02107 list.append(msg);
02108 } else {
02109
02110 if ( srcFolder->folderType() == KMFolderTypeImap )
02111 {
02112
02113 mCompleteWithAddedMsg = true;
02114 }
02115 rc = mDestFolder->moveMsg(msg, &index);
02116 if (rc == 0 && index != -1) {
02117 KMMsgBase *mb = mDestFolder->unGetMsg( mDestFolder->count() - 1 );
02118 if (undo && mb)
02119 {
02120 if ( undoId == -1 )
02121 undoId = kmkernel->undoStack()->newUndoAction( srcFolder, mDestFolder );
02122 kmkernel->undoStack()->addMsgToAction( undoId, mb->getMsgSerNum() );
02123 }
02124 } else if (rc != 0) {
02125
02126
02127 completeMove( Failed );
02128 return Failed;
02129 }
02130 }
02131 } else {
02132
02133
02134 if (srcFolder->folderType() == KMFolderTypeImap) {
02135 if (!folderDeleteList[srcFolder])
02136 folderDeleteList[srcFolder] = new QPtrList<KMMessage>;
02137 folderDeleteList[srcFolder]->append( msg );
02138 } else {
02139 srcFolder->removeMsg(idx);
02140 delete msg;
02141 }
02142 }
02143 }
02144 if (!list.isEmpty() && mDestFolder) {
02145
02146 mDestFolder->moveMsg(list, &index);
02147 } else {
02148 FolderToMessageListMap::Iterator it;
02149 for ( it = folderDeleteList.begin(); it != folderDeleteList.end(); ++it ) {
02150 it.key()->removeMsg(*it.data());
02151 delete it.data();
02152 }
02153 if ( !mCompleteWithAddedMsg ) {
02154
02155 completeMove( OK );
02156 }
02157 }
02158
02159 return OK;
02160 }
02161
02162 void KMMoveCommand::slotImapFolderCompleted(KMFolderImap* imapFolder, bool success)
02163 {
02164 disconnect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
02165 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
02166 if ( success ) {
02167
02168
02169
02170
02171
02172
02173 if ( !mLostBoys.isEmpty() ) {
02174 kdDebug(5006) << "### Not all moved messages reported back that they were " << endl
02175 << "### added to the target folder. Did uidValidity change? " << endl;
02176 }
02177 completeMove( OK );
02178 } else {
02179
02180 completeMove( Failed );
02181 }
02182 }
02183
02184 void KMMoveCommand::slotMsgAddedToDestFolder(KMFolder *folder, Q_UINT32 serNum)
02185 {
02186 if ( folder != mDestFolder || mLostBoys.find( serNum ) == mLostBoys.end() ) {
02187
02188
02189 return;
02190 }
02191 mLostBoys.remove(serNum);
02192 if ( mLostBoys.isEmpty() ) {
02193
02194 disconnect (mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
02195 this, SLOT(slotMsgAddedToDestFolder(KMFolder*, Q_UINT32)));
02196 if (mDestFolder && mDestFolder->folderType() != KMFolderTypeImap) {
02197 mDestFolder->sync();
02198 }
02199 if ( mCompleteWithAddedMsg ) {
02200 completeMove( OK );
02201 }
02202 } else {
02203 if ( mProgressItem ) {
02204 mProgressItem->incCompletedItems();
02205 mProgressItem->updateProgress();
02206 }
02207 }
02208 }
02209
02210 void KMMoveCommand::completeMove( Result result )
02211 {
02212 if ( mDestFolder )
02213 mDestFolder->close();
02214 while ( !mOpenedFolders.empty() ) {
02215 KMFolder *folder = mOpenedFolders.back();
02216 mOpenedFolders.pop_back();
02217 folder->close();
02218 }
02219 if ( mProgressItem ) {
02220 mProgressItem->setComplete();
02221 mProgressItem = 0;
02222 }
02223 setResult( result );
02224 emit completed( this );
02225 deleteLater();
02226 }
02227
02228 void KMMoveCommand::slotMoveCanceled()
02229 {
02230 completeMove( Canceled );
02231 }
02232
02233
02234 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder,
02235 const QPtrList<KMMsgBase> &msgList )
02236 :KMMoveCommand( findTrashFolder( srcFolder ), msgList)
02237 {
02238 srcFolder->open();
02239 mOpenedFolders.push_back( srcFolder );
02240 }
02241
02242 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder, KMMessage * msg )
02243 :KMMoveCommand( findTrashFolder( srcFolder ), msg)
02244 {
02245 srcFolder->open();
02246 mOpenedFolders.push_back( srcFolder );
02247 }
02248
02249 KMDeleteMsgCommand::KMDeleteMsgCommand( Q_UINT32 sernum )
02250 :KMMoveCommand( sernum )
02251 {
02252 KMFolder *srcFolder = 0;
02253 int idx;
02254 KMMsgDict::instance()->getLocation( sernum, &srcFolder, &idx );
02255 if ( srcFolder ) {
02256 KMMsgBase *msg = srcFolder->getMsgBase( idx );
02257 srcFolder->open();
02258 mOpenedFolders.push_back( srcFolder );
02259 addMsg( msg );
02260 }
02261 setDestFolder( findTrashFolder( srcFolder ) );
02262 }
02263
02264 KMFolder * KMDeleteMsgCommand::findTrashFolder( KMFolder * folder )
02265 {
02266 KMFolder* trash = folder->trashFolder();
02267 if( !trash )
02268 trash = kmkernel->trashFolder();
02269 if( trash != folder )
02270 return trash;
02271 return 0;
02272 }
02273
02274
02275 KMUrlClickedCommand::KMUrlClickedCommand( const KURL &url, uint identity,
02276 KMReaderWin *readerWin, bool htmlPref, KMMainWidget *mainWidget )
02277 :mUrl( url ), mIdentity( identity ), mReaderWin( readerWin ),
02278 mHtmlPref( htmlPref ), mMainWidget( mainWidget )
02279 {
02280 }
02281
02282 KMCommand::Result KMUrlClickedCommand::execute()
02283 {
02284 KMMessage* msg;
02285
02286 if (mUrl.protocol() == "mailto")
02287 {
02288 msg = new KMMessage;
02289 msg->initHeader(mIdentity);
02290 msg->setCharset("utf-8");
02291 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
02292 QString query=mUrl.query();
02293 while (!query.isEmpty()) {
02294 QString queryPart;
02295 int secondQuery = query.find('?',1);
02296 if (secondQuery != -1)
02297 queryPart = query.left(secondQuery);
02298 else
02299 queryPart = query;
02300 query = query.mid(queryPart.length());
02301
02302 if (queryPart.left(9) == "?subject=")
02303 msg->setSubject( KURL::decode_string(queryPart.mid(9)) );
02304 else if (queryPart.left(6) == "?body=")
02305
02306
02307 msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() );
02308 else if (queryPart.left(4) == "?cc=")
02309 msg->setCc( KURL::decode_string(queryPart.mid(4)) );
02310 }
02311
02312 KMail::Composer * win = KMail::makeComposer( msg, mIdentity );
02313 win->setCharset("", TRUE);
02314 win->show();
02315 }
02316 else if ( mUrl.protocol() == "im" )
02317 {
02318 kmkernel->imProxy()->chatWithContact( mUrl.path() );
02319 }
02320 else if ((mUrl.protocol() == "http") || (mUrl.protocol() == "https") ||
02321 (mUrl.protocol() == "ftp") || (mUrl.protocol() == "file") ||
02322 (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
02323 (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
02324 (mUrl.protocol() == "smb") || (mUrl.protocol() == "fish") ||
02325 (mUrl.protocol() == "news"))
02326 {
02327 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n("Opening URL..."));
02328 KMimeType::Ptr mime = KMimeType::findByURL( mUrl );
02329 if (mime->name() == "application/x-desktop" ||
02330 mime->name() == "application/x-executable" ||
02331 mime->name() == "application/x-msdos-program" ||
02332 mime->name() == "application/x-shellscript" )
02333 {
02334 if (KMessageBox::warningYesNo( 0, i18n( "<qt>Do you really want to execute <b>%1</b>?</qt>" )
02335 .arg( mUrl.prettyURL() ), QString::null, i18n("Execute"), KStdGuiItem::cancel() ) != KMessageBox::Yes)
02336 return Canceled;
02337 }
02338 (void) new KRun( mUrl );
02339 }
02340 else
02341 return Failed;
02342
02343 return OK;
02344 }
02345
02346 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, KMMessage *msg )
02347 : KMCommand( parent, msg ), mImplicitAttachments( true ), mEncoded( false )
02348 {
02349 }
02350
02351 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, const QPtrList<KMMsgBase>& msgs )
02352 : KMCommand( parent, msgs ), mImplicitAttachments( true ), mEncoded( false )
02353 {
02354 }
02355
02356 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, QPtrList<partNode>& attachments,
02357 KMMessage *msg, bool encoded )
02358 : KMCommand( parent ), mImplicitAttachments( false ), mEncoded( encoded )
02359 {
02360 for ( QPtrListIterator<partNode> it( attachments ); it.current(); ++it ) {
02361 mAttachmentMap.insert( it.current(), msg );
02362 }
02363 }
02364
02365 KMCommand::Result KMSaveAttachmentsCommand::execute()
02366 {
02367 setEmitsCompletedItself( true );
02368 if ( mImplicitAttachments ) {
02369 QPtrList<KMMessage> msgList = retrievedMsgs();
02370 KMMessage *msg;
02371 for ( QPtrListIterator<KMMessage> itr( msgList );
02372 ( msg = itr.current() );
02373 ++itr ) {
02374 partNode *rootNode = partNode::fromMessage( msg );
02375 for ( partNode *child = rootNode; child;
02376 child = child->firstChild() ) {
02377 for ( partNode *node = child; node; node = node->nextSibling() ) {
02378 if ( node->type() != DwMime::kTypeMultipart )
02379 mAttachmentMap.insert( node, msg );
02380 }
02381 }
02382 }
02383 }
02384 setDeletesItself( true );
02385
02386 KMLoadPartsCommand *command = new KMLoadPartsCommand( mAttachmentMap );
02387 connect( command, SIGNAL( partsRetrieved() ),
02388 this, SLOT( slotSaveAll() ) );
02389 command->start();
02390
02391 return OK;
02392 }
02393
02394 void KMSaveAttachmentsCommand::slotSaveAll()
02395 {
02396
02397
02398
02399 if ( mImplicitAttachments ) {
02400 for ( PartNodeMessageMap::iterator it = mAttachmentMap.begin();
02401 it != mAttachmentMap.end(); ) {
02402
02403
02404
02405 if ( it.key()->msgPart().fileName().stripWhiteSpace().isEmpty() &&
02406 ( it.key()->msgPart().name().stripWhiteSpace().isEmpty() ||
02407 !it.key()->parentNode() ) ) {
02408 PartNodeMessageMap::iterator delIt = it;
02409 ++it;
02410 mAttachmentMap.remove( delIt );
02411 }
02412 else
02413 ++it;
02414 }
02415 if ( mAttachmentMap.isEmpty() ) {
02416 KMessageBox::information( 0, i18n("Found no attachments to save.") );
02417 setResult( OK );
02418 emit completed( this );
02419 deleteLater();
02420 return;
02421 }
02422 }
02423
02424 KURL url, dirUrl;
02425 if ( mAttachmentMap.count() > 1 ) {
02426
02427 dirUrl = KDirSelectDialog::selectDirectory( QString::null, false,
02428 parentWidget(),
02429 i18n("Save Attachments To") );
02430 if ( !dirUrl.isValid() ) {
02431 setResult( Canceled );
02432 emit completed( this );
02433 deleteLater();
02434 return;
02435 }
02436
02437
02438 dirUrl.adjustPath( 1 );
02439 }
02440 else {
02441
02442 partNode *node = mAttachmentMap.begin().key();
02443
02444 QString s =
02445 node->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02446 if ( s.isEmpty() )
02447 s = node->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02448 if ( s.isEmpty() )
02449 s = i18n("filename for an unnamed attachment", "attachment.1");
02450 url = KFileDialog::getSaveURL( s, QString::null, parentWidget(),
02451 QString::null );
02452 if ( url.isEmpty() ) {
02453 setResult( Canceled );
02454 emit completed( this );
02455 deleteLater();
02456 return;
02457 }
02458 }
02459
02460 QMap< QString, int > renameNumbering;
02461
02462 Result globalResult = OK;
02463 int unnamedAtmCount = 0;
02464 for ( PartNodeMessageMap::const_iterator it = mAttachmentMap.begin();
02465 it != mAttachmentMap.end();
02466 ++it ) {
02467 KURL curUrl;
02468 if ( !dirUrl.isEmpty() ) {
02469 curUrl = dirUrl;
02470 QString s =
02471 it.key()->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02472 if ( s.isEmpty() )
02473 s = it.key()->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02474 if ( s.isEmpty() ) {
02475 ++unnamedAtmCount;
02476 s = i18n("filename for the %1-th unnamed attachment",
02477 "attachment.%1")
02478 .arg( unnamedAtmCount );
02479 }
02480 curUrl.setFileName( s );
02481 } else {
02482 curUrl = url;
02483 }
02484
02485 if ( !curUrl.isEmpty() ) {
02486
02487
02488
02489 QString origFile = curUrl.fileName();
02490 QString file = origFile;
02491
02492 while ( renameNumbering.contains(file) ) {
02493 file = origFile;
02494 int num = renameNumbering[file] + 1;
02495 int dotIdx = file.findRev('.');
02496 file = file.insert( (dotIdx>=0) ? dotIdx : file.length(), QString("_") + QString::number(num) );
02497 }
02498 curUrl.setFileName(file);
02499
02500
02501 if ( !renameNumbering.contains(origFile))
02502 renameNumbering[origFile] = 1;
02503 else
02504 renameNumbering[origFile]++;
02505
02506 if ( file != origFile ) {
02507 if ( !renameNumbering.contains(file))
02508 renameNumbering[file] = 1;
02509 else
02510 renameNumbering[file]++;
02511 }
02512
02513
02514 if ( KIO::NetAccess::exists( curUrl, false, parentWidget() ) ) {
02515 if ( KMessageBox::warningContinueCancel( parentWidget(),
02516 i18n( "A file named %1 already exists. Do you want to overwrite it?" )
02517 .arg( curUrl.fileName() ),
02518 i18n( "File Already Exists" ), i18n("&Overwrite") ) == KMessageBox::Cancel) {
02519 continue;
02520 }
02521 }
02522
02523 const Result result = saveItem( it.key(), curUrl );
02524 if ( result != OK )
02525 globalResult = result;
02526 }
02527 }
02528 setResult( globalResult );
02529 emit completed( this );
02530 deleteLater();
02531 }
02532
02533 KMCommand::Result KMSaveAttachmentsCommand::saveItem( partNode *node,
02534 const KURL& url )
02535 {
02536 bool bSaveEncrypted = false;
02537 bool bEncryptedParts = node->encryptionState() != KMMsgNotEncrypted;
02538 if( bEncryptedParts )
02539 if( KMessageBox::questionYesNo( parentWidget(),
02540 i18n( "The part %1 of the message is encrypted. Do you want to keep the encryption when saving?" ).
02541 arg( url.fileName() ),
02542 i18n( "KMail Question" ), i18n("Keep Encryption"), i18n("Do Not Keep") ) ==
02543 KMessageBox::Yes )
02544 bSaveEncrypted = true;
02545
02546 bool bSaveWithSig = true;
02547 if( node->signatureState() != KMMsgNotSigned )
02548 if( KMessageBox::questionYesNo( parentWidget(),
02549 i18n( "The part %1 of the message is signed. Do you want to keep the signature when saving?" ).
02550 arg( url.fileName() ),
02551 i18n( "KMail Question" ), i18n("Keep Signature"), i18n("Do Not Keep") ) !=
02552 KMessageBox::Yes )
02553 bSaveWithSig = false;
02554
02555 QByteArray data;
02556 if ( mEncoded )
02557 {
02558
02559
02560 data = KMail::Util::ByteArray( node->msgPart().dwBody() );
02561 }
02562 else
02563 {
02564 if( bSaveEncrypted || !bEncryptedParts) {
02565 partNode *dataNode = node;
02566 QCString rawReplyString;
02567 bool gotRawReplyString = false;
02568 if( !bSaveWithSig ) {
02569 if( DwMime::kTypeMultipart == node->type() &&
02570 DwMime::kSubtypeSigned == node->subType() ){
02571
02572 if( node->findType( DwMime::kTypeApplication,
02573 DwMime::kSubtypePgpSignature,
02574 TRUE, false ) ){
02575 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02576 DwMime::kSubtypePgpSignature,
02577 TRUE, false );
02578 }else if( node->findType( DwMime::kTypeApplication,
02579 DwMime::kSubtypePkcs7Mime,
02580 TRUE, false ) ){
02581 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02582 DwMime::kSubtypePkcs7Mime,
02583 TRUE, false );
02584 }else{
02585 dataNode = node->findTypeNot( DwMime::kTypeMultipart,
02586 DwMime::kSubtypeUnknown,
02587 TRUE, false );
02588 }
02589 }else{
02590 ObjectTreeParser otp( 0, 0, false, false, false );
02591
02592
02593 dataNode->setProcessed( false, true );
02594 otp.parseObjectTree( dataNode );
02595
02596 rawReplyString = otp.rawReplyString();
02597 gotRawReplyString = true;
02598 }
02599 }
02600 QByteArray cstr = gotRawReplyString
02601 ? rawReplyString
02602 : dataNode->msgPart().bodyDecodedBinary();
02603 data = cstr;
02604 size_t size = cstr.size();
02605 if ( dataNode->msgPart().type() == DwMime::kTypeText ) {
02606
02607 size = KMail::Util::crlf2lf( cstr.data(), size );
02608 }
02609 data.resize( size );
02610 }
02611 }
02612 QDataStream ds;
02613 QFile file;
02614 KTempFile tf;
02615 tf.setAutoDelete( true );
02616 if ( url.isLocalFile() )
02617 {
02618
02619 file.setName( url.path() );
02620 if ( !file.open( IO_WriteOnly ) )
02621 {
02622 KMessageBox::error( parentWidget(),
02623 i18n( "%2 is detailed error description",
02624 "Could not write the file %1:\n%2" )
02625 .arg( file.name() )
02626 .arg( QString::fromLocal8Bit( strerror( errno ) ) ),
02627 i18n( "KMail Error" ) );
02628 return Failed;
02629 }
02630 fchmod( file.handle(), S_IRUSR | S_IWUSR );
02631 ds.setDevice( &file );
02632 } else
02633 {
02634
02635 ds.setDevice( tf.file() );
02636 }
02637
02638 ds.writeRawBytes( data.data(), data.size() );
02639 if ( !url.isLocalFile() )
02640 {
02641 tf.close();
02642 if ( !KIO::NetAccess::upload( tf.name(), url, parentWidget() ) )
02643 {
02644 KMessageBox::error( parentWidget(),
02645 i18n( "Could not write the file %1." )
02646 .arg( url.path() ),
02647 i18n( "KMail Error" ) );
02648 return Failed;
02649 }
02650 } else
02651 file.close();
02652 return OK;
02653 }
02654
02655 KMLoadPartsCommand::KMLoadPartsCommand( QPtrList<partNode>& parts, KMMessage *msg )
02656 : mNeedsRetrieval( 0 )
02657 {
02658 for ( QPtrListIterator<partNode> it( parts ); it.current(); ++it ) {
02659 mPartMap.insert( it.current(), msg );
02660 }
02661 }
02662
02663 KMLoadPartsCommand::KMLoadPartsCommand( partNode *node, KMMessage *msg )
02664 : mNeedsRetrieval( 0 )
02665 {
02666 mPartMap.insert( node, msg );
02667 }
02668
02669 KMLoadPartsCommand::KMLoadPartsCommand( PartNodeMessageMap& partMap )
02670 : mNeedsRetrieval( 0 ), mPartMap( partMap )
02671 {
02672 }
02673
02674 void KMLoadPartsCommand::slotStart()
02675 {
02676 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02677 it != mPartMap.end();
02678 ++it ) {
02679 if ( !it.key()->msgPart().isComplete() &&
02680 !it.key()->msgPart().partSpecifier().isEmpty() ) {
02681
02682 ++mNeedsRetrieval;
02683 KMFolder* curFolder = it.data()->parent();
02684 if ( curFolder ) {
02685 FolderJob *job =
02686 curFolder->createJob( it.data(), FolderJob::tGetMessage,
02687 0, it.key()->msgPart().partSpecifier() );
02688 job->setCancellable( false );
02689 connect( job, SIGNAL(messageUpdated(KMMessage*, QString)),
02690 this, SLOT(slotPartRetrieved(KMMessage*, QString)) );
02691 job->start();
02692 } else
02693 kdWarning(5006) << "KMLoadPartsCommand - msg has no parent" << endl;
02694 }
02695 }
02696 if ( mNeedsRetrieval == 0 )
02697 execute();
02698 }
02699
02700 void KMLoadPartsCommand::slotPartRetrieved( KMMessage *msg,
02701 QString partSpecifier )
02702 {
02703 DwBodyPart *part =
02704 msg->findDwBodyPart( msg->getFirstDwBodyPart(), partSpecifier );
02705 if ( part ) {
02706
02707 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02708 it != mPartMap.end();
02709 ++it ) {
02710 if ( it.key()->dwPart()->partId() == part->partId() )
02711 it.key()->setDwPart( part );
02712 }
02713 } else
02714 kdWarning(5006) << "KMLoadPartsCommand::slotPartRetrieved - could not find bodypart!" << endl;
02715 --mNeedsRetrieval;
02716 if ( mNeedsRetrieval == 0 )
02717 execute();
02718 }
02719
02720 KMCommand::Result KMLoadPartsCommand::execute()
02721 {
02722 emit partsRetrieved();
02723 setResult( OK );
02724 emit completed( this );
02725 deleteLater();
02726 return OK;
02727 }
02728
02729 KMResendMessageCommand::KMResendMessageCommand( QWidget *parent,
02730 KMMessage *msg )
02731 :KMCommand( parent, msg )
02732 {
02733 }
02734
02735 KMCommand::Result KMResendMessageCommand::execute()
02736 {
02737 KMMessage *msg = retrievedMessage();
02738
02739 KMMessage *newMsg = new KMMessage(*msg);
02740 newMsg->setCharset(msg->codec()->mimeName());
02741
02742 newMsg->removeHeaderField( "Message-Id" );
02743 newMsg->setParent( 0 );
02744
02745
02746 newMsg->removeHeaderField( "Date" );
02747
02748 KMail::Composer * win = KMail::makeComposer();
02749 win->setMsg(newMsg, false, true);
02750 win->show();
02751
02752 return OK;
02753 }
02754
02755 KMMailingListCommand::KMMailingListCommand( QWidget *parent, KMFolder *folder )
02756 : KMCommand( parent ), mFolder( folder )
02757 {
02758 }
02759
02760 KMCommand::Result KMMailingListCommand::execute()
02761 {
02762 KURL::List lst = urls();
02763 QString handler = ( mFolder->mailingList().handler() == MailingList::KMail )
02764 ? "mailto" : "https";
02765
02766 KMCommand *command = 0;
02767 for ( KURL::List::Iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
02768 if ( handler == (*itr).protocol() ) {
02769 command = new KMUrlClickedCommand( *itr, mFolder->identity(), 0, false );
02770 }
02771 }
02772 if ( !command && !lst.empty() ) {
02773 command =
02774 new KMUrlClickedCommand( lst.first(), mFolder->identity(), 0, false );
02775 }
02776 if ( command ) {
02777 connect( command, SIGNAL( completed( KMCommand * ) ),
02778 this, SLOT( commandCompleted( KMCommand * ) ) );
02779 setDeletesItself( true );
02780 setEmitsCompletedItself( true );
02781 command->start();
02782 return OK;
02783 }
02784 return Failed;
02785 }
02786
02787 void KMMailingListCommand::commandCompleted( KMCommand *command )
02788 {
02789 setResult( command->result() );
02790 emit completed( this );
02791 deleteLater();
02792 }
02793
02794 KMMailingListPostCommand::KMMailingListPostCommand( QWidget *parent, KMFolder *folder )
02795 : KMMailingListCommand( parent, folder )
02796 {
02797 }
02798 KURL::List KMMailingListPostCommand::urls() const
02799 {
02800 return mFolder->mailingList().postURLS();
02801 }
02802
02803 KMMailingListSubscribeCommand::KMMailingListSubscribeCommand( QWidget *parent, KMFolder *folder )
02804 : KMMailingListCommand( parent, folder )
02805 {
02806 }
02807 KURL::List KMMailingListSubscribeCommand::urls() const
02808 {
02809 return mFolder->mailingList().subscribeURLS();
02810 }
02811
02812 KMMailingListUnsubscribeCommand::KMMailingListUnsubscribeCommand( QWidget *parent, KMFolder *folder )
02813 : KMMailingListCommand( parent, folder )
02814 {
02815 }
02816 KURL::List KMMailingListUnsubscribeCommand::urls() const
02817 {
02818 return mFolder->mailingList().unsubscribeURLS();
02819 }
02820
02821 KMMailingListArchivesCommand::KMMailingListArchivesCommand( QWidget *parent, KMFolder *folder )
02822 : KMMailingListCommand( parent, folder )
02823 {
02824 }
02825 KURL::List KMMailingListArchivesCommand::urls() const
02826 {
02827 return mFolder->mailingList().archiveURLS();
02828 }
02829
02830 KMMailingListHelpCommand::KMMailingListHelpCommand( QWidget *parent, KMFolder *folder )
02831 : KMMailingListCommand( parent, folder )
02832 {
02833 }
02834 KURL::List KMMailingListHelpCommand::urls() const
02835 {
02836 return mFolder->mailingList().helpURLS();
02837 }
02838
02839 KMIMChatCommand::KMIMChatCommand( const KURL &url, KMMessage *msg )
02840 :mUrl( url ), mMessage( msg )
02841 {
02842 }
02843
02844 KMCommand::Result KMIMChatCommand::execute()
02845 {
02846 kdDebug( 5006 ) << k_funcinfo << " URL is: " << mUrl << endl;
02847 QString addr = KMMessage::decodeMailtoUrl( mUrl.path() );
02848
02849 KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
02850 KABC::AddresseeList addressees = addressBook->findByEmail( KPIM::getEmailAddress( addr ) ) ;
02851
02852
02853 if( addressees.count() == 1 ) {
02854 kmkernel->imProxy()->chatWithContact( addressees[0].uid() );
02855 return OK;
02856 }
02857 else
02858 {
02859 kdDebug( 5006 ) << "Didn't find exactly one addressee, couldn't tell who to chat to for that email address. Count = " << addressees.count() << endl;
02860
02861 QString apology;
02862 if ( addressees.isEmpty() )
02863 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." );
02864 else
02865 {
02866 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." );
02867 QStringList nameList;
02868 KABC::AddresseeList::const_iterator it = addressees.begin();
02869 KABC::AddresseeList::const_iterator end = addressees.end();
02870 for ( ; it != end; ++it )
02871 {
02872 nameList.append( (*it).realName() );
02873 }
02874 QString names = nameList.join( QString::fromLatin1( ",\n" ) );
02875 apology = apology.arg( names );
02876 }
02877
02878 KMessageBox::sorry( parentWidget(), apology );
02879 return Failed;
02880 }
02881 }
02882
02883 KMHandleAttachmentCommand::KMHandleAttachmentCommand( partNode* node,
02884 KMMessage* msg, int atmId, const QString& atmName,
02885 AttachmentAction action, KService::Ptr offer, QWidget* parent )
02886 : KMCommand( parent ), mNode( node ), mMsg( msg ), mAtmId( atmId ), mAtmName( atmName ),
02887 mAction( action ), mOffer( offer ), mJob( 0 )
02888 {
02889 }
02890
02891 void KMHandleAttachmentCommand::slotStart()
02892 {
02893 if ( !mNode->msgPart().isComplete() )
02894 {
02895
02896 kdDebug(5006) << "load part" << endl;
02897 KMLoadPartsCommand *command = new KMLoadPartsCommand( mNode, mMsg );
02898 connect( command, SIGNAL( partsRetrieved() ),
02899 this, SLOT( slotPartComplete() ) );
02900 command->start();
02901 } else
02902 {
02903 execute();
02904 }
02905 }
02906
02907 void KMHandleAttachmentCommand::slotPartComplete()
02908 {
02909 execute();
02910 }
02911
02912 KMCommand::Result KMHandleAttachmentCommand::execute()
02913 {
02914 switch( mAction )
02915 {
02916 case Open:
02917 atmOpen();
02918 break;
02919 case OpenWith:
02920 atmOpenWith();
02921 break;
02922 case View:
02923 atmView();
02924 break;
02925 case Save:
02926 atmSave();
02927 break;
02928 case Properties:
02929 atmProperties();
02930 break;
02931 case ChiasmusEncrypt:
02932 atmEncryptWithChiasmus();
02933 return Undefined;
02934 break;
02935 default:
02936 kdDebug(5006) << "unknown action " << mAction << endl;
02937 break;
02938 }
02939 setResult( OK );
02940 emit completed( this );
02941 deleteLater();
02942 return OK;
02943 }
02944
02945 QString KMHandleAttachmentCommand::createAtmFileLink() const
02946 {
02947 QFileInfo atmFileInfo( mAtmName );
02948
02949 if ( atmFileInfo.size() == 0 )
02950 {
02951 kdDebug(5006) << k_funcinfo << "rewriting attachment" << endl;
02952
02953 QByteArray data = mNode->msgPart().bodyDecodedBinary();
02954 size_t size = data.size();
02955 if ( mNode->msgPart().type() == DwMime::kTypeText && size) {
02956
02957 size = KMail::Util::crlf2lf( data.data(), size );
02958 }
02959 KPIM::kBytesToFile( data.data(), size, mAtmName, false, false, false );
02960 }
02961
02962 KTempFile *linkFile = new KTempFile( locateLocal("tmp", atmFileInfo.fileName() +"_["),
02963 "]."+ atmFileInfo.extension() );
02964
02965 linkFile->setAutoDelete(true);
02966 QString linkName = linkFile->name();
02967 delete linkFile;
02968
02969 if ( ::link(QFile::encodeName( mAtmName ), QFile::encodeName( linkName )) == 0 ) {
02970 return linkName;
02971 }
02972 return QString::null;
02973 }
02974
02975 KService::Ptr KMHandleAttachmentCommand::getServiceOffer()
02976 {
02977 KMMessagePart& msgPart = mNode->msgPart();
02978 const QString contentTypeStr =
02979 ( msgPart.typeStr() + '/' + msgPart.subtypeStr() ).lower();
02980
02981 if ( contentTypeStr == "text/x-vcard" ) {
02982 atmView();
02983 return 0;
02984 }
02985
02986 KMimeType::Ptr mimetype;
02987
02988 mimetype = KMimeType::mimeType( contentTypeStr );
02989 if ( mimetype->name() == "application/octet-stream" ) {
02990
02991 mimetype = KMimeType::findByPath( mAtmName, 0, true );
02992 }
02993 if ( ( mimetype->name() == "application/octet-stream" )
02994 && msgPart.isComplete() ) {
02995
02996
02997 mimetype = KMimeType::findByFileContent( mAtmName );
02998 }
02999 return KServiceTypeProfile::preferredService( mimetype->name(), "Application" );
03000 }
03001
03002 void KMHandleAttachmentCommand::atmOpen()
03003 {
03004 if ( !mOffer )
03005 mOffer = getServiceOffer();
03006 if ( !mOffer ) {
03007 kdDebug(5006) << k_funcinfo << "got no offer" << endl;
03008 return;
03009 }
03010
03011 KURL::List lst;
03012 KURL url;
03013 bool autoDelete = true;
03014 QString fname = createAtmFileLink();
03015
03016 if ( fname.isNull() ) {
03017 autoDelete = false;
03018 fname = mAtmName;
03019 }
03020
03021 url.setPath( fname );
03022 lst.append( url );
03023 if ( (KRun::run( *mOffer, lst, autoDelete ) <= 0) && autoDelete ) {
03024 QFile::remove(url.path());
03025 }
03026 }
03027
03028 void KMHandleAttachmentCommand::atmOpenWith()
03029 {
03030 KURL::List lst;
03031 KURL url;
03032 bool autoDelete = true;
03033 QString fname = createAtmFileLink();
03034
03035 if ( fname.isNull() ) {
03036 autoDelete = false;
03037 fname = mAtmName;
03038 }
03039
03040 url.setPath( fname );
03041 lst.append( url );
03042 if ( (! KRun::displayOpenWithDialog(lst, autoDelete)) && autoDelete ) {
03043 QFile::remove( url.path() );
03044 }
03045 }
03046
03047 void KMHandleAttachmentCommand::atmView()
03048 {
03049
03050 emit showAttachment( mAtmId, mAtmName );
03051 }
03052
03053 void KMHandleAttachmentCommand::atmSave()
03054 {
03055 QPtrList<partNode> parts;
03056 parts.append( mNode );
03057
03058 KMSaveAttachmentsCommand *command =
03059 new KMSaveAttachmentsCommand( 0, parts, mMsg, false );
03060 command->start();
03061 }
03062
03063 void KMHandleAttachmentCommand::atmProperties()
03064 {
03065 KMMsgPartDialogCompat dlg( parentWidget() , 0, true );
03066 KMMessagePart& msgPart = mNode->msgPart();
03067 dlg.setMsgPart( &msgPart );
03068 dlg.exec();
03069 }
03070
03071 void KMHandleAttachmentCommand::atmEncryptWithChiasmus()
03072 {
03073 const partNode * node = mNode;
03074 Q_ASSERT( node );
03075 if ( !node )
03076 return;
03077
03078
03079 if ( !mAtmName.endsWith( ".xia", false ) )
03080 return;
03081
03082 const Kleo::CryptoBackend::Protocol * chiasmus =
03083 Kleo::CryptoBackendFactory::instance()->protocol( "Chiasmus" );
03084 Q_ASSERT( chiasmus );
03085 if ( !chiasmus )
03086 return;
03087
03088 const STD_NAMESPACE_PREFIX auto_ptr<Kleo::SpecialJob> listjob( chiasmus->specialJob( "x-obtain-keys", QMap<QString,QVariant>() ) );
03089 if ( !listjob.get() ) {
03090 const QString msg = i18n( "Chiasmus backend does not offer the "
03091 "\"x-obtain-keys\" function. Please report this bug." );
03092 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03093 return;
03094 }
03095
03096 if ( listjob->exec() ) {
03097 listjob->showErrorDialog( parentWidget(), i18n( "Chiasmus Backend Error" ) );
03098 return;
03099 }
03100
03101 const QVariant result = listjob->property( "result" );
03102 if ( result.type() != QVariant::StringList ) {
03103 const QString msg = i18n( "Unexpected return value from Chiasmus backend: "
03104 "The \"x-obtain-keys\" function did not return a "
03105 "string list. Please report this bug." );
03106 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03107 return;
03108 }
03109
03110 const QStringList keys = result.toStringList();
03111 if ( keys.empty() ) {
03112 const QString msg = i18n( "No keys have been found. Please check that a "
03113 "valid key path has been set in the Chiasmus "
03114 "configuration." );
03115 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03116 return;
03117 }
03118
03119 ChiasmusKeySelector selectorDlg( parentWidget(), i18n( "Chiasmus Decryption Key Selection" ),
03120 keys, GlobalSettings::chiasmusDecryptionKey(),
03121 GlobalSettings::chiasmusDecryptionOptions() );
03122 if ( selectorDlg.exec() != QDialog::Accepted )
03123 return;
03124
03125 GlobalSettings::setChiasmusDecryptionOptions( selectorDlg.options() );
03126 GlobalSettings::setChiasmusDecryptionKey( selectorDlg.key() );
03127 assert( !GlobalSettings::chiasmusDecryptionKey().isEmpty() );
03128
03129 Kleo::SpecialJob * job = chiasmus->specialJob( "x-decrypt", QMap<QString,QVariant>() );
03130 if ( !job ) {
03131 const QString msg = i18n( "Chiasmus backend does not offer the "
03132 "\"x-decrypt\" function. Please report this bug." );
03133 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03134 return;
03135 }
03136
03137 const QByteArray input = node->msgPart().bodyDecodedBinary();
03138
03139 if ( !job->setProperty( "key", GlobalSettings::chiasmusDecryptionKey() ) ||
03140 !job->setProperty( "options", GlobalSettings::chiasmusDecryptionOptions() ) ||
03141 !job->setProperty( "input", input ) ) {
03142 const QString msg = i18n( "The \"x-decrypt\" function does not accept "
03143 "the expected parameters. Please report this bug." );
03144 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03145 return;
03146 }
03147
03148 setDeletesItself( true );
03149 if ( job->start() ) {
03150 job->showErrorDialog( parentWidget(), i18n( "Chiasmus Decryption Error" ) );
03151 return;
03152 }
03153
03154 mJob = job;
03155 connect( job, SIGNAL(result(const GpgME::Error&,const QVariant&)),
03156 this, SLOT(slotAtmDecryptWithChiasmusResult(const GpgME::Error&,const QVariant&)) );
03157 }
03158
03159
03160 static bool checkOverwrite( const KURL& url, bool& overwrite, QWidget* w )
03161 {
03162 if ( KIO::NetAccess::exists( url, false , w ) ) {
03163 if ( KMessageBox::Cancel ==
03164 KMessageBox::warningContinueCancel(
03165 w,
03166 i18n( "A file named \"%1\" already exists. "
03167 "Are you sure you want to overwrite it?" ).arg( url.prettyURL() ),
03168 i18n( "Overwrite File?" ),
03169 i18n( "&Overwrite" ) ) )
03170 return false;
03171 overwrite = true;
03172 }
03173 return true;
03174 }
03175
03176 static const QString chomp( const QString & base, const QString & suffix, bool cs ) {
03177 return base.endsWith( suffix, cs ) ? base.left( base.length() - suffix.length() ) : base ;
03178 }
03179
03180 void KMHandleAttachmentCommand::slotAtmDecryptWithChiasmusResult( const GpgME::Error & err, const QVariant & result )
03181 {
03182 LaterDeleterWithCommandCompletion d( this );
03183 if ( !mJob )
03184 return;
03185 Q_ASSERT( mJob == sender() );
03186 if ( mJob != sender() )
03187 return;
03188 Kleo::Job * job = mJob;
03189 mJob = 0;
03190 if ( err.isCanceled() )
03191 return;
03192 if ( err ) {
03193 job->showErrorDialog( parentWidget(), i18n( "Chiasmus Decryption Error" ) );
03194 return;
03195 }
03196
03197 if ( result.type() != QVariant::ByteArray ) {
03198 const QString msg = i18n( "Unexpected return value from Chiasmus backend: "
03199 "The \"x-decrypt\" function did not return a "
03200 "byte array. Please report this bug." );
03201 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03202 return;
03203 }
03204
03205 const KURL url = KFileDialog::getSaveURL( chomp( mAtmName, ".xia", false ), QString::null, parentWidget() );
03206 if ( url.isEmpty() )
03207 return;
03208
03209 bool overwrite = false;
03210 if ( !checkOverwrite( url, overwrite, parentWidget() ) )
03211 return;
03212
03213 d.setDisabled( true );
03214 KIO::Job * uploadJob = KIO::storedPut( result.toByteArray(), url, -1, overwrite, false );
03215 uploadJob->setWindow( parentWidget() );
03216 connect( uploadJob, SIGNAL(result(KIO::Job*)),
03217 this, SLOT(slotAtmDecryptWithChiasmusUploadResult(KIO::Job*)) );
03218 }
03219
03220 void KMHandleAttachmentCommand::slotAtmDecryptWithChiasmusUploadResult( KIO::Job * job )
03221 {
03222 if ( job->error() )
03223 job->showErrorDialog();
03224 LaterDeleterWithCommandCompletion d( this );
03225 d.setResult( OK );
03226 }
03227
03228 #include "kmcommands.moc"