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