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