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