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