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