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()->isMessage()) &&
00239 (mMsgList.getFirst()->parent() == 0))
00240 {
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 ) {
02385 KMMsgBase *msg = srcFolder->getMsgBase( idx );
02386 srcFolder->open("kmcommand");
02387 mOpenedFolders.push_back( srcFolder );
02388 addMsg( msg );
02389 }
02390 setDestFolder( findTrashFolder( srcFolder ) );
02391 }
02392
02393 KMFolder * KMDeleteMsgCommand::findTrashFolder( KMFolder * folder )
02394 {
02395 KMFolder* trash = folder->trashFolder();
02396 if( !trash )
02397 trash = kmkernel->trashFolder();
02398 if( trash != folder )
02399 return trash;
02400 return 0;
02401 }
02402
02403
02404 KMUrlClickedCommand::KMUrlClickedCommand( const KURL &url, uint identity,
02405 KMReaderWin *readerWin, bool htmlPref, KMMainWidget *mainWidget )
02406 :mUrl( url ), mIdentity( identity ), mReaderWin( readerWin ),
02407 mHtmlPref( htmlPref ), mMainWidget( mainWidget )
02408 {
02409 }
02410
02411 KMCommand::Result KMUrlClickedCommand::execute()
02412 {
02413 KMMessage* msg;
02414
02415 if (mUrl.protocol() == "mailto")
02416 {
02417 msg = new KMMessage;
02418 msg->initHeader(mIdentity);
02419 msg->setCharset("utf-8");
02420 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
02421 QString query=mUrl.query();
02422 while (!query.isEmpty()) {
02423 QString queryPart;
02424 int secondQuery = query.find('?',1);
02425 if (secondQuery != -1)
02426 queryPart = query.left(secondQuery);
02427 else
02428 queryPart = query;
02429 query = query.mid(queryPart.length());
02430
02431 if (queryPart.left(9) == "?subject=")
02432 msg->setSubject( KURL::decode_string(queryPart.mid(9)) );
02433 else if (queryPart.left(6) == "?body=")
02434
02435
02436 msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() );
02437 else if (queryPart.left(4) == "?cc=")
02438 msg->setCc( KURL::decode_string(queryPart.mid(4)) );
02439 }
02440
02441 KMail::Composer * win = KMail::makeComposer( msg, mIdentity );
02442 win->setCharset("", true);
02443 win->show();
02444 }
02445 else if ( mUrl.protocol() == "im" )
02446 {
02447 kmkernel->imProxy()->chatWithContact( mUrl.path() );
02448 }
02449 else if ((mUrl.protocol() == "http") || (mUrl.protocol() == "https") ||
02450 (mUrl.protocol() == "ftp") || (mUrl.protocol() == "file") ||
02451 (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
02452 (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
02453 (mUrl.protocol() == "smb") || (mUrl.protocol() == "fish") ||
02454 (mUrl.protocol() == "news"))
02455 {
02456 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n("Opening URL..."));
02457 KMimeType::Ptr mime = KMimeType::findByURL( mUrl );
02458 if (mime->name() == "application/x-desktop" ||
02459 mime->name() == "application/x-executable" ||
02460 mime->name() == "application/x-msdos-program" ||
02461 mime->name() == "application/x-shellscript" )
02462 {
02463 if (KMessageBox::warningYesNo( 0, i18n( "<qt>Do you really want to execute <b>%1</b>?</qt>" )
02464 .arg( mUrl.prettyURL() ), QString::null, i18n("Execute"), KStdGuiItem::cancel() ) != KMessageBox::Yes)
02465 return Canceled;
02466 }
02467 KRun * runner = new KRun( mUrl );
02468 runner->setRunExecutables( false );
02469 }
02470 else
02471 return Failed;
02472
02473 return OK;
02474 }
02475
02476 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, KMMessage *msg )
02477 : KMCommand( parent, msg ), mImplicitAttachments( true ), mEncoded( false )
02478 {
02479 }
02480
02481 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, const QPtrList<KMMsgBase>& msgs )
02482 : KMCommand( parent, msgs ), mImplicitAttachments( true ), mEncoded( false )
02483 {
02484 }
02485
02486 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, QPtrList<partNode>& attachments,
02487 KMMessage *msg, bool encoded )
02488 : KMCommand( parent ), mImplicitAttachments( false ), mEncoded( encoded )
02489 {
02490 for ( QPtrListIterator<partNode> it( attachments ); it.current(); ++it ) {
02491 mAttachmentMap.insert( it.current(), msg );
02492 }
02493 }
02494
02495 KMCommand::Result KMSaveAttachmentsCommand::execute()
02496 {
02497 setEmitsCompletedItself( true );
02498 if ( mImplicitAttachments ) {
02499 QPtrList<KMMessage> msgList = retrievedMsgs();
02500 KMMessage *msg;
02501 for ( QPtrListIterator<KMMessage> itr( msgList );
02502 ( msg = itr.current() );
02503 ++itr ) {
02504 partNode *rootNode = partNode::fromMessage( msg );
02505 for ( partNode *child = rootNode; child;
02506 child = child->firstChild() ) {
02507 for ( partNode *node = child; node; node = node->nextSibling() ) {
02508 if ( node->type() != DwMime::kTypeMultipart )
02509 mAttachmentMap.insert( node, msg );
02510 }
02511 }
02512 }
02513 }
02514 setDeletesItself( true );
02515
02516 KMLoadPartsCommand *command = new KMLoadPartsCommand( mAttachmentMap );
02517 connect( command, SIGNAL( partsRetrieved() ),
02518 this, SLOT( slotSaveAll() ) );
02519 command->start();
02520
02521 return OK;
02522 }
02523
02524 void KMSaveAttachmentsCommand::slotSaveAll()
02525 {
02526
02527
02528
02529 if ( mImplicitAttachments ) {
02530 for ( PartNodeMessageMap::iterator it = mAttachmentMap.begin();
02531 it != mAttachmentMap.end(); ) {
02532
02533
02534
02535 if ( it.key()->msgPart().fileName().stripWhiteSpace().isEmpty() &&
02536 ( it.key()->msgPart().name().stripWhiteSpace().isEmpty() ||
02537 !it.key()->parentNode() ) ) {
02538 PartNodeMessageMap::iterator delIt = it;
02539 ++it;
02540 mAttachmentMap.remove( delIt );
02541 }
02542 else
02543 ++it;
02544 }
02545 if ( mAttachmentMap.isEmpty() ) {
02546 KMessageBox::information( 0, i18n("Found no attachments to save.") );
02547 setResult( OK );
02548 emit completed( this );
02549 deleteLater();
02550 return;
02551 }
02552 }
02553
02554 KURL url, dirUrl;
02555 if ( mAttachmentMap.count() > 1 ) {
02556
02557 dirUrl = KDirSelectDialog::selectDirectory( QString::null, false,
02558 parentWidget(),
02559 i18n("Save Attachments To") );
02560 if ( !dirUrl.isValid() ) {
02561 setResult( Canceled );
02562 emit completed( this );
02563 deleteLater();
02564 return;
02565 }
02566
02567
02568 dirUrl.adjustPath( 1 );
02569 }
02570 else {
02571
02572 partNode *node = mAttachmentMap.begin().key();
02573
02574 QString s =
02575 node->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02576 if ( s.isEmpty() )
02577 s = node->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02578 if ( s.isEmpty() )
02579 s = i18n("filename for an unnamed attachment", "attachment.1");
02580 url = KFileDialog::getSaveURL( s, QString::null, parentWidget(),
02581 QString::null );
02582 if ( url.isEmpty() ) {
02583 setResult( Canceled );
02584 emit completed( this );
02585 deleteLater();
02586 return;
02587 }
02588 }
02589
02590 QMap< QString, int > renameNumbering;
02591
02592 Result globalResult = OK;
02593 int unnamedAtmCount = 0;
02594 for ( PartNodeMessageMap::const_iterator it = mAttachmentMap.begin();
02595 it != mAttachmentMap.end();
02596 ++it ) {
02597 KURL curUrl;
02598 if ( !dirUrl.isEmpty() ) {
02599 curUrl = dirUrl;
02600 QString s =
02601 it.key()->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02602 if ( s.isEmpty() )
02603 s = it.key()->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02604 if ( s.isEmpty() ) {
02605 ++unnamedAtmCount;
02606 s = i18n("filename for the %1-th unnamed attachment",
02607 "attachment.%1")
02608 .arg( unnamedAtmCount );
02609 }
02610 curUrl.setFileName( s );
02611 } else {
02612 curUrl = url;
02613 }
02614
02615 if ( !curUrl.isEmpty() ) {
02616
02617
02618
02619 QString origFile = curUrl.fileName();
02620 QString file = origFile;
02621
02622 while ( renameNumbering.contains(file) ) {
02623 file = origFile;
02624 int num = renameNumbering[file] + 1;
02625 int dotIdx = file.findRev('.');
02626 file = file.insert( (dotIdx>=0) ? dotIdx : file.length(), QString("_") + QString::number(num) );
02627 }
02628 curUrl.setFileName(file);
02629
02630
02631 if ( !renameNumbering.contains(origFile))
02632 renameNumbering[origFile] = 1;
02633 else
02634 renameNumbering[origFile]++;
02635
02636 if ( file != origFile ) {
02637 if ( !renameNumbering.contains(file))
02638 renameNumbering[file] = 1;
02639 else
02640 renameNumbering[file]++;
02641 }
02642
02643
02644 if ( KIO::NetAccess::exists( curUrl, false, parentWidget() ) ) {
02645 if ( KMessageBox::warningContinueCancel( parentWidget(),
02646 i18n( "A file named %1 already exists. Do you want to overwrite it?" )
02647 .arg( curUrl.fileName() ),
02648 i18n( "File Already Exists" ), i18n("&Overwrite") ) == KMessageBox::Cancel) {
02649 continue;
02650 }
02651 }
02652
02653 const Result result = saveItem( it.key(), curUrl );
02654 if ( result != OK )
02655 globalResult = result;
02656 }
02657 }
02658 setResult( globalResult );
02659 emit completed( this );
02660 deleteLater();
02661 }
02662
02663 KMCommand::Result KMSaveAttachmentsCommand::saveItem( partNode *node,
02664 const KURL& url )
02665 {
02666 bool bSaveEncrypted = false;
02667 bool bEncryptedParts = node->encryptionState() != KMMsgNotEncrypted;
02668 if( bEncryptedParts )
02669 if( KMessageBox::questionYesNo( parentWidget(),
02670 i18n( "The part %1 of the message is encrypted. Do you want to keep the encryption when saving?" ).
02671 arg( url.fileName() ),
02672 i18n( "KMail Question" ), i18n("Keep Encryption"), i18n("Do Not Keep") ) ==
02673 KMessageBox::Yes )
02674 bSaveEncrypted = true;
02675
02676 bool bSaveWithSig = true;
02677 if( node->signatureState() != KMMsgNotSigned )
02678 if( KMessageBox::questionYesNo( parentWidget(),
02679 i18n( "The part %1 of the message is signed. Do you want to keep the signature when saving?" ).
02680 arg( url.fileName() ),
02681 i18n( "KMail Question" ), i18n("Keep Signature"), i18n("Do Not Keep") ) !=
02682 KMessageBox::Yes )
02683 bSaveWithSig = false;
02684
02685 QByteArray data;
02686 if ( mEncoded )
02687 {
02688
02689
02690 data = KMail::Util::ByteArray( node->msgPart().dwBody() );
02691 }
02692 else
02693 {
02694 if( bSaveEncrypted || !bEncryptedParts) {
02695 partNode *dataNode = node;
02696 QCString rawReplyString;
02697 bool gotRawReplyString = false;
02698 if( !bSaveWithSig ) {
02699 if( DwMime::kTypeMultipart == node->type() &&
02700 DwMime::kSubtypeSigned == node->subType() ){
02701
02702 if( node->findType( DwMime::kTypeApplication,
02703 DwMime::kSubtypePgpSignature,
02704 true, false ) ){
02705 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02706 DwMime::kSubtypePgpSignature,
02707 true, false );
02708 }else if( node->findType( DwMime::kTypeApplication,
02709 DwMime::kSubtypePkcs7Mime,
02710 true, false ) ){
02711 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02712 DwMime::kSubtypePkcs7Mime,
02713 true, false );
02714 }else{
02715 dataNode = node->findTypeNot( DwMime::kTypeMultipart,
02716 DwMime::kSubtypeUnknown,
02717 true, false );
02718 }
02719 }else{
02720 ObjectTreeParser otp( 0, 0, false, false, false );
02721
02722
02723 dataNode->setProcessed( false, true );
02724 otp.parseObjectTree( dataNode );
02725
02726 rawReplyString = otp.rawReplyString();
02727 gotRawReplyString = true;
02728 }
02729 }
02730 QByteArray cstr = gotRawReplyString
02731 ? rawReplyString
02732 : dataNode->msgPart().bodyDecodedBinary();
02733 data = cstr;
02734 size_t size = cstr.size();
02735 if ( dataNode->msgPart().type() == DwMime::kTypeText ) {
02736
02737 size = KMail::Util::crlf2lf( cstr.data(), size );
02738 }
02739 data.resize( size );
02740 }
02741 }
02742 QDataStream ds;
02743 QFile file;
02744 KTempFile tf;
02745 tf.setAutoDelete( true );
02746 if ( url.isLocalFile() )
02747 {
02748
02749 file.setName( url.path() );
02750 if ( !file.open( IO_WriteOnly ) )
02751 {
02752 KMessageBox::error( parentWidget(),
02753 i18n( "%2 is detailed error description",
02754 "Could not write the file %1:\n%2" )
02755 .arg( file.name() )
02756 .arg( QString::fromLocal8Bit( strerror( errno ) ) ),
02757 i18n( "KMail Error" ) );
02758 return Failed;
02759 }
02760
02761
02762 if ( GlobalSettings::self()->disregardUmask() )
02763 fchmod( file.handle(), S_IRUSR | S_IWUSR );
02764
02765 ds.setDevice( &file );
02766 } else
02767 {
02768
02769 ds.setDevice( tf.file() );
02770 }
02771
02772 ds.writeRawBytes( data.data(), data.size() );
02773 if ( !url.isLocalFile() )
02774 {
02775 tf.close();
02776 if ( !KIO::NetAccess::upload( tf.name(), url, parentWidget() ) )
02777 {
02778 KMessageBox::error( parentWidget(),
02779 i18n( "Could not write the file %1." )
02780 .arg( url.path() ),
02781 i18n( "KMail Error" ) );
02782 return Failed;
02783 }
02784 } else
02785 file.close();
02786 return OK;
02787 }
02788
02789 KMLoadPartsCommand::KMLoadPartsCommand( QPtrList<partNode>& parts, KMMessage *msg )
02790 : mNeedsRetrieval( 0 )
02791 {
02792 for ( QPtrListIterator<partNode> it( parts ); it.current(); ++it ) {
02793 mPartMap.insert( it.current(), msg );
02794 }
02795 }
02796
02797 KMLoadPartsCommand::KMLoadPartsCommand( partNode *node, KMMessage *msg )
02798 : mNeedsRetrieval( 0 )
02799 {
02800 mPartMap.insert( node, msg );
02801 }
02802
02803 KMLoadPartsCommand::KMLoadPartsCommand( PartNodeMessageMap& partMap )
02804 : mNeedsRetrieval( 0 ), mPartMap( partMap )
02805 {
02806 }
02807
02808 void KMLoadPartsCommand::slotStart()
02809 {
02810 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02811 it != mPartMap.end();
02812 ++it ) {
02813 if ( !it.key()->msgPart().isComplete() &&
02814 !it.key()->msgPart().partSpecifier().isEmpty() ) {
02815
02816 ++mNeedsRetrieval;
02817 KMFolder* curFolder = it.data()->parent();
02818 if ( curFolder ) {
02819 FolderJob *job =
02820 curFolder->createJob( it.data(), FolderJob::tGetMessage,
02821 0, it.key()->msgPart().partSpecifier() );
02822 job->setCancellable( false );
02823 connect( job, SIGNAL(messageUpdated(KMMessage*, QString)),
02824 this, SLOT(slotPartRetrieved(KMMessage*, QString)) );
02825 job->start();
02826 } else
02827 kdWarning(5006) << "KMLoadPartsCommand - msg has no parent" << endl;
02828 }
02829 }
02830 if ( mNeedsRetrieval == 0 )
02831 execute();
02832 }
02833
02834 void KMLoadPartsCommand::slotPartRetrieved( KMMessage *msg,
02835 QString partSpecifier )
02836 {
02837 DwBodyPart *part =
02838 msg->findDwBodyPart( msg->getFirstDwBodyPart(), partSpecifier );
02839 if ( part ) {
02840
02841 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02842 it != mPartMap.end();
02843 ++it ) {
02844 if ( it.key()->dwPart()->partId() == part->partId() )
02845 it.key()->setDwPart( part );
02846 }
02847 } else
02848 kdWarning(5006) << "KMLoadPartsCommand::slotPartRetrieved - could not find bodypart!" << endl;
02849 --mNeedsRetrieval;
02850 if ( mNeedsRetrieval == 0 )
02851 execute();
02852 }
02853
02854 KMCommand::Result KMLoadPartsCommand::execute()
02855 {
02856 emit partsRetrieved();
02857 setResult( OK );
02858 emit completed( this );
02859 deleteLater();
02860 return OK;
02861 }
02862
02863 KMResendMessageCommand::KMResendMessageCommand( QWidget *parent,
02864 KMMessage *msg )
02865 :KMCommand( parent, msg )
02866 {
02867 }
02868
02869 KMCommand::Result KMResendMessageCommand::execute()
02870 {
02871 KMMessage *msg = retrievedMessage();
02872 if ( !msg || !msg->codec() ) {
02873 return Failed;
02874 }
02875 KMMessage *newMsg = new KMMessage(*msg);
02876
02877 QStringList whiteList;
02878 whiteList << "To" << "Cc" << "Bcc" << "Subject";
02879 newMsg->sanitizeHeaders( whiteList );
02880
02881 newMsg->setCharset(msg->codec()->mimeName());
02882 newMsg->setParent( 0 );
02883
02884
02885 newMsg->setHeaderField("X-KMail-Identity", QString::number( newMsg->identityUoid() ));
02886 newMsg->applyIdentity( newMsg->identityUoid() );
02887
02888 KMail::Composer * win = KMail::makeComposer();
02889 win->setMsg(newMsg, false, true);
02890 win->show();
02891
02892 return OK;
02893 }
02894
02895 KMMailingListCommand::KMMailingListCommand( QWidget *parent, KMFolder *folder )
02896 : KMCommand( parent ), mFolder( folder )
02897 {
02898 }
02899
02900 KMCommand::Result KMMailingListCommand::execute()
02901 {
02902 KURL::List lst = urls();
02903 QString handler = ( mFolder->mailingList().handler() == MailingList::KMail )
02904 ? "mailto" : "https";
02905
02906 KMCommand *command = 0;
02907 for ( KURL::List::Iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
02908 if ( handler == (*itr).protocol() ) {
02909 command = new KMUrlClickedCommand( *itr, mFolder->identity(), 0, false );
02910 }
02911 }
02912 if ( !command && !lst.empty() ) {
02913 command =
02914 new KMUrlClickedCommand( lst.first(), mFolder->identity(), 0, false );
02915 }
02916 if ( command ) {
02917 connect( command, SIGNAL( completed( KMCommand * ) ),
02918 this, SLOT( commandCompleted( KMCommand * ) ) );
02919 setDeletesItself( true );
02920 setEmitsCompletedItself( true );
02921 command->start();
02922 return OK;
02923 }
02924 return Failed;
02925 }
02926
02927 void KMMailingListCommand::commandCompleted( KMCommand *command )
02928 {
02929 setResult( command->result() );
02930 emit completed( this );
02931 deleteLater();
02932 }
02933
02934 KMMailingListPostCommand::KMMailingListPostCommand( QWidget *parent, KMFolder *folder )
02935 : KMMailingListCommand( parent, folder )
02936 {
02937 }
02938 KURL::List KMMailingListPostCommand::urls() const
02939 {
02940 return mFolder->mailingList().postURLS();
02941 }
02942
02943 KMMailingListSubscribeCommand::KMMailingListSubscribeCommand( QWidget *parent, KMFolder *folder )
02944 : KMMailingListCommand( parent, folder )
02945 {
02946 }
02947 KURL::List KMMailingListSubscribeCommand::urls() const
02948 {
02949 return mFolder->mailingList().subscribeURLS();
02950 }
02951
02952 KMMailingListUnsubscribeCommand::KMMailingListUnsubscribeCommand( QWidget *parent, KMFolder *folder )
02953 : KMMailingListCommand( parent, folder )
02954 {
02955 }
02956 KURL::List KMMailingListUnsubscribeCommand::urls() const
02957 {
02958 return mFolder->mailingList().unsubscribeURLS();
02959 }
02960
02961 KMMailingListArchivesCommand::KMMailingListArchivesCommand( QWidget *parent, KMFolder *folder )
02962 : KMMailingListCommand( parent, folder )
02963 {
02964 }
02965 KURL::List KMMailingListArchivesCommand::urls() const
02966 {
02967 return mFolder->mailingList().archiveURLS();
02968 }
02969
02970 KMMailingListHelpCommand::KMMailingListHelpCommand( QWidget *parent, KMFolder *folder )
02971 : KMMailingListCommand( parent, folder )
02972 {
02973 }
02974 KURL::List KMMailingListHelpCommand::urls() const
02975 {
02976 return mFolder->mailingList().helpURLS();
02977 }
02978
02979 KMIMChatCommand::KMIMChatCommand( const KURL &url, KMMessage *msg )
02980 :mUrl( url ), mMessage( msg )
02981 {
02982 }
02983
02984 KMCommand::Result KMIMChatCommand::execute()
02985 {
02986 kdDebug( 5006 ) << k_funcinfo << " URL is: " << mUrl << endl;
02987 QString addr = KMMessage::decodeMailtoUrl( mUrl.path() );
02988
02989 KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
02990 KABC::AddresseeList addressees = addressBook->findByEmail( KPIM::getEmailAddress( addr ) ) ;
02991
02992
02993 if( addressees.count() == 1 ) {
02994 kmkernel->imProxy()->chatWithContact( addressees[0].uid() );
02995 return OK;
02996 }
02997 else
02998 {
02999 kdDebug( 5006 ) << "Didn't find exactly one addressee, couldn't tell who to chat to for that email address. Count = " << addressees.count() << endl;
03000
03001 QString apology;
03002 if ( addressees.isEmpty() )
03003 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." );
03004 else
03005 {
03006 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." );
03007 QStringList nameList;
03008 KABC::AddresseeList::const_iterator it = addressees.begin();
03009 KABC::AddresseeList::const_iterator end = addressees.end();
03010 for ( ; it != end; ++it )
03011 {
03012 nameList.append( (*it).realName() );
03013 }
03014 QString names = nameList.join( QString::fromLatin1( ",\n" ) );
03015 apology = apology.arg( names );
03016 }
03017
03018 KMessageBox::sorry( parentWidget(), apology );
03019 return Failed;
03020 }
03021 }
03022
03023 KMHandleAttachmentCommand::KMHandleAttachmentCommand( partNode* node,
03024 KMMessage* msg, int atmId, const QString& atmName,
03025 AttachmentAction action, KService::Ptr offer, QWidget* parent )
03026 : KMCommand( parent ), mNode( node ), mMsg( msg ), mAtmId( atmId ), mAtmName( atmName ),
03027 mAction( action ), mOffer( offer ), mJob( 0 )
03028 {
03029 }
03030
03031 void KMHandleAttachmentCommand::slotStart()
03032 {
03033 if ( !mNode->msgPart().isComplete() )
03034 {
03035
03036 kdDebug(5006) << "load part" << endl;
03037 KMLoadPartsCommand *command = new KMLoadPartsCommand( mNode, mMsg );
03038 connect( command, SIGNAL( partsRetrieved() ),
03039 this, SLOT( slotPartComplete() ) );
03040 command->start();
03041 } else
03042 {
03043 execute();
03044 }
03045 }
03046
03047 void KMHandleAttachmentCommand::slotPartComplete()
03048 {
03049 execute();
03050 }
03051
03052 KMCommand::Result KMHandleAttachmentCommand::execute()
03053 {
03054 switch( mAction )
03055 {
03056 case Open:
03057 atmOpen();
03058 break;
03059 case OpenWith:
03060 atmOpenWith();
03061 break;
03062 case View:
03063 atmView();
03064 break;
03065 case Save:
03066 atmSave();
03067 break;
03068 case Properties:
03069 atmProperties();
03070 break;
03071 case ChiasmusEncrypt:
03072 atmEncryptWithChiasmus();
03073 return Undefined;
03074 break;
03075 default:
03076 kdDebug(5006) << "unknown action " << mAction << endl;
03077 break;
03078 }
03079 setResult( OK );
03080 emit completed( this );
03081 deleteLater();
03082 return OK;
03083 }
03084
03085 QString KMHandleAttachmentCommand::createAtmFileLink() const
03086 {
03087 QFileInfo atmFileInfo( mAtmName );
03088
03089 if ( atmFileInfo.size() == 0 )
03090 {
03091 kdDebug(5006) << k_funcinfo << "rewriting attachment" << endl;
03092
03093 QByteArray data = mNode->msgPart().bodyDecodedBinary();
03094 size_t size = data.size();
03095 if ( mNode->msgPart().type() == DwMime::kTypeText && size) {
03096
03097 size = KMail::Util::crlf2lf( data.data(), size );
03098 }
03099 KPIM::kBytesToFile( data.data(), size, mAtmName, false, false, false );
03100 }
03101
03102 KTempFile *linkFile = new KTempFile( locateLocal("tmp", atmFileInfo.fileName() +"_["),
03103 "]."+ atmFileInfo.extension() );
03104
03105 linkFile->setAutoDelete(true);
03106 QString linkName = linkFile->name();
03107 delete linkFile;
03108
03109 if ( ::link(QFile::encodeName( mAtmName ), QFile::encodeName( linkName )) == 0 ) {
03110 return linkName;
03111 }
03112 return QString::null;
03113 }
03114
03115 KService::Ptr KMHandleAttachmentCommand::getServiceOffer()
03116 {
03117 KMMessagePart& msgPart = mNode->msgPart();
03118 const QString contentTypeStr =
03119 ( msgPart.typeStr() + '/' + msgPart.subtypeStr() ).lower();
03120
03121 if ( contentTypeStr == "text/x-vcard" ) {
03122 atmView();
03123 return 0;
03124 }
03125
03126 KMimeType::Ptr mimetype;
03127
03128 mimetype = KMimeType::mimeType( contentTypeStr );
03129 if ( mimetype->name() == "application/octet-stream" ) {
03130
03131 mimetype = KMimeType::findByPath( mAtmName, 0, true );
03132 }
03133 if ( ( mimetype->name() == "application/octet-stream" )
03134 && msgPart.isComplete() ) {
03135
03136
03137 mimetype = KMimeType::findByFileContent( mAtmName );
03138 }
03139 return KServiceTypeProfile::preferredService( mimetype->name(), "Application" );
03140 }
03141
03142 void KMHandleAttachmentCommand::atmOpen()
03143 {
03144 if ( !mOffer )
03145 mOffer = getServiceOffer();
03146 if ( !mOffer ) {
03147 kdDebug(5006) << k_funcinfo << "got no offer" << endl;
03148 return;
03149 }
03150
03151 KURL::List lst;
03152 KURL url;
03153 bool autoDelete = true;
03154 QString fname = createAtmFileLink();
03155
03156 if ( fname.isNull() ) {
03157 autoDelete = false;
03158 fname = mAtmName;
03159 }
03160
03161 url.setPath( fname );
03162 lst.append( url );
03163 if ( (KRun::run( *mOffer, lst, autoDelete ) <= 0) && autoDelete ) {
03164 QFile::remove(url.path());
03165 }
03166 }
03167
03168 void KMHandleAttachmentCommand::atmOpenWith()
03169 {
03170 KURL::List lst;
03171 KURL url;
03172 bool autoDelete = true;
03173 QString fname = createAtmFileLink();
03174
03175 if ( fname.isNull() ) {
03176 autoDelete = false;
03177 fname = mAtmName;
03178 }
03179
03180 url.setPath( fname );
03181 lst.append( url );
03182 if ( (! KRun::displayOpenWithDialog(lst, autoDelete)) && autoDelete ) {
03183 QFile::remove( url.path() );
03184 }
03185 }
03186
03187 void KMHandleAttachmentCommand::atmView()
03188 {
03189
03190 emit showAttachment( mAtmId, mAtmName );
03191 }
03192
03193 void KMHandleAttachmentCommand::atmSave()
03194 {
03195 QPtrList<partNode> parts;
03196 parts.append( mNode );
03197
03198 KMSaveAttachmentsCommand *command =
03199 new KMSaveAttachmentsCommand( parentWidget(), parts, mMsg, false );
03200 command->start();
03201 }
03202
03203 void KMHandleAttachmentCommand::atmProperties()
03204 {
03205 KMMsgPartDialogCompat dlg( parentWidget() , 0, true );
03206 KMMessagePart& msgPart = mNode->msgPart();
03207 dlg.setMsgPart( &msgPart );
03208 dlg.exec();
03209 }
03210
03211 void KMHandleAttachmentCommand::atmEncryptWithChiasmus()
03212 {
03213 const partNode * node = mNode;
03214 Q_ASSERT( node );
03215 if ( !node )
03216 return;
03217
03218
03219 if ( !mAtmName.endsWith( ".xia", false ) )
03220 return;
03221
03222 const Kleo::CryptoBackend::Protocol * chiasmus =
03223 Kleo::CryptoBackendFactory::instance()->protocol( "Chiasmus" );
03224 Q_ASSERT( chiasmus );
03225 if ( !chiasmus )
03226 return;
03227
03228 const STD_NAMESPACE_PREFIX auto_ptr<Kleo::SpecialJob> listjob( chiasmus->specialJob( "x-obtain-keys", QMap<QString,QVariant>() ) );
03229 if ( !listjob.get() ) {
03230 const QString msg = i18n( "Chiasmus backend does not offer the "
03231 "\"x-obtain-keys\" function. Please report this bug." );
03232 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03233 return;
03234 }
03235
03236 if ( listjob->exec() ) {
03237 listjob->showErrorDialog( parentWidget(), i18n( "Chiasmus Backend Error" ) );
03238 return;
03239 }
03240
03241 const QVariant result = listjob->property( "result" );
03242 if ( result.type() != QVariant::StringList ) {
03243 const QString msg = i18n( "Unexpected return value from Chiasmus backend: "
03244 "The \"x-obtain-keys\" function did not return a "
03245 "string list. Please report this bug." );
03246 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03247 return;
03248 }
03249
03250 const QStringList keys = result.toStringList();
03251 if ( keys.empty() ) {
03252 const QString msg = i18n( "No keys have been found. Please check that a "
03253 "valid key path has been set in the Chiasmus "
03254 "configuration." );
03255 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03256 return;
03257 }
03258
03259 ChiasmusKeySelector selectorDlg( parentWidget(), i18n( "Chiasmus Decryption Key Selection" ),
03260 keys, GlobalSettings::chiasmusDecryptionKey(),
03261 GlobalSettings::chiasmusDecryptionOptions() );
03262 if ( selectorDlg.exec() != QDialog::Accepted )
03263 return;
03264
03265 GlobalSettings::setChiasmusDecryptionOptions( selectorDlg.options() );
03266 GlobalSettings::setChiasmusDecryptionKey( selectorDlg.key() );
03267 assert( !GlobalSettings::chiasmusDecryptionKey().isEmpty() );
03268
03269 Kleo::SpecialJob * job = chiasmus->specialJob( "x-decrypt", QMap<QString,QVariant>() );
03270 if ( !job ) {
03271 const QString msg = i18n( "Chiasmus backend does not offer the "
03272 "\"x-decrypt\" function. Please report this bug." );
03273 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03274 return;
03275 }
03276
03277 const QByteArray input = node->msgPart().bodyDecodedBinary();
03278
03279 if ( !job->setProperty( "key", GlobalSettings::chiasmusDecryptionKey() ) ||
03280 !job->setProperty( "options", GlobalSettings::chiasmusDecryptionOptions() ) ||
03281 !job->setProperty( "input", input ) ) {
03282 const QString msg = i18n( "The \"x-decrypt\" function does not accept "
03283 "the expected parameters. Please report this bug." );
03284 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03285 return;
03286 }
03287
03288 setDeletesItself( true );
03289 if ( job->start() ) {
03290 job->showErrorDialog( parentWidget(), i18n( "Chiasmus Decryption Error" ) );
03291 return;
03292 }
03293
03294 mJob = job;
03295 connect( job, SIGNAL(result(const GpgME::Error&,const QVariant&)),
03296 this, SLOT(slotAtmDecryptWithChiasmusResult(const GpgME::Error&,const QVariant&)) );
03297 }
03298
03299 static const QString chomp( const QString & base, const QString & suffix, bool cs ) {
03300 return base.endsWith( suffix, cs ) ? base.left( base.length() - suffix.length() ) : base ;
03301 }
03302
03303 void KMHandleAttachmentCommand::slotAtmDecryptWithChiasmusResult( const GpgME::Error & err, const QVariant & result )
03304 {
03305 LaterDeleterWithCommandCompletion d( this );
03306 if ( !mJob )
03307 return;
03308 Q_ASSERT( mJob == sender() );
03309 if ( mJob != sender() )
03310 return;
03311 Kleo::Job * job = mJob;
03312 mJob = 0;
03313 if ( err.isCanceled() )
03314 return;
03315 if ( err ) {
03316 job->showErrorDialog( parentWidget(), i18n( "Chiasmus Decryption Error" ) );
03317 return;
03318 }
03319
03320 if ( result.type() != QVariant::ByteArray ) {
03321 const QString msg = i18n( "Unexpected return value from Chiasmus backend: "
03322 "The \"x-decrypt\" function did not return a "
03323 "byte array. Please report this bug." );
03324 KMessageBox::error( parentWidget(), msg, i18n( "Chiasmus Backend Error" ) );
03325 return;
03326 }
03327
03328 const KURL url = KFileDialog::getSaveURL( chomp( mAtmName, ".xia", false ), QString::null, parentWidget() );
03329 if ( url.isEmpty() )
03330 return;
03331
03332 bool overwrite = KMail::Util::checkOverwrite( url, parentWidget() );
03333 if ( !overwrite )
03334 return;
03335
03336 d.setDisabled( true );
03337 KIO::Job * uploadJob = KIO::storedPut( result.toByteArray(), url, -1, overwrite, false );
03338 uploadJob->setWindow( parentWidget() );
03339 connect( uploadJob, SIGNAL(result(KIO::Job*)),
03340 this, SLOT(slotAtmDecryptWithChiasmusUploadResult(KIO::Job*)) );
03341 }
03342
03343 void KMHandleAttachmentCommand::slotAtmDecryptWithChiasmusUploadResult( KIO::Job * job )
03344 {
03345 if ( job->error() )
03346 job->showErrorDialog();
03347 LaterDeleterWithCommandCompletion d( this );
03348 d.setResult( OK );
03349 }
03350
03351
03352 AttachmentModifyCommand::AttachmentModifyCommand(partNode * node, KMMessage * msg, QWidget * parent) :
03353 KMCommand( parent, msg ),
03354 mPartIndex( node->nodeId() ),
03355 mSernum( 0 )
03356 {
03357 }
03358
03359 AttachmentModifyCommand::AttachmentModifyCommand( int nodeId, KMMessage *msg, QWidget *parent )
03360 : KMCommand( parent, msg ),
03361 mPartIndex( nodeId ),
03362 mSernum( 0 )
03363 {
03364 }
03365
03366 AttachmentModifyCommand::~ AttachmentModifyCommand()
03367 {
03368 }
03369
03370 KMCommand::Result AttachmentModifyCommand::execute()
03371 {
03372 KMMessage *msg = retrievedMessage();
03373 if ( !msg )
03374 return Failed;
03375 mSernum = msg->getMsgSerNum();
03376
03377 mFolder = msg->parent();
03378 if ( !mFolder || !mFolder->storage() )
03379 return Failed;
03380
03381 Result res = doAttachmentModify();
03382 if ( res != OK )
03383 return res;
03384
03385 setEmitsCompletedItself( true );
03386 setDeletesItself( true );
03387 return OK;
03388 }
03389
03390 void AttachmentModifyCommand::storeChangedMessage(KMMessage * msg)
03391 {
03392 if ( !mFolder || !mFolder->storage() ) {
03393 kdWarning(5006) << k_funcinfo << "We lost the folder!" << endl;
03394 setResult( Failed );
03395 emit completed( this );
03396 deleteLater();
03397 }
03398 int res = mFolder->addMsg( msg ) != 0;
03399 if ( mFolder->folderType() == KMFolderTypeImap ) {
03400 KMFolderImap *f = static_cast<KMFolderImap*>( mFolder->storage() );
03401 connect( f, SIGNAL(folderComplete(KMFolderImap*,bool)),
03402 SLOT(messageStoreResult(KMFolderImap*,bool)) );
03403 } else {
03404 messageStoreResult( 0, res == 0 );
03405 }
03406 }
03407
03408 void AttachmentModifyCommand::messageStoreResult(KMFolderImap* folder, bool success )
03409 {
03410 Q_UNUSED( folder );
03411 if ( success ) {
03412 KMCommand *delCmd = new KMDeleteMsgCommand( mSernum );
03413 connect( delCmd, SIGNAL(completed(KMCommand*)), SLOT(messageDeleteResult(KMCommand*)) );
03414 delCmd->start();
03415 return;
03416 }
03417 kdWarning(5006) << k_funcinfo << "Adding modified message failed." << endl;
03418 setResult( Failed );
03419 emit completed( this );
03420 deleteLater();
03421 }
03422
03423 void AttachmentModifyCommand::messageDeleteResult(KMCommand * cmd)
03424 {
03425 setResult( cmd->result() );
03426 emit completed( this );
03427 deleteLater();
03428 }
03429
03430 KMDeleteAttachmentCommand::KMDeleteAttachmentCommand(partNode * node, KMMessage * msg, QWidget * parent) :
03431 AttachmentModifyCommand( node, msg, parent )
03432 {
03433 kdDebug(5006) << k_funcinfo << endl;
03434 }
03435
03436 KMDeleteAttachmentCommand::KMDeleteAttachmentCommand( int nodeId, KMMessage *msg, QWidget *parent )
03437 : AttachmentModifyCommand( nodeId, msg, parent )
03438 {
03439 kdDebug(5006) << k_funcinfo << endl;
03440 }
03441
03442 KMDeleteAttachmentCommand::~KMDeleteAttachmentCommand()
03443 {
03444 kdDebug(5006) << k_funcinfo << endl;
03445 }
03446
03447 KMCommand::Result KMDeleteAttachmentCommand::doAttachmentModify()
03448 {
03449 KMMessage *msg = retrievedMessage();
03450 if ( !msg || !msg->deleteBodyPart( mPartIndex ) )
03451 return Failed;
03452
03453 KMMessage *newMsg = new KMMessage();
03454 newMsg->fromDwString( msg->asDwString() );
03455 newMsg->setStatus( msg->status() );
03456
03457 storeChangedMessage( newMsg );
03458 return OK;
03459 }
03460
03461
03462 KMEditAttachmentCommand::KMEditAttachmentCommand(partNode * node, KMMessage * msg, QWidget * parent) :
03463 AttachmentModifyCommand( node, msg, parent )
03464 {
03465 kdDebug(5006) << k_funcinfo << endl;
03466 mTempFile.setAutoDelete( true );
03467 }
03468
03469 KMEditAttachmentCommand::KMEditAttachmentCommand( int nodeId, KMMessage *msg, QWidget *parent )
03470 : AttachmentModifyCommand( nodeId, msg, parent )
03471 {
03472 kdDebug(5006) << k_funcinfo << endl;
03473 mTempFile.setAutoDelete( true );
03474 }
03475
03476 KMEditAttachmentCommand::~ KMEditAttachmentCommand()
03477 {
03478 }
03479
03480 KMCommand::Result KMEditAttachmentCommand::doAttachmentModify()
03481 {
03482 KMMessage *msg = retrievedMessage();
03483 if ( !msg )
03484 return Failed;
03485
03486 KMMessagePart part;
03487 DwBodyPart *dwpart = msg->findPart( mPartIndex );
03488 if ( !dwpart )
03489 return Failed;
03490 KMMessage::bodyPart( dwpart, &part, true );
03491 if ( !part.isComplete() )
03492 return Failed;
03493
03494 if( !dynamic_cast<DwBody*>( dwpart->Parent() ) )
03495 return Failed;
03496
03497 mTempFile.file()->writeBlock( part.bodyDecodedBinary() );
03498 mTempFile.file()->flush();
03499
03500 KMail::EditorWatcher *watcher =
03501 new KMail::EditorWatcher( KURL( mTempFile.file()->name() ),
03502 part.typeStr() + "/" + part.subtypeStr(),
03503 false, this, parentWidget() );
03504 connect( watcher, SIGNAL(editDone(KMail::EditorWatcher*)), SLOT(editDone(KMail::EditorWatcher*)) );
03505 if ( !watcher->start() )
03506 return Failed;
03507 setEmitsCompletedItself( true );
03508 setDeletesItself( true );
03509 return OK;
03510 }
03511
03512 void KMEditAttachmentCommand::editDone(KMail::EditorWatcher * watcher)
03513 {
03514 kdDebug(5006) << k_funcinfo << endl;
03515
03516 if ( !watcher->fileChanged() ) {
03517 kdDebug(5006) << k_funcinfo << "File has not been changed" << endl;
03518 setResult( Canceled );
03519 emit completed( this );
03520 deleteLater();
03521 }
03522
03523 mTempFile.file()->reset();
03524 QByteArray data = mTempFile.file()->readAll();
03525
03526
03527 KMMessage *msg = retrievedMessage();
03528 KMMessagePart part;
03529 DwBodyPart *dwpart = msg->findPart( mPartIndex );
03530 KMMessage::bodyPart( dwpart, &part, true );
03531
03532 DwBody *parentNode = dynamic_cast<DwBody*>( dwpart->Parent() );
03533 assert( parentNode );
03534 parentNode->RemoveBodyPart( dwpart );
03535
03536 KMMessagePart att;
03537 att.duplicate( part );
03538 att.setBodyEncodedBinary( data );
03539
03540 DwBodyPart* newDwPart = msg->createDWBodyPart( &att );
03541 parentNode->AddBodyPart( newDwPart );
03542 msg->getTopLevelPart()->Assemble();
03543
03544 KMMessage *newMsg = new KMMessage();
03545 newMsg->fromDwString( msg->asDwString() );
03546 newMsg->setStatus( msg->status() );
03547
03548 storeChangedMessage( newMsg );
03549 }
03550
03551
03552 CreateTodoCommand::CreateTodoCommand(QWidget * parent, KMMessage * msg)
03553 : KMCommand( parent, msg )
03554 {
03555 }
03556
03557 KMCommand::Result CreateTodoCommand::execute()
03558 {
03559 KMMessage *msg = retrievedMessage();
03560 if ( !msg || !msg->codec() ) {
03561 return Failed;
03562 }
03563
03564 KMail::KorgHelper::ensureRunning();
03565
03566 QString txt = i18n("From: %1\nTo: %2\nSubject: %3").arg( msg->from() )
03567 .arg( msg->to() ).arg( msg->subject() );
03568
03569 KTempFile tf;
03570 tf.setAutoDelete( true );
03571 QString uri = "kmail:" + QString::number( msg->getMsgSerNum() ) + "/" + msg->msgId();
03572 tf.file()->writeBlock( msg->asDwString().c_str(), msg->asDwString().length() );
03573 tf.close();
03574
03575 KCalendarIface_stub *iface = new KCalendarIface_stub( kapp->dcopClient(), "korganizer", "CalendarIface" );
03576 iface->openTodoEditor( i18n("Mail: %1").arg( msg->subject() ), txt, uri,
03577 tf.name(), QStringList(), "message/rfc822", true );
03578 delete iface;
03579
03580 return OK;
03581 }
03582
03583 #include "kmcommands.moc"