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