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