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