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