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