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