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