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