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